{"model_name":"deepseek-v4-pro-high","codes":{"1":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\nusing namespace chrono;\n\n// Fast random number generator\nstruct XorShift {\n    uint32_t x, y, z, w;\n    XorShift(uint32_t seed = 123456789) : x(seed), y(362436069), z(521288629), w(88675123) {\n        for (int i = 0; i < 10; i++) next();\n    }\n    uint32_t next() {\n        uint32_t t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = w ^ (w >> 19) ^ t ^ (t >> 8);\n    }\n    int nextInt(int max) {\n        if (max < 0) return 0;\n        return next() % (max + 1);\n    }\n    double nextDouble() {\n        return (double)(next() & 0xFFFFFF) / 0x1000000;\n    }\n};\n\nstruct Node {\n    int type;   // 0: leaf, 1: vertical cut, 2: horizontal cut\n    int leaf_id; // used when type == 0\n    int k;       // cut coordinate\n    int left, right;\n    int parent;\n    int min_k, max_k;   // allowed range for k\n    int x1, y1, x2, y2; // bounding box (computed during evaluation)\n    vector<int> ids;    // leaf indices in this subtree\n};\n\nint n;\nvector<int> x, y, r;\nvector<Node> nodes;\nint root;\nXorShift rng(system_clock::now().time_since_epoch().count());\n\n// Recursively build a slicing tree for the given points inside the given bounding box.\nint buildTree(const vector<int>& pts, int x1, int y1, int x2, int y2, int parent) {\n    if (pts.size() == 1) {\n        int id = pts[0];\n        nodes.push_back({0, id, 0, -1, -1, parent, 0, 0, 0, 0, 0, 0, {id}});\n        return nodes.size() - 1;\n    }\n\n    // Collect feasible splits\n    struct Split { vector<int> left, right; int L, R; };\n    vector<Split> v_splits, h_splits;\n\n    // Vertical splits\n    vector<int> sorted = pts;\n    sort(sorted.begin(), sorted.end(), [&](int a, int b) { return x[a] < x[b]; });\n    for (int i = 0; i < (int)sorted.size() - 1; i++) {\n        int left_max = x[sorted[i]];\n        int right_min = x[sorted[i + 1]];\n        int L = left_max + 1;\n        int R = right_min;\n        if (L <= R) {\n            vector<int> left_pts(sorted.begin(), sorted.begin() + i + 1);\n            vector<int> right_pts(sorted.begin() + i + 1, sorted.end());\n            v_splits.push_back({left_pts, right_pts, L, R});\n        }\n    }\n\n    // Horizontal splits\n    sort(sorted.begin(), sorted.end(), [&](int a, int b) { return y[a] < y[b]; });\n    for (int i = 0; i < (int)sorted.size() - 1; i++) {\n        int bottom_max = y[sorted[i]];\n        int top_min = y[sorted[i + 1]];\n        int L = bottom_max + 1;\n        int R = top_min;\n        if (L <= R) {\n            vector<int> left_pts(sorted.begin(), sorted.begin() + i + 1);\n            vector<int> right_pts(sorted.begin() + i + 1, sorted.end());\n            h_splits.push_back({left_pts, right_pts, L, R});\n        }\n    }\n\n    // Randomly choose orientation and split\n    int orient;\n    Split chosen;\n    if (!v_splits.empty() && !h_splits.empty()) {\n        if (rng.nextInt(1) == 0) {\n            orient = 1;\n            chosen = v_splits[rng.nextInt(v_splits.size() - 1)];\n        } else {\n            orient = 2;\n            chosen = h_splits[rng.nextInt(h_splits.size() - 1)];\n        }\n    } else if (!v_splits.empty()) {\n        orient = 1;\n        chosen = v_splits[rng.nextInt(v_splits.size() - 1)];\n    } else {\n        orient = 2;\n        chosen = h_splits[rng.nextInt(h_splits.size() - 1)];\n    }\n\n    int k = chosen.L + rng.nextInt(chosen.R - chosen.L);\n\n    // Create the internal node\n    nodes.push_back({orient, -1, k, -1, -1, parent, 0, 0, 0, 0, 0, 0, pts});\n    int idx = nodes.size() - 1;\n\n    int left_child, right_child;\n    if (orient == 1) {\n        left_child = buildTree(chosen.left, x1, y1, k, y2, idx);\n        right_child = buildTree(chosen.right, k, y1, x2, y2, idx);\n        int max_x_left = 0;\n        for (int id : chosen.left) max_x_left = max(max_x_left, x[id]);\n        int min_x_right = 10000;\n        for (int id : chosen.right) min_x_right = min(min_x_right, x[id]);\n        nodes[idx].min_k = max_x_left + 1;\n        nodes[idx].max_k = min_x_right;\n    } else {\n        left_child = buildTree(chosen.left, x1, y1, x2, k, idx);\n        right_child = buildTree(chosen.right, x1, k, x2, y2, idx);\n        int max_y_bottom = 0;\n        for (int id : chosen.left) max_y_bottom = max(max_y_bottom, y[id]);\n        int min_y_top = 10000;\n        for (int id : chosen.right) min_y_top = min(min_y_top, y[id]);\n        nodes[idx].min_k = max_y_bottom + 1;\n        nodes[idx].max_k = min_y_top;\n    }\n    nodes[idx].left = left_child;\n    nodes[idx].right = right_child;\n    return idx;\n}\n\n// Compute satisfaction sum and update bounding boxes of all active nodes\ndouble evaluate(int node_idx, int x1, int y1, int x2, int y2) {\n    Node& node = nodes[node_idx];\n    node.x1 = x1; node.y1 = y1; node.x2 = x2; node.y2 = y2;\n    if (node.type == 0) {\n        long long area = (long long)(x2 - x1) * (y2 - y1);\n        int target = r[node.leaf_id];\n        double ratio;\n        if (area <= target) ratio = (double)area / target;\n        else ratio = (double)target / area;\n        return 2.0 * ratio - ratio * ratio;\n    } else if (node.type == 1) {\n        int k = node.k;\n        double p1 = evaluate(node.left, x1, y1, k, y2);\n        double p2 = evaluate(node.right, k, y1, x2, y2);\n        return p1 + p2;\n    } else {\n        int k = node.k;\n        double p1 = evaluate(node.left, x1, y1, x2, k);\n        double p2 = evaluate(node.right, x1, k, x2, y2);\n        return p1 + p2;\n    }\n}\n\nvector<int> active_internal;\n\nvoid refreshActive() {\n    active_internal.clear();\n    function<void(int)> dfs = [&](int idx) {\n        if (nodes[idx].type != 0) {\n            active_internal.push_back(idx);\n            dfs(nodes[idx].left);\n            dfs(nodes[idx].right);\n        }\n    };\n    dfs(root);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n;\n    x.resize(n); y.resize(n); r.resize(n);\n    for (int i = 0; i < n; i++) cin >> x[i] >> y[i] >> r[i];\n\n    double global_best_score = -1e9;\n    vector<Node> global_best_nodes;\n    int global_best_root = -1;\n\n    auto start_time = steady_clock::now();\n    auto time_left = [&]() -> bool {\n        double elapsed = duration<double>(steady_clock::now() - start_time).count();\n        return elapsed > 4.5; // leave 0.5s for hill-climbing and output\n    };\n\n    // Multi-start SA with restarts\n    while (!time_left()) {\n        // Build a new random initial tree\n        nodes.clear();\n        vector<int> all_ids(n);\n        iota(all_ids.begin(), all_ids.end(), 0);\n        root = buildTree(all_ids, 0, 0, 10000, 10000, -1);\n        refreshActive();\n        double current_score = evaluate(root, 0, 0, 10000, 10000);\n        double best_restart_score = current_score;\n        vector<Node> best_restart_nodes = nodes;\n        int best_restart_root = root;\n\n        // Simulated annealing for this restart\n        int restart_iters = 150000;\n        double T_start = 10.0;\n        double T_end = 0.001;\n\n        for (int iter = 0; iter < restart_iters; iter++) {\n            if (iter % 1000 == 0 && time_left()) break;\n\n            double progress = (double)iter / restart_iters;\n            double T = T_start * pow(T_end / T_start, progress);\n\n            if (active_internal.empty()) break;\n            int idx = active_internal[rng.nextInt(active_internal.size() - 1)];\n            int old_k = nodes[idx].k;\n            int min_k = nodes[idx].min_k;\n            int max_k = nodes[idx].max_k;\n            if (min_k == max_k) continue;\n            int new_k = min_k + rng.nextInt(max_k - min_k);\n            if (new_k == old_k) continue;\n\n            nodes[idx].k = new_k;\n            double new_score = evaluate(root, 0, 0, 10000, 10000);\n            if (new_score > current_score || rng.nextDouble() < exp((new_score - current_score) / T)) {\n                current_score = new_score;\n                if (new_score > best_restart_score) {\n                    best_restart_score = new_score;\n                    best_restart_nodes = nodes;\n                    best_restart_root = root;\n                }\n            } else {\n                nodes[idx].k = old_k;\n                evaluate(root, 0, 0, 10000, 10000); // restore bounding boxes\n            }\n        }\n\n        if (best_restart_score > global_best_score) {\n            global_best_score = best_restart_score;\n            global_best_nodes = best_restart_nodes;\n            global_best_root = best_restart_root;\n        }\n    }\n\n    // Final polishing: one pass of full enumeration hill-climbing on the global best\n    nodes = global_best_nodes;\n    root = global_best_root;\n    refreshActive();\n    double current_score = evaluate(root, 0, 0, 10000, 10000);\n    vector<int> internals = active_internal;\n    for (int idx : internals) {\n        if (nodes[idx].min_k >= nodes[idx].max_k) continue;\n        int old_k = nodes[idx].k;\n        double best_local = current_score;\n        int best_k = old_k;\n        for (int k = nodes[idx].min_k; k <= nodes[idx].max_k; k++) {\n            if (k == old_k) continue;\n            nodes[idx].k = k;\n            double score = evaluate(root, 0, 0, 10000, 10000);\n            if (score > best_local) {\n                best_local = score;\n                best_k = k;\n            }\n        }\n        if (best_k != old_k) {\n            nodes[idx].k = best_k;\n            current_score = best_local;\n        } else {\n            nodes[idx].k = old_k;\n            evaluate(root, 0, 0, 10000, 10000);\n        }\n    }\n    // Update global best\n    global_best_score = current_score;\n    global_best_nodes = nodes;\n    global_best_root = root;\n\n    // Output the best layout\n    nodes = global_best_nodes;\n    root = global_best_root;\n    evaluate(root, 0, 0, 10000, 10000); // ensure boxes are consistent\n    vector<tuple<int, int, int, int>> ans(n);\n    function<void(int)> collect = [&](int idx) {\n        Node& node = nodes[idx];\n        if (node.type == 0) {\n            ans[node.leaf_id] = {node.x1, node.y1, node.x2, node.y2};\n        } else {\n            collect(node.left);\n            collect(node.right);\n        }\n    };\n    collect(root);\n    for (int i = 0; i < n; i++) {\n        auto [a, b, c, d] = ans[i];\n        cout << a << \" \" << b << \" \" << c << \" \" << d << \"\\n\";\n    }\n\n    return 0;\n}","ahc002":"#include <iostream>\n#include <vector>\n#include <bitset>\n#include <queue>\n#include <algorithm>\n#include <chrono>\n#include <numeric>\n#include <unordered_map>\n#include <string>\nusing namespace std;\n\nconstexpr int N = 50;\nconstexpr int MAX_TILES = 2500;\n\nstruct State {\n    int parent_id;\n    unsigned short current_tile;\n    int score;\n    bitset<MAX_TILES> visited;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj;\n    cin >> si >> sj;\n\n    vector t(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> t[i][j];\n\n    vector p(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> p[i][j];\n\n    // --- Compute tiles ---\n    int M = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (t[i][j] > M) M = t[i][j];\n    M += 1;\n\n    vector<vector<pair<int,int>>> tile_sq(M);\n    vector<int> tile_weight(M, 0);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int id = t[i][j];\n            tile_sq[id].push_back({i, j});\n            tile_weight[id] += p[i][j];\n        }\n    }\n\n    // --- Adjacency and exit squares ---\n    const int dirs[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};\n    vector<vector<int>> adj(M);\n    vector<unordered_map<int, pair<int,int>>> exit_sq(M);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = t[i][j];\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + dirs[d][0], nj = j + dirs[d][1];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                int v = t[ni][nj];\n                if (u != v) {\n                    adj[u].push_back(v);\n                    if (exit_sq[u].find(v) == exit_sq[u].end()) {\n                        exit_sq[u][v] = {i, j};\n                    }\n                }\n            }\n        }\n    }\n    for (int i = 0; i < M; ++i) {\n        sort(adj[i].begin(), adj[i].end());\n        adj[i].erase(unique(adj[i].begin(), adj[i].end()), adj[i].end());\n    }\n\n    // --- Beam search ---\n    int start_tile = t[si][sj];\n    vector<State> states;\n    states.reserve(2000000);\n    State init;\n    init.parent_id = -1;\n    init.current_tile = start_tile;\n    init.visited.reset();\n    init.visited.set(start_tile);\n    init.score = tile_weight[start_tile];\n    states.push_back(init);\n    vector<int> cur = {0};\n    int best_id = 0;\n\n    const int BEAM_WIDTH = 700;\n    auto start_time = chrono::steady_clock::now();\n\n    while (!cur.empty()) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - start_time).count() > 1950) break;\n        if (states.size() > 2000000) break;\n\n        vector<int> nxt_cand;\n        nxt_cand.reserve(cur.size() * 4);\n        for (int id : cur) {\n            const State& st = states[id];\n            unsigned short u = st.current_tile;\n            for (unsigned short v : adj[u]) {\n                if (!st.visited[v]) {\n                    State ns = st;\n                    ns.visited.set(v);\n                    ns.score += tile_weight[v];\n                    ns.current_tile = v;\n                    ns.parent_id = id;\n                    nxt_cand.push_back(states.size());\n                    states.push_back(move(ns));\n                    if (states.back().score > states[best_id].score) {\n                        best_id = states.size() - 1;\n                    }\n                }\n            }\n        }\n        if (nxt_cand.empty()) break;\n\n        if ((int)nxt_cand.size() > BEAM_WIDTH) {\n            // Heuristic: current score + sum of weights of tiles within 2 steps\n            vector<long long> vals(nxt_cand.size());\n            for (size_t i = 0; i < nxt_cand.size(); ++i) {\n                int sid = nxt_cand[i];\n                const State& s = states[sid];\n                long long h = s.score;\n                vector<bool> vis_local(M, false);\n                queue<int> q;\n                q.push(s.current_tile);\n                vis_local[s.current_tile] = true;\n                for (int d = 0; d < 2; ++d) {\n                    int qsz = q.size();\n                    if (qsz == 0) break;\n                    for (int k = 0; k < qsz; ++k) {\n                        int uu = q.front(); q.pop();\n                        for (int vv : adj[uu]) {\n                            if (!s.visited[vv] && !vis_local[vv]) {\n                                vis_local[vv] = true;\n                                h += tile_weight[vv];\n                                q.push(vv);\n                            }\n                        }\n                    }\n                }\n                vals[i] = h;\n            }\n            vector<int> idx(nxt_cand.size());\n            iota(idx.begin(), idx.end(), 0);\n            sort(idx.begin(), idx.end(), [&](int i, int j) { return vals[i] > vals[j]; });\n            cur.clear();\n            cur.reserve(BEAM_WIDTH);\n            for (int i = 0; i < BEAM_WIDTH; ++i) {\n                cur.push_back(nxt_cand[idx[i]]);\n            }\n        } else {\n            cur = move(nxt_cand);\n        }\n    }\n\n    // --- Reconstruct tile sequence ---\n    vector<unsigned short> tile_seq;\n    for (int id = best_id; id != -1; id = states[id].parent_id) {\n        tile_seq.push_back(states[id].current_tile);\n    }\n    reverse(tile_seq.begin(), tile_seq.end());\n\n    // --- Generate path string ---\n    string ans;\n    int x = si, y = sj;\n    vector vis(N, vector<bool>(N, false));\n    vis[x][y] = true;\n\n    auto get_move = [&](int x1, int y1, int x2, int y2) -> string {\n        if (x2 == x1 - 1) return \"U\";\n        if (x2 == x1 + 1) return \"D\";\n        if (y2 == y1 - 1) return \"L\";\n        if (y2 == y1 + 1) return \"R\";\n        return \"\";\n    };\n\n    for (size_t idx = 0; idx < tile_seq.size(); ++idx) {\n        unsigned short t = tile_seq[idx];\n        auto& sqs = tile_sq[t];\n        // Visit all squares inside the current tile\n        if (sqs.size() == 2) {\n            auto [r0, c0] = sqs[0];\n            auto [r1, c1] = sqs[1];\n            bool v0 = vis[r0][c0], v1 = vis[r1][c1];\n            if (!v0 || !v1) {\n                auto [ur, uc] = v0 ? sqs[1] : sqs[0];\n                ans += get_move(x, y, ur, uc);\n                x = ur; y = uc;\n                vis[x][y] = true;\n            }\n        }\n        // If not the last tile, move to exit square and then to the next tile\n        if (idx != tile_seq.size() - 1) {\n            unsigned short nxt = tile_seq[idx + 1];\n            auto [ex, ey] = exit_sq[t][nxt];\n            if (x != ex || y != ey) {\n                ans += get_move(x, y, ex, ey);\n                x = ex; y = ey;\n                vis[x][y] = true;\n            }\n            int nx = -1, ny = -1;\n            for (int d = 0; d < 4; ++d) {\n                int ni = x + dirs[d][0], nj = y + dirs[d][1];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N && t[ni][nj] == nxt) {\n                    nx = ni; ny = nj;\n                    break;\n                }\n            }\n            if (nx != -1) {\n                ans += get_move(x, y, nx, ny);\n                x = nx; y = ny;\n                vis[x][y] = true;\n            } else {\n                break; // should not happen\n            }\n        }\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int N = 30;\nconstexpr int H_EDGES = N * (N - 1);   // 870\nconstexpr int V_EDGES = (N - 1) * N;   // 870\nconstexpr int E = H_EDGES + V_EDGES;   // 1740\n\n// edge index for horizontal edge between (i,j) and (i,j+1)\nint edge_idx_horiz(int i, int j) { return i * (N - 1) + j; }\n// edge index for vertical edge between (i,j) and (i+1,j)\nint edge_idx_vert(int i, int j) { return H_EDGES + i * N + j; }\n\n// Dijkstra returning move string and edges traversed\nstring dijkstra(int si, int sj, int ti, int tj,\n                const vector<double>& w_plan,\n                const vector<int>& cnt,\n                double alpha,\n                mt19937& rng,\n                vector<int>& path_edges) {\n    int start = si * N + sj;\n    int goal = ti * N + tj;\n\n    vector<double> dist(N * N, 1e18);\n    vector<int> parent(N * N, -1);\n    vector<int> parent_edge(N * N, -1);\n    dist[start] = 0;\n\n    using P = pair<double, int>;\n    priority_queue<P, vector<P>, greater<P>> pq;\n    pq.push({0, start});\n\n    uniform_real_distribution<double> noise(-0.5, 0.5);\n\n    // adjacency\n    static vector<vector<pair<int, int>>> adj;\n    if (adj.empty()) {\n        adj.resize(N * N);\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (j < N - 1) {\n                    int u = i * N + j, v = i * N + j + 1;\n                    int e = edge_idx_horiz(i, j);\n                    adj[u].push_back({v, e});\n                    adj[v].push_back({u, e});\n                }\n                if (i < N - 1) {\n                    int u = i * N + j, v = (i + 1) * N + j;\n                    int e = edge_idx_vert(i, j);\n                    adj[u].push_back({v, e});\n                    adj[v].push_back({u, e});\n                }\n            }\n        }\n    }\n\n    while (!pq.empty()) {\n        auto [d, u] = pq.top(); pq.pop();\n        if (d != dist[u]) continue;\n        if (u == goal) break;\n        for (auto [v, e] : adj[u]) {\n            double w_mod = w_plan[e] - alpha / sqrt(cnt[e] + 1.0);\n            if (w_mod < 1.0) w_mod = 1.0;\n            double nd = d + w_mod + noise(rng) * 0.1;\n            if (nd < dist[v]) {\n                dist[v] = nd;\n                parent[v] = u;\n                parent_edge[v] = e;\n                pq.push({nd, v});\n            }\n        }\n    }\n\n    // reconstruct\n    path_edges.clear();\n    vector<int> nodes;\n    for (int cur = goal; cur != start; cur = parent[cur]) {\n        nodes.push_back(cur);\n        path_edges.push_back(parent_edge[cur]);\n    }\n    nodes.push_back(start);\n    reverse(nodes.begin(), nodes.end());\n    reverse(path_edges.begin(), path_edges.end());\n\n    string moves;\n    for (size_t i = 0; i + 1 < nodes.size(); ++i) {\n        int u = nodes[i], v = nodes[i + 1];\n        int ui = u / N, uj = u % N;\n        int vi = v / N, vj = v % N;\n        if (vi == ui - 1) moves += 'U';\n        else if (vi == ui + 1) moves += 'D';\n        else if (vj == uj - 1) moves += 'L';\n        else moves += 'R';\n    }\n    return moves;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    vector<double> w(E, 5000.0);\n    vector<double> w_plan = w;\n    vector<int> cnt(E, 0);\n    vector<double> row_h_mean(N, 5000.0);\n    vector<double> col_v_mean(N, 5000.0);\n\n    mt19937 rng(12345);\n    double alpha_explore = 2000.0;\n    double base_lr = 800.0;\n    double reg_coeff = 0.0005;\n\n    auto clamp = [](double v, double lo, double hi) {\n        return max(lo, min(hi, v));\n    };\n\n    auto recompute_means = [&]() {\n        for (int i = 0; i < N; ++i) {\n            double s = 0;\n            for (int j = 0; j < N - 1; ++j) s += w[edge_idx_horiz(i, j)];\n            row_h_mean[i] = s / (N - 1);\n        }\n        for (int j = 0; j < N; ++j) {\n            double s = 0;\n            for (int i = 0; i < N - 1; ++i) s += w[edge_idx_vert(i, j)];\n            col_v_mean[j] = s / (N - 1);\n        }\n    };\n\n    auto segment_rows = [&]() {\n        for (int i = 0; i < N; ++i) {\n            vector<double> a(N - 1);\n            for (int j = 0; j < N - 1; ++j) a[j] = w[edge_idx_horiz(i, j)];\n            double sum_total = accumulate(a.begin(), a.end(), 0.0);\n            double mean_all = sum_total / (N - 1);\n            double sse0 = 0;\n            for (double x : a) sse0 += (x - mean_all) * (x - mean_all);\n            double best_sse = sse0;\n            int best_x = -1;\n            double best_meanL = mean_all, best_meanR = mean_all;\n            double sum_left = 0;\n            for (int x = 1; x < N - 1; ++x) {\n                sum_left += a[x - 1];\n                double meanL = sum_left / x;\n                double sum_right = sum_total - sum_left;\n                double meanR = sum_right / (N - 1 - x);\n                double sse = 0;\n                for (int j = 0; j < x; ++j) sse += (a[j] - meanL) * (a[j] - meanL);\n                for (int j = x; j < N - 1; ++j) sse += (a[j] - meanR) * (a[j] - meanR);\n                if (sse < best_sse) {\n                    best_sse = sse;\n                    best_x = x;\n                    best_meanL = meanL;\n                    best_meanR = meanR;\n                }\n            }\n            if (best_sse < sse0 * 0.95) {\n                for (int j = 0; j < best_x; ++j) w[edge_idx_horiz(i, j)] = best_meanL;\n                for (int j = best_x; j < N - 1; ++j) w[edge_idx_horiz(i, j)] = best_meanR;\n            } else {\n                for (int j = 0; j < N - 1; ++j) w[edge_idx_horiz(i, j)] = mean_all;\n            }\n        }\n    };\n\n    auto segment_cols = [&]() {\n        for (int j = 0; j < N; ++j) {\n            vector<double> a(N - 1);\n            for (int i = 0; i < N - 1; ++i) a[i] = w[edge_idx_vert(i, j)];\n            double sum_total = accumulate(a.begin(), a.end(), 0.0);\n            double mean_all = sum_total / (N - 1);\n            double sse0 = 0;\n            for (double x : a) sse0 += (x - mean_all) * (x - mean_all);\n            double best_sse = sse0;\n            int best_x = -1;\n            double best_meanL = mean_all, best_meanR = mean_all;\n            double sum_left = 0;\n            for (int x = 1; x < N - 1; ++x) {\n                sum_left += a[x - 1];\n                double meanL = sum_left / x;\n                double sum_right = sum_total - sum_left;\n                double meanR = sum_right / (N - 1 - x);\n                double sse = 0;\n                for (int i = 0; i < x; ++i) sse += (a[i] - meanL) * (a[i] - meanL);\n                for (int i = x; i < N - 1; ++i) sse += (a[i] - meanR) * (a[i] - meanR);\n                if (sse < best_sse) {\n                    best_sse = sse;\n                    best_x = x;\n                    best_meanL = meanL;\n                    best_meanR = meanR;\n                }\n            }\n            if (best_sse < sse0 * 0.95) {\n                for (int i = 0; i < best_x; ++i) w[edge_idx_vert(i, j)] = best_meanL;\n                for (int i = best_x; i < N - 1; ++i) w[edge_idx_vert(i, j)] = best_meanR;\n            } else {\n                for (int i = 0; i < N - 1; ++i) w[edge_idx_vert(i, j)] = mean_all;\n            }\n        }\n    };\n\n    for (int k = 0; k < 1000; ++k) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n\n        vector<int> path_edges;\n        string moves = dijkstra(si, sj, ti, tj, w_plan, cnt, alpha_explore, rng, path_edges);\n        cout << moves << endl; // flushes\n\n        int obs;\n        cin >> obs;\n\n        double pred = 0;\n        for (int e : path_edges) pred += w[e];\n\n        double lr_decay = 1.0 / (1.0 + k * 0.005);\n        double lr_abs = base_lr / (pred + 1.0) * lr_decay;\n\n        for (int e : path_edges) {\n            double mean;\n            if (e < H_EDGES) {\n                int i = e / (N - 1);\n                mean = row_h_mean[i];\n            } else {\n                int idx = e - H_EDGES;\n                int j = idx % N;\n                mean = col_v_mean[j];\n            }\n            double grad = pred - obs;\n            double reg = w[e] - mean;\n            w[e] -= lr_abs * grad + reg_coeff * reg;\n            w[e] = clamp(w[e], 1000.0, 9000.0);\n            cnt[e]++;\n        }\n\n        recompute_means();\n\n        double rho = 0.05;\n        for (int e = 0; e < E; ++e)\n            w_plan[e] = (1 - rho) * w_plan[e] + rho * w[e];\n\n        alpha_explore = max(0.0, alpha_explore - 2.0);\n\n        if ((k + 1) % 100 == 0 && k >= 99) {\n            segment_rows();\n            segment_cols();\n            recompute_means();\n            for (int e = 0; e < E; ++e) w_plan[e] = w[e];\n        }\n    }\n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <numeric>\n#include <chrono>\n#include <cmath>\n#include <cstring>\n#include <cstdint>\n\nusing namespace std;\n\nconstexpr int N = 20;\n\nstruct XorShift {\n    uint32_t x;\n    XorShift(uint32_t seed) : x(seed) {}\n    uint32_t next() {\n        x ^= x << 13;\n        x ^= x >> 17;\n        x ^= x << 5;\n        return x;\n    }\n    int nextInt(int max) {\n        return next() % max;\n    }\n    double nextDouble() {\n        return (next() >> 8) * 0x1p-24;\n    }\n};\n\nint M;\nvector<string> strs;\nvector<int> len;\nvector<uint8_t> h_match_count, v_match_count, h_count, v_count;\nvector<int16_t> s_count;\nint c_total;\nchar grid[N][N];\n\nvoid init_match_arrays() {\n    h_match_count.assign(M * N * N, 0);\n    v_match_count.assign(M * N * N, 0);\n    h_count.assign(M * N, 0);\n    v_count.assign(M * N, 0);\n    s_count.assign(M, 0);\n    c_total = 0;\n}\n\nvoid compute_all_matches() {\n    fill(h_match_count.begin(), h_match_count.end(), 0);\n    fill(v_match_count.begin(), v_match_count.end(), 0);\n    fill(h_count.begin(), h_count.end(), 0);\n    fill(v_count.begin(), v_count.end(), 0);\n    fill(s_count.begin(), s_count.end(), 0);\n    c_total = 0;\n\n    for (int i = 0; i < M; ++i) {\n        int L = len[i];\n        const string& s = strs[i];\n        int total = 0;\n        // horizontal\n        for (int r = 0; r < N; ++r) {\n            int h_cnt = 0;\n            for (int start = 0; start < N; ++start) {\n                int cnt = 0;\n                for (int pos = 0; pos < L; ++pos) {\n                    if (grid[r][(start+pos)%N] == s[pos]) cnt++;\n                }\n                h_match_count[i * N * N + r * N + start] = cnt;\n                if (cnt == L) h_cnt++;\n            }\n            h_count[i * N + r] = h_cnt;\n            total += h_cnt;\n        }\n        // vertical\n        for (int c = 0; c < N; ++c) {\n            int v_cnt = 0;\n            for (int start = 0; start < N; ++start) {\n                int cnt = 0;\n                for (int pos = 0; pos < L; ++pos) {\n                    if (grid[(start+pos)%N][c] == s[pos]) cnt++;\n                }\n                v_match_count[i * N * N + c * N + start] = cnt;\n                if (cnt == L) v_cnt++;\n            }\n            v_count[i * N + c] = v_cnt;\n            total += v_cnt;\n        }\n        s_count[i] = total;\n        if (total > 0) c_total++;\n    }\n}\n\nint count_matched(const char g[N][N]) {\n    int cnt = 0;\n    for (int i = 0; i < M; ++i) {\n        const string& s = strs[i];\n        int L = len[i];\n        bool found = false;\n        for (int r = 0; r < N && !found; ++r) {\n            for (int start = 0; start < N && !found; ++start) {\n                bool ok = true;\n                for (int pos = 0; pos < L; ++pos) {\n                    if (g[r][(start+pos)%N] != s[pos]) { ok=false; break; }\n                }\n                if (ok) found = true;\n            }\n        }\n        for (int c = 0; c < N && !found; ++c) {\n            for (int start = 0; start < N && !found; ++start) {\n                bool ok = true;\n                for (int pos = 0; pos < L; ++pos) {\n                    if (g[(start+pos)%N][c] != s[pos]) { ok=false; break; }\n                }\n                if (ok) found = true;\n            }\n        }\n        if (found) cnt++;\n    }\n    return cnt;\n}\n\nint count_dots(const char g[N][N]) {\n    int d = 0;\n    for (int i=0; i<N; ++i) for (int j=0; j<N; ++j) if (g[i][j] == '.') d++;\n    return d;\n}\n\nvoid flip(int r, int c, char new_char) {\n    char old_char = grid[r][c];\n    if (old_char == new_char) return;\n    for (int i = 0; i < M; ++i) {\n        int L = len[i];\n        const string& s = strs[i];\n        // horizontal\n        int h_base = i * N * N + r * N;\n        int h_count_base = i * N + r;\n        for (int offset = 0; offset < L; ++offset) {\n            int start = (c - offset + N) % N;\n            bool old_contrib = (old_char == s[offset]);\n            bool new_contrib = (new_char == s[offset]);\n            int diff = (new_contrib ? 1 : 0) - (old_contrib ? 1 : 0);\n            if (diff != 0) {\n                int idx = h_base + start;\n                int old_cnt = h_match_count[idx];\n                int new_cnt = old_cnt + diff;\n                h_match_count[idx] = new_cnt;\n                bool was = (old_cnt == L);\n                bool is = (new_cnt == L);\n                if (was != is) {\n                    if (is) {\n                        h_count[h_count_base]++;\n                        s_count[i]++;\n                        if (s_count[i] == 1) c_total++;\n                    } else {\n                        h_count[h_count_base]--;\n                        s_count[i]--;\n                        if (s_count[i] == 0) c_total--;\n                    }\n                }\n            }\n        }\n        // vertical\n        int v_base = i * N * N + c * N;\n        int v_count_base = i * N + c;\n        for (int offset = 0; offset < L; ++offset) {\n            int start = (r - offset + N) % N;\n            bool old_contrib = (old_char == s[offset]);\n            bool new_contrib = (new_char == s[offset]);\n            int diff = (new_contrib ? 1 : 0) - (old_contrib ? 1 : 0);\n            if (diff != 0) {\n                int idx = v_base + start;\n                int old_cnt = v_match_count[idx];\n                int new_cnt = old_cnt + diff;\n                v_match_count[idx] = new_cnt;\n                bool was = (old_cnt == L);\n                bool is = (new_cnt == L);\n                if (was != is) {\n                    if (is) {\n                        v_count[v_count_base]++;\n                        s_count[i]++;\n                        if (s_count[i] == 1) c_total++;\n                    } else {\n                        v_count[v_count_base]--;\n                        s_count[i]--;\n                        if (s_count[i] == 0) c_total--;\n                    }\n                }\n            }\n        }\n    }\n    grid[r][c] = new_char;\n}\n\nint main() {\n    ios::sync_with_stdio(false); cin.tie(0);\n    auto start_time = chrono::steady_clock::now();\n    auto get_time = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n\n    cin >> N >> M; // N is fixed to 20\n    N = 20;\n    strs.resize(M);\n    len.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> strs[i];\n        len[i] = strs[i].size();\n    }\n\n    XorShift rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    // --- greedy construction ---\n    double greedy_time_limit = 0.5;\n    char best_grid[N][N];\n    int best_c = -1;\n    int best_d = 0;\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    char cur_grid[N][N];\n\n    struct Placement {\n        int ori; // 0 horizontal, 1 vertical\n        int rc;  // row or column index\n        int start;\n        int overlap;\n    };\n    vector<Placement> valid;\n    valid.reserve(800);\n\n    while (get_time() < greedy_time_limit) {\n        memset(cur_grid, '.', sizeof(cur_grid));\n        for (int i = M-1; i > 0; --i) swap(order[i], order[rng.nextInt(i+1)]);\n        for (int idx : order) {\n            const string& s = strs[idx];\n            int L = len[idx];\n            valid.clear();\n            // horizontal\n            for (int r = 0; r < N; ++r) {\n                for (int start = 0; start < N; ++start) {\n                    int overlap = 0;\n                    bool ok = true;\n                    for (int pos = 0; pos < L; ++pos) {\n                        int c = (start+pos)%N;\n                        if (cur_grid[r][c] != '.' && cur_grid[r][c] != s[pos]) {\n                            ok = false; break;\n                        }\n                        if (cur_grid[r][c] != '.') overlap++;\n                    }\n                    if (ok) valid.push_back({0, r, start, overlap});\n                }\n            }\n            // vertical\n            for (int c = 0; c < N; ++c) {\n                for (int start = 0; start < N; ++start) {\n                    int overlap = 0;\n                    bool ok = true;\n                    for (int pos = 0; pos < L; ++pos) {\n                        int r = (start+pos)%N;\n                        if (cur_grid[r][c] != '.' && cur_grid[r][c] != s[pos]) {\n                            ok = false; break;\n                        }\n                        if (cur_grid[r][c] != '.') overlap++;\n                    }\n                    if (ok) valid.push_back({1, c, start, overlap});\n                }\n            }\n            if (valid.empty()) continue;\n            int max_overlap = -1;\n            for (auto& p : valid) if (p.overlap > max_overlap) max_overlap = p.overlap;\n            vector<Placement*> candidates;\n            for (auto& p : valid) if (p.overlap == max_overlap) candidates.push_back(&p);\n            Placement& chosen = *candidates[rng.nextInt(candidates.size())];\n            if (chosen.ori == 0) {\n                int r = chosen.rc;\n                int start = chosen.start;\n                for (int pos = 0; pos < L; ++pos) cur_grid[r][(start+pos)%N] = s[pos];\n            } else {\n                int c = chosen.rc;\n                int start = chosen.start;\n                for (int pos = 0; pos < L; ++pos) cur_grid[(start+pos)%N][c] = s[pos];\n            }\n        }\n        int actual_c = count_matched(cur_grid);\n        int d = count_dots(cur_grid);\n        if (actual_c > best_c || (actual_c == best_c && d > best_d)) {\n            best_c = actual_c;\n            best_d = d;\n            memcpy(best_grid, cur_grid, sizeof(best_grid));\n        }\n        if (best_c == M) break;\n    }\n\n    char overall_best_grid[N][N];\n    int overall_best_c = best_c;\n    int overall_best_d = best_d;\n    memcpy(overall_best_grid, best_grid, sizeof(best_grid));\n\n    // --- SA phase when c < M ---\n    if (overall_best_c < M) {\n        memcpy(grid, best_grid, sizeof(grid));\n        for (int i=0; i<N; ++i)\n            for (int j=0; j<N; ++j)\n                if (grid[i][j] == '.')\n                    grid[i][j] = \"ABCDEFGH\"[rng.nextInt(8)];\n\n        init_match_arrays();\n        compute_all_matches();\n        int best_c_sa = c_total;\n        char best_grid_sa[N][N];\n        memcpy(best_grid_sa, grid, sizeof(grid));\n\n        double T_start = 1.0;\n        double T_end = 0.001;\n        int max_steps = 200000;\n        double cool_rate = pow(T_end / T_start, 1.0 / max_steps);\n        double T = T_start;\n        double sa_time_limit = 2.9;\n        int step = 0;\n\n        while (get_time() < sa_time_limit && step < max_steps && c_total < M) {\n            int r = rng.nextInt(N);\n            int c = rng.nextInt(N);\n            char old_char = grid[r][c];\n            char new_char = \"ABCDEFGH\"[rng.nextInt(8)];\n            if (new_char == old_char) continue;\n            int old_c = c_total;\n            flip(r, c, new_char);\n            int new_c = c_total;\n            int delta = new_c - old_c;\n            if (delta >= 0) {\n                if (new_c > best_c_sa) {\n                    best_c_sa = new_c;\n                    memcpy(best_grid_sa, grid, sizeof(grid));\n                }\n            } else {\n                double prob = exp(delta / T);\n                if (rng.nextDouble() < prob) {\n                    // accept\n                } else {\n                    flip(r, c, old_char); // revert\n                }\n            }\n            T *= cool_rate;\n            ++step;\n            if (c_total == M) {\n                best_c_sa = M;\n                memcpy(best_grid_sa, grid, sizeof(grid));\n                break;\n            }\n        }\n        if (best_c_sa > overall_best_c) {\n            overall_best_c = best_c_sa;\n            overall_best_d = 0;\n            memcpy(overall_best_grid, best_grid_sa, sizeof(best_grid_sa));\n        }\n    }\n\n    // --- dot optimization if all strings are matched ---\n    if (overall_best_c == M) {\n        memcpy(grid, overall_best_grid, sizeof(grid));\n        init_match_arrays();\n        compute_all_matches();\n        vector<pair<int,int>> cells;\n        cells.reserve(N*N);\n        for (int i=0; i<N; ++i) for (int j=0; j<N; ++j) if (grid[i][j] != '.') cells.emplace_back(i,j);\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            for (int i = cells.size()-1; i>0; --i) swap(cells[i], cells[rng.nextInt(i+1)]);\n            for (auto& p : cells) {\n                int r = p.first, c = p.second;\n                if (grid[r][c] == '.') continue;\n                char old = grid[r][c];\n                flip(r, c, '.');\n                if (c_total == M) {\n                    changed = true;\n                } else {\n                    flip(r, c, old);\n                }\n            }\n        }\n        memcpy(overall_best_grid, grid, sizeof(grid));\n    }\n\n    // output\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) cout << overall_best_grid[i][j];\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int N, si, sj;\n    cin >> N >> si >> sj;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n\n    // Assign IDs to road cells\n    vector<vector<int>> id(N, vector<int>(N, -1));\n    vector<pair<int, int>> cells;\n    vector<int> cell_cost;\n    int r = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != '#') {\n                id[i][j] = r;\n                cells.emplace_back(i, j);\n                cell_cost.push_back(grid[i][j] - '0');\n                r++;\n            }\n        }\n    }\n\n    // Adjacency list: each edge (v, w) where w is cost of entering v\n    vector<vector<pair<int, int>>> adj(r);\n    const int di[4] = {-1, 1, 0, 0};\n    const int dj[4] = {0, 0, -1, 1};\n    for (int u = 0; u < r; ++u) {\n        int i = cells[u].first, j = cells[u].second;\n        for (int d = 0; d < 4; ++d) {\n            int ni = i + di[d], nj = j + dj[d];\n            if (ni >= 0 && ni < N && nj >= 0 && nj < N && id[ni][nj] != -1) {\n                int v = id[ni][nj];\n                int w = cell_cost[v];\n                adj[u].emplace_back(v, w);\n            }\n        }\n    }\n\n    // Horizontal segments (rows)\n    vector<int> h_id(r, -1);\n    int H_count = 0;\n    vector<int> h_ep1, h_ep2; // endpoints\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ) {\n            if (id[i][j] != -1) {\n                int start_j = j;\n                while (j < N && id[i][j] != -1) {\n                    h_id[id[i][j]] = H_count;\n                    j++;\n                }\n                int end_j = j - 1;\n                h_ep1.push_back(id[i][start_j]);\n                h_ep2.push_back(id[i][end_j]);\n                H_count++;\n            } else {\n                j++;\n            }\n        }\n    }\n\n    // Vertical segments (columns)\n    vector<int> v_id(r, -1);\n    int V_count = 0;\n    vector<int> v_ep1, v_ep2;\n    for (int j = 0; j < N; ++j) {\n        for (int i = 0; i < N; ) {\n            if (id[i][j] != -1) {\n                int start_i = i;\n                while (i < N && id[i][j] != -1) {\n                    v_id[id[i][j]] = V_count;\n                    i++;\n                }\n                int end_i = i - 1;\n                v_ep1.push_back(id[start_i][j]);\n                v_ep2.push_back(id[end_i][j]);\n                V_count++;\n            } else i++;\n        }\n    }\n\n    int total_seg = H_count + V_count;\n\n    // Candidate set: start + all segment endpoints\n    set<int> cand_set;\n    cand_set.insert(id[si][sj]);\n    for (int x : h_ep1) cand_set.insert(x);\n    for (int x : h_ep2) cand_set.insert(x);\n    for (int x : v_ep1) cand_set.insert(x);\n    for (int x : v_ep2) cand_set.insert(x);\n    vector<int> P(cand_set.begin(), cand_set.end());\n    int P_sz = P.size();\n\n    // For each candidate, list of segments it covers (h_id and v_id with offset)\n    vector<vector<int>> seg_cover(P_sz);\n    for (int i = 0; i < P_sz; ++i) {\n        int cid = P[i];\n        seg_cover[i].push_back(h_id[cid]);\n        seg_cover[i].push_back(H_count + v_id[cid]);\n    }\n\n    // Greedy set cover, starting with start cell\n    int start_cid = id[si][sj];\n    int start_idx = -1;\n    for (int i = 0; i < P_sz; ++i) if (P[i] == start_cid) { start_idx = i; break; }\n\n    vector<bool> covered(total_seg, false);\n    vector<int> selected;\n    if (start_idx != -1) {\n        selected.push_back(start_idx);\n        for (int seg : seg_cover[start_idx]) covered[seg] = true;\n    }\n    int uncovered = 0;\n    for (bool b : covered) if (!b) uncovered++;\n\n    while (uncovered > 0) {\n        int best_idx = -1, best_gain = 0;\n        for (int i = 0; i < P_sz; ++i) {\n            if (find(selected.begin(), selected.end(), i) != selected.end()) continue;\n            int gain = 0;\n            for (int seg : seg_cover[i]) if (!covered[seg]) gain++;\n            if (gain > best_gain) {\n                best_gain = gain;\n                best_idx = i;\n            }\n        }\n        if (best_gain == 0) break; // safety\n        selected.push_back(best_idx);\n        for (int seg : seg_cover[best_idx]) {\n            if (!covered[seg]) { covered[seg] = true; uncovered--; }\n        }\n    }\n\n    // Prune redundant waypoints\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        for (size_t i = 0; i < selected.size(); ++i) {\n            if (P[selected[i]] == start_cid) continue;\n            vector<bool> cov_without(total_seg, false);\n            for (size_t j = 0; j < selected.size(); ++j) {\n                if (i == j) continue;\n                for (int seg : seg_cover[selected[j]]) cov_without[seg] = true;\n            }\n            bool needed = false;\n            for (int seg : seg_cover[selected[i]]) if (!cov_without[seg]) { needed = true; break; }\n            if (!needed) {\n                selected.erase(selected.begin() + i);\n                changed = true;\n                break;\n            }\n        }\n    }\n\n    // Ensure start is first\n    if (selected.empty() || P[selected[0]] != start_cid) {\n        auto it = find(selected.begin(), selected.end(), start_idx);\n        if (it != selected.end()) {\n            int pos = it - selected.begin();\n            swap(selected[0], selected[pos]);\n        } else {\n            selected.insert(selected.begin(), start_idx);\n        }\n    }\n\n    // C: cell ids of chosen waypoints\n    vector<int> C;\n    for (int idx : selected) C.push_back(P[idx]);\n    int K = C.size();\n\n    if (K == 1) {\n        cout << \"\" << \"\\n\";\n        return 0;\n    }\n\n    // Distance matrix D (directed costs)\n    const int INF = 1e9;\n    vector<vector<int>> D(K, vector<int>(K, 0));\n\n    // Dijkstra (Dial's algorithm) for directed shortest paths\n    auto dijkstra = [&](int src, vector<int>& dist, vector<int>& prev) {\n        dist.assign(r, INF);\n        prev.assign(r, -1);\n        vector<queue<int>> buckets(10);\n        dist[src] = 0;\n        buckets[0].push(src);\n        int max_d = 0, cur_d = 0;\n        while (cur_d <= max_d) {\n            int idx = cur_d % 10;\n            if (!buckets[idx].empty()) {\n                int u = buckets[idx].front(); buckets[idx].pop();\n                if (dist[u] < cur_d) continue;\n                for (auto& p : adj[u]) {\n                    int v = p.first, w = p.second;\n                    int nd = dist[u] + w;\n                    if (nd < dist[v]) {\n                        dist[v] = nd;\n                        prev[v] = u;\n                        buckets[nd % 10].push(v);\n                        if (nd > max_d) max_d = nd;\n                    }\n                }\n            } else {\n                cur_d++;\n            }\n        }\n    };\n\n    // Build D\n    for (int i = 0; i < K; ++i) {\n        vector<int> dist, prev;\n        dijkstra(C[i], dist, prev);\n        for (int j = 0; j < K; ++j) D[i][j] = dist[C[j]];\n    }\n\n    // Build initial ATSP tour using nearest neighbour\n    vector<int> tour(K);\n    vector<bool> used(K, false);\n    tour[0] = 0; used[0] = true;\n    for (int pos = 1; pos < K; ++pos) {\n        int last = tour[pos - 1];\n        int best = -1, best_d = INF;\n        for (int nxt = 0; nxt < K; ++nxt) {\n            if (!used[nxt] && D[last][nxt] < best_d) {\n                best_d = D[last][nxt];\n                best = nxt;\n            }\n        }\n        tour[pos] = best;\n        used[best] = true;\n    }\n\n    // 2-opt improvement for asymmetric TSP (segment reversal)\n    auto eval_tour = [&](const vector<int>& t) {\n        int sum = 0;\n        for (int i = 0; i < K; ++i) sum += D[t[i]][t[(i+1)%K]];\n        return sum;\n    };\n\n    int best_cost = eval_tour(tour);\n    if (K <= 400) { // only run 2-opt for moderate K\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            for (int i = 0; i < K; ++i) {\n                for (int j = i + 2; j < K; ++j) {\n                    if (i == 0 && j == K - 1) continue; // not reversing the whole tour\n                    int a = tour[i], b = tour[(i+1)%K], c = tour[j], d = tour[(j+1)%K];\n                    // Simple delta calculation with prefix sums to avoid O(K) per move\n                    // For simplicity and given K is small, we just do O(K) evaluator:\n                    vector<int> nt = tour;\n                    reverse(nt.begin() + i + 1, nt.begin() + j + 1);\n                    int new_cost = eval_tour(nt);\n                    if (new_cost < best_cost) {\n                        tour = nt;\n                        best_cost = new_cost;\n                        improved = true;\n                        // restart loops\n                        goto next_2opt;\n                    }\n                }\n            }\n            next_2opt:;\n        }\n    }\n\n    // Generate output route\n    string ans;\n    ans.reserve(1000000);\n\n    for (int step = 0; step < K; ++step) {\n        int u = C[tour[step]];\n        int v = C[tour[(step + 1) % K]];\n        vector<int> dist, prev;\n        dijkstra(u, dist, prev);\n        vector<int> path;\n        for (int cur = v; cur != u; cur = prev[cur]) path.push_back(cur);\n        path.push_back(u);\n        reverse(path.begin(), path.end());\n\n        for (size_t k = 0; k + 1 < path.size(); ++k) {\n            int from = path[k], to = path[k + 1];\n            int fi = cells[from].first, fj = cells[from].second;\n            int ti = cells[to].first, tj = cells[to].second;\n            if (ti < fi) ans += 'U';\n            else if (ti > fi) ans += 'D';\n            else if (tj < fj) ans += 'L';\n            else ans += 'R';\n        }\n    }\n\n    cout << ans << \"\\n\";\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <set>\n#include <climits>\n#include <cmath>\nusing namespace std;\n\nstruct Obs {\n    int task;\n    int L;\n    int U;\n};\n\nint N, M, K, R;\nvector<vector<int>> d;           // task difficulties\nvector<vector<int>> out_edges;   // dependents of each task\nvector<int> indegree;            // original indegree\nvector<int> height;              // longest path to sink (including itself)\nint max_height;\n\nvector<int> task_status;         // 0: not started, 1: in progress, 2: completed\nvector<int> req_remaining;       // number of unfinished prerequisites\nvector<int> worker_task;         // which task worker is doing (-1 = free)\nvector<int> worker_start;        // day the worker started current task\nvector<vector<Obs>> obs;         // observations per worker\nvector<vector<int>> LB, UB;      // skill bounds per worker\n\n// update skill bounds for worker j using all observations\nvoid update_bounds(int j) {\n    vector<int> &lb = LB[j];\n    vector<int> &ub = UB[j];\n    fill(lb.begin(), lb.end(), 0);\n    fill(ub.begin(), ub.end(), 200);\n\n    bool changed = true;\n    int iter = 0;\n    while (changed && iter < 10) {\n        changed = false;\n        iter++;\n        for (const auto &ob : obs[j]) {\n            int ti = ob.task;\n            int L = ob.L;\n            int U = ob.U;\n            // Update lower bounds using upper bound U\n            for (int k = 0; k < K; k++) {\n                int new_lb = max(lb[k], d[ti][k] - U);\n                if (new_lb > ub[k]) new_lb = ub[k]; // keep consistent\n                if (new_lb > lb[k]) {\n                    lb[k] = new_lb;\n                    changed = true;\n                }\n            }\n            // Precompute S_others_max (max possible deficit from other skills)\n            vector<int> S_others_max(K, 0);\n            for (int k = 0; k < K; k++) {\n                int sum = 0;\n                for (int k2 = 0; k2 < K; k2++) {\n                    if (k2 == k) continue;\n                    sum += max(0, d[ti][k2] - lb[k2]);\n                }\n                S_others_max[k] = sum;\n            }\n            // Update upper bounds using lower bound L\n            for (int k = 0; k < K; k++) {\n                if (L > S_others_max[k]) {\n                    int new_ub = d[ti][k] - (L - S_others_max[k]);\n                    if (new_ub < lb[k]) new_ub = lb[k]; // keep consistent\n                    if (new_ub < ub[k]) {\n                        ub[k] = new_ub;\n                        changed = true;\n                    }\n                }\n            }\n        }\n    }\n}\n\n// estimate days needed for worker w to finish task idx\nint estimate_t(int worker, int task) {\n    double r = 0.0;\n    if (max_height > 1) {\n        r = (double)(height[task] - 1) / (max_height - 1);\n    }\n    int w_val = 0;\n    for (int k = 0; k < K; k++) {\n        double s_blend = LB[worker][k] + (UB[worker][k] - LB[worker][k]) * (1.0 - r);\n        int s_int = (int)round(s_blend);\n        int def = d[task][k] - s_int;\n        if (def > 0) w_val += def;\n    }\n    return (w_val == 0) ? 1 : w_val;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> M >> K >> R;\n    d.resize(N, vector<int>(K));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < K; j++) {\n            cin >> d[i][j];\n        }\n    }\n    out_edges.resize(N);\n    indegree.assign(N, 0);\n    for (int i = 0; i < R; i++) {\n        int u, v;\n        cin >> u >> v;\n        u--; v--;\n        out_edges[u].push_back(v);\n        indegree[v]++;\n    }\n    \n    // Compute height = length of longest path to a sink (inclusive)\n    height.resize(N);\n    max_height = 0;\n    for (int i = N - 1; i >= 0; i--) {\n        int best = 0;\n        for (int v : out_edges[i]) {\n            best = max(best, height[v]);\n        }\n        height[i] = best + 1;\n        max_height = max(max_height, height[i]);\n    }\n    \n    // Initialize state\n    task_status.assign(N, 0);\n    req_remaining = indegree;\n    worker_task.assign(M, -1);\n    worker_start.assign(M, -1);\n    obs.resize(M);\n    LB.assign(M, vector<int>(K, 0));\n    UB.assign(M, vector<int>(K, 200));\n    \n    int day = 1;\n    int completed = 0;\n    \n    while (true) {\n        vector<int> free_workers;\n        for (int j = 0; j < M; j++) {\n            if (worker_task[j] == -1) free_workers.push_back(j);\n        }\n        vector<int> ready_tasks;\n        for (int i = 0; i < N; i++) {\n            if (task_status[i] == 0 && req_remaining[i] == 0) {\n                ready_tasks.push_back(i);\n            }\n        }\n        \n        // Sort by height descending (critical first)\n        sort(ready_tasks.begin(), ready_tasks.end(), [&](int a, int b) {\n            return height[a] > height[b];\n        });\n        \n        // Only consider a limited number of highest priority tasks\n        int max_consider = max((int)free_workers.size() * 3, 40);\n        if ((int)ready_tasks.size() > max_consider) {\n            ready_tasks.resize(max_consider);\n        }\n        \n        vector<pair<int,int>> assignments;\n        set<int> used;\n        for (int task : ready_tasks) {\n            int best_w = -1;\n            int best_t = INT_MAX;\n            for (int w : free_workers) {\n                if (used.count(w)) continue;\n                int t_est = estimate_t(w, task);\n                if (t_est < best_t) {\n                    best_t = t_est;\n                    best_w = w;\n                }\n            }\n            if (best_w != -1) {\n                assignments.push_back({best_w, task});\n                used.insert(best_w);\n                if (used.size() == free_workers.size()) break;\n            }\n        }\n        \n        // Output assignments\n        cout << assignments.size();\n        for (auto &p : assignments) {\n            cout << \" \" << p.first + 1 << \" \" << p.second + 1;\n        }\n        cout << \"\\n\";\n        cout.flush();\n        \n        // Update state for newly started tasks\n        for (auto &p : assignments) {\n            int w = p.first;\n            int task = p.second;\n            worker_task[w] = task;\n            worker_start[w] = day;\n            task_status[task] = 1;\n        }\n        \n        // Read completions\n        int n;\n        cin >> n;\n        if (n == -1) {\n            break;\n        }\n        vector<int> finished_workers(n);\n        for (int i = 0; i < n; i++) {\n            cin >> finished_workers[i];\n            finished_workers[i]--;\n        }\n        \n        // Process each completion\n        for (int w : finished_workers) {\n            int task = worker_task[w];\n            int start = worker_start[w];\n            int t_actual = day - start + 1;\n            int L, U;\n            if (t_actual == 1) {\n                L = 0;\n                U = 4;\n            } else {\n                L = max(1, t_actual - 3);\n                U = t_actual + 3;\n            }\n            obs[w].push_back({task, L, U});\n            \n            task_status[task] = 2;\n            completed++;\n            for (int v : out_edges[task]) {\n                req_remaining[v]--;\n            }\n            worker_task[w] = -1;\n            worker_start[w] = -1;\n        }\n        \n        // Update skill bounds for workers who finished a task\n        for (int w : finished_workers) {\n            update_bounds(w);\n        }\n        \n        day++;\n        if (day > 2000) {\n            break;\n        }\n    }\n    \n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct InsertResult {\n    int cost, i, j;\n};\n\nint main() {\n    auto start_time = chrono::steady_clock::now();\n    auto elapsed_ms = [&]() {\n        return chrono::duration_cast<chrono::milliseconds>(\n                   chrono::steady_clock::now() - start_time)\n            .count();\n    };\n\n    // ---------- input ----------\n    vector<int> ax(1000), ay(1000), cx(1000), cy(1000);\n    for (int i = 0; i < 1000; i++)\n        cin >> ax[i] >> ay[i] >> cx[i] >> cy[i];\n\n    // ---------- precompute coordinates ----------\n    vector<pair<int, int>> coords(2001);\n    coords[0] = {400, 400};\n    for (int i = 0; i < 1000; i++) {\n        coords[2 * i + 1] = {ax[i], ay[i]};\n        coords[2 * i + 2] = {cx[i], cy[i]};\n    }\n    auto dist = [&](int u, int v) -> int {\n        return abs(coords[u].first - coords[v].first) +\n               abs(coords[u].second - coords[v].second);\n    };\n\n    // ---------- state ----------\n    vector<int> seq;            // sequence of node IDs (without depot)\n    int T = 0;                  // total travel time\n    vector<bool> sel_flag(1000, false);\n    vector<int> sel_orders;     // selected order indices (0..999)\n\n    // ---------- helpers ----------\n    auto calc_total = [&](const vector<int>& s) -> int {\n        if (s.empty()) return 0;\n        int tot = dist(0, s[0]);\n        for (size_t i = 0; i + 1 < s.size(); i++)\n            tot += dist(s[i], s[i + 1]);\n        tot += dist(s.back(), 0);\n        return tot;\n    };\n\n    auto eval_ins = [&](const vector<int>& s, int o) -> InsertResult {\n        int L = s.size();\n        int P = 2 * o + 1, D = 2 * o + 2;\n        int best_cost = INT_MAX, best_i = -1, best_j = -1;\n        for (int i = 0; i <= L; i++) {\n            int prev_i = (i == 0 ? 0 : s[i - 1]);\n            int next_i = (i == L ? 0 : s[i]);\n            int base_i = dist(prev_i, next_i);\n            // consecutive P and D at gap i\n            int cost_pd = dist(prev_i, P) + dist(P, D) + dist(D, next_i) - base_i;\n            if (cost_pd < best_cost) {\n                best_cost = cost_pd;\n                best_i = best_j = i;\n            }\n            int inc_P = dist(prev_i, P) + dist(P, next_i) - base_i;\n            for (int j = i + 1; j <= L; j++) {\n                int prev_j = s[j - 1];  // j>=1\n                int next_j = (j == L ? 0 : s[j]);\n                int inc_D = dist(prev_j, D) + dist(D, next_j) - dist(prev_j, next_j);\n                int cost = inc_P + inc_D;\n                if (cost < best_cost) {\n                    best_cost = cost;\n                    best_i = i;\n                    best_j = j;\n                }\n            }\n        }\n        return {best_cost, best_i, best_j};\n    };\n\n    auto apply_ins = [&](vector<int>& s, int o, int i, int j) {\n        int P = 2 * o + 1, D = 2 * o + 2;\n        int L = s.size();\n        vector<int> ns;\n        ns.reserve(L + 2);\n        for (int pos = 0; pos <= L; pos++) {\n            if (pos == i) ns.push_back(P);\n            if (pos == j) ns.push_back(D);\n            if (pos < L) ns.push_back(s[pos]);\n        }\n        s = move(ns);\n    };\n\n    auto remove_order = [&](vector<int>& s, int o) {\n        int P = 2 * o + 1, D = 2 * o + 2;\n        s.erase(remove(s.begin(), s.end(), P), s.end());\n        s.erase(remove(s.begin(), s.end(), D), s.end());\n    };\n\n    // ---------- greedy construction of initial 50 orders ----------\n    for (int sel = 0; sel < 50; sel++) {\n        int best_o = -1, best_cost = INT_MAX, best_i = -1, best_j = -1;\n        for (int o = 0; o < 1000; o++) {\n            if (sel_flag[o]) continue;\n            auto res = eval_ins(seq, o);\n            if (res.cost < best_cost) {\n                best_cost = res.cost;\n                best_o = o;\n                best_i = res.i;\n                best_j = res.j;\n            }\n        }\n        apply_ins(seq, best_o, best_i, best_j);\n        T += best_cost;\n        sel_flag[best_o] = true;\n        sel_orders.push_back(best_o);\n    }\n    T = calc_total(seq);  // avoid any accumulation error\n\n    // ---------- route improvement (deterministic local search) ----------\n    auto improve_route = [&]() {\n        const int MAX_PASSES = 20;\n        for (int pass = 0; pass < MAX_PASSES; pass++) {\n            bool improved = false;\n            // --- re\u2011insert whole order ---\n            for (int i = 0; i < (int)sel_orders.size(); i++) {\n                int o = sel_orders[i];\n                vector<int> temp_s = seq;\n                remove_order(temp_s, o);\n                int T_wo = calc_total(temp_s);\n                auto res = eval_ins(temp_s, o);\n                int T_new = T_wo + res.cost;\n                if (T_new < T) {\n                    seq = move(temp_s);\n                    apply_ins(seq, o, res.i, res.j);\n                    T = T_new;\n                    improved = true;\n                    break;\n                }\n            }\n            if (improved) continue;\n\n            // --- relocate one stop (pickup or delivery) ---\n            int L = seq.size();\n            for (int idx = 0; idx < L; idx++) {\n                int node = seq[idx];\n                int o = (node - 1) / 2;\n                bool is_pickup = (node % 2 == 1);\n                int other_node = is_pickup ? node + 1 : node - 1;\n                int other_idx = -1;\n                for (int k = 0; k < L; k++)\n                    if (seq[k] == other_node) { other_idx = k; break; }\n                vector<int> temp_s = seq;\n                temp_s.erase(temp_s.begin() + idx);\n                int other_idx_temp = -1;\n                for (int k = 0; k < L - 1; k++)\n                    if (temp_s[k] == other_node) { other_idx_temp = k; break; }\n                int best_delta = 0, best_pos = -1;\n                for (int pos = 0; pos <= L - 1; pos++) {\n                    if (is_pickup && pos > other_idx_temp) continue;\n                    if (!is_pickup && pos < other_idx_temp) continue;\n                    int prev = (pos == 0 ? 0 : temp_s[pos - 1]);\n                    int next = (pos == L - 1 ? 0 : temp_s[pos]);\n                    int base = dist(prev, next);\n                    int delta = dist(prev, node) + dist(node, next) - base;\n                    if (delta < best_delta) {\n                        best_delta = delta;\n                        best_pos = pos;\n                    }\n                }\n                if (best_delta < 0) {\n                    temp_s.insert(temp_s.begin() + best_pos, node);\n                    seq = move(temp_s);\n                    T += best_delta;\n                    improved = true;\n                    break;\n                }\n            }\n            if (improved) continue;\n\n            // --- reverse a segment (if feasible) ---\n            L = seq.size();\n            int best_delta = 0, best_i = -1, best_j = -1;\n            for (int i = 0; i < L; i++) {\n                for (int j = i + 1; j < L; j++) {\n                    bool feasible = true;\n                    for (int o : sel_orders) {\n                        int P = 2 * o + 1, D = 2 * o + 2;\n                        bool p_in = false, d_in = false;\n                        for (int k = i; k <= j; k++) {\n                            if (seq[k] == P) p_in = true;\n                            if (seq[k] == D) d_in = true;\n                        }\n                        if (p_in && d_in) { feasible = false; break; }\n                    }\n                    if (!feasible) continue;\n                    int prev_i = (i == 0 ? 0 : seq[i - 1]);\n                    int next_j = (j == L - 1 ? 0 : seq[j + 1]);\n                    int delta = dist(prev_i, seq[j]) + dist(seq[i], next_j) -\n                                dist(prev_i, seq[i]) - dist(seq[j], next_j);\n                    if (delta < best_delta) {\n                        best_delta = delta;\n                        best_i = i;\n                        best_j = j;\n                    }\n                }\n            }\n            if (best_delta < 0) {\n                reverse(seq.begin() + best_i, seq.begin() + best_j + 1);\n                T += best_delta;\n                improved = true;\n            }\n            if (!improved) break;\n        }\n    };\n\n    improve_route();\n\n    // ---------- SA + subset optimisation ----------\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> rnd_order(0, 999);\n    uniform_int_distribution<int> rnd_idx(0, 49);\n    uniform_real_distribution<double> rnd_prob(0.0, 1.0);\n\n    auto last_improve_time = chrono::steady_clock::now();\n\n    while (elapsed_ms() < 1900) {\n        double temp = 500.0 * (1.0 - elapsed_ms() / 2000.0);\n        if (temp < 1.0) temp = 1.0;\n        for (int a = 0; a < 100; a++) {\n            int idx_sel = rnd_idx(rng);\n            int o_sel = sel_orders[idx_sel];\n            int o_unsel;\n            do { o_unsel = rnd_order(rng); } while (sel_flag[o_unsel]);\n\n            int P_sel = 2 * o_sel + 1, D_sel = 2 * o_sel + 2;\n            vector<int> temp_s;\n            temp_s.reserve(seq.size() - 2);\n            for (int node : seq)\n                if (node != P_sel && node != D_sel) temp_s.push_back(node);\n            int T_wo = calc_total(temp_s);\n            auto res = eval_ins(temp_s, o_unsel);\n            int T_new = T_wo + res.cost;\n            double delta = T_new - T;\n            if (delta < 0 || exp(-delta / temp) > rnd_prob(rng)) {\n                apply_ins(temp_s, o_unsel, res.i, res.j);\n                seq = move(temp_s);\n                T = T_new;\n                sel_flag[o_sel] = false;\n                sel_flag[o_unsel] = true;\n                sel_orders[idx_sel] = o_unsel;\n            }\n        }\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - last_improve_time)\n                .count() > 200) {\n            improve_route();\n            last_improve_time = chrono::steady_clock::now();\n        }\n    }\n\n    // final polish\n    improve_route();\n\n    // ---------- output ----------\n    sort(sel_orders.begin(), sel_orders.end());\n    cout << 50;\n    for (int o : sel_orders) cout << \" \" << o + 1;\n    cout << \"\\n\";\n    cout << (seq.size() + 2);\n    cout << \" 400 400\";\n    for (int node : seq)\n        cout << \" \" << coords[node].first << \" \" << coords[node].second;\n    cout << \" 400 400\" << endl;\n\n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <stack>\n#include <tuple>\n#include <cstdint>\n\nusing namespace std;\n\nstruct DSU {\n    vector<int> parent, sz;\n    int comps;\n    DSU(int n) : parent(n), sz(n, 1), comps(n) {\n        for (int i = 0; i < n; ++i) parent[i] = i;\n    }\n    int find(int x) {\n        while (parent[x] != x) {\n            parent[x] = parent[parent[x]];\n            x = parent[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        parent[b] = a;\n        sz[a] += sz[b];\n        --comps;\n        return true;\n    }\n    bool same(int a, int b) { return find(a) == find(b); }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\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        cin >> x[i] >> y[i];\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    // Compute d_i (rounded Euclidean distance)\n    vector<int> d(M);\n    for (int i = 0; i < M; ++i) {\n        double dx = x[U[i]] - x[V[i]];\n        double dy = y[U[i]] - y[V[i]];\n        d[i] = (int)round(sqrt(dx*dx + dy*dy));\n    }\n    \n    // ---------- T_ref (MST using expected length 2*d) ----------\n    vector<tuple<int,int,int>> ref_edges; // (weight, u, v)\n    ref_edges.reserve(M);\n    for (int i = 0; i < M; ++i) {\n        ref_edges.emplace_back(d[i] * 2, U[i], V[i]);\n    }\n    sort(ref_edges.begin(), ref_edges.end());\n    \n    DSU dsu_ref(N);\n    vector<vector<pair<int,int>>> adj(N); // (neighbor, weight)\n    for (auto [w, u, v] : ref_edges) {\n        if (dsu_ref.unite(u, v)) {\n            adj[u].emplace_back(v, w);\n            adj[v].emplace_back(u, w);\n        }\n    }\n    \n    // max_w[u][v] = maximum edge weight on the unique path in T_ref\n    vector<vector<int>> max_w(N, vector<int>(N, 0));\n    for (int s = 0; s < N; ++s) {\n        stack<tuple<int,int,int>> st;\n        st.push({s, -1, 0});\n        while (!st.empty()) {\n            auto [node, par, cur_max] = st.top(); st.pop();\n            max_w[s][node] = cur_max;\n            for (auto [nxt, w] : adj[node]) {\n                if (nxt == par) continue;\n                st.push({nxt, node, max(cur_max, w)});\n            }\n        }\n    }\n    \n    // ---------- Monte Carlo estimation of P(e in MST) ----------\n    const int num_sim = 800;\n    vector<int> mst_count(M, 0);\n    \n    // Fast xorshift RNG\n    uint32_t xs[4] = {123456789, 362436069, 521288629, 88675123};\n    auto xorshift = [&]() -> uint32_t {\n        uint32_t t = xs[0] ^ (xs[0] << 11);\n        xs[0] = xs[1];\n        xs[1] = xs[2];\n        xs[2] = xs[3];\n        xs[3] = xs[3] ^ (xs[3] >> 19) ^ t ^ (t >> 8);\n        return xs[3];\n    };\n    \n    vector<tuple<int,int,int,int>> sim_edges; // (l, u, v, original_index)\n    sim_edges.reserve(M);\n    for (int sim = 0; sim < num_sim; ++sim) {\n        sim_edges.clear();\n        for (int i = 0; i < M; ++i) {\n            int range = 2 * d[i] + 1;\n            int l = d[i] + int(xorshift() % range);\n            sim_edges.emplace_back(l, U[i], V[i], i);\n        }\n        sort(sim_edges.begin(), sim_edges.end());\n        DSU dsu_sim(N);\n        for (auto [l, u, v, idx] : sim_edges) {\n            if (dsu_sim.unite(u, v)) {\n                mst_count[idx]++;\n            }\n        }\n    }\n    \n    vector<double> prob(M);\n    for (int i = 0; i < M; ++i) {\n        prob[i] = (double)mst_count[i] / num_sim;\n    }\n    \n    // ---------- Online decision phase ----------\n    DSU dsu_acc(N);\n    vector<pair<int,int>> accepted;\n    \n    for (int i = 0; i < M; ++i) {\n        int l_i;\n        cin >> l_i;\n        int u = U[i], v = V[i];\n        \n        // Already connected -> reject\n        if (dsu_acc.same(u, v)) {\n            cout << 0 << endl;\n            continue;\n        }\n        \n        // Very cheap edge -> accept immediately\n        if (l_i <= d[i] * 1.2) {\n            dsu_acc.unite(u, v);\n            accepted.emplace_back(u, v);\n            cout << 1 << endl;\n            continue;\n        }\n        \n        // Safety check: would rejecting this edge disconnect the remaining available graph?\n        DSU dsu_check(N);\n        for (auto [uu, vv] : accepted) {\n            dsu_check.unite(uu, vv);\n        }\n        bool connected = false;\n        for (int j = i + 1; j < M; ++j) {\n            dsu_check.unite(U[j], V[j]);\n            if (dsu_check.comps == 1) {\n                connected = true;\n                break;\n            }\n        }\n        if (!connected && dsu_check.comps > 1) {\n            // Must accept to keep the graph connected\n            dsu_acc.unite(u, v);\n            accepted.emplace_back(u, v);\n            cout << 1 << endl;\n            continue;\n        }\n        \n        // Dynamic threshold based on progress, urgency, and edge probability\n        double progress = (double)i / M;\n        int K = dsu_acc.comps;\n        int R = M - i - 1;\n        double urgency = (K - 1) / (double)max(1, R);\n        double factor = 0.3 + 0.5 * progress + 0.4 * urgency;\n        factor = min(max(factor, 0.3), 1.5);\n        \n        double threshold = max_w[u][v] * factor * (0.5 + prob[i]);\n        \n        if (l_i <= threshold) {\n            dsu_acc.unite(u, v);\n            accepted.emplace_back(u, v);\n            cout << 1 << endl;\n        } else {\n            cout << 0 << endl;\n        }\n    }\n    \n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst long long INF_CAP = 1e9;\n\nstruct Dinic {\n    struct Edge {\n        int to, rev;\n        long long cap;\n    };\n    vector<vector<Edge>> g;\n    vector<int> level, iter;\n    Dinic(int n) : g(n), level(n), iter(n) {}\n    void add_edge(int from, int to, long long cap) {\n        g[from].push_back({to, (int)g[to].size(), cap});\n        g[to].push_back({from, (int)g[from].size() - 1, 0});\n    }\n    void bfs(int s) {\n        fill(level.begin(), level.end(), -1);\n        queue<int> q;\n        level[s] = 0; q.push(s);\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (auto &e : g[v]) {\n                if (e.cap > 0 && level[e.to] < 0) {\n                    level[e.to] = level[v] + 1;\n                    q.push(e.to);\n                }\n            }\n        }\n    }\n    long long dfs(int v, int t, long long f) {\n        if (v == t) return f;\n        for (int &i = iter[v]; i < (int)g[v].size(); i++) {\n            Edge &e = g[v][i];\n            if (e.cap > 0 && level[v] < level[e.to]) {\n                long long d = dfs(e.to, t, min(f, e.cap));\n                if (d > 0) {\n                    e.cap -= d;\n                    g[e.to][e.rev].cap += d;\n                    return d;\n                }\n            }\n        }\n        return 0;\n    }\n    long long max_flow(int s, int t) {\n        long long flow = 0;\n        while (true) {\n            bfs(s);\n            if (level[t] < 0) return flow;\n            fill(iter.begin(), iter.end(), 0);\n            long long f;\n            while ((f = dfs(s, t, 1LL<<60)) > 0) flow += f;\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N; cin >> N;\n    vector<int> px(N), py(N), pt(N);\n    for (int i = 0; i < N; i++) cin >> px[i] >> py[i] >> pt[i];\n    int M; cin >> M;\n    vector<int> hx(M), hy(M);\n    for (int i = 0; i < M; i++) cin >> hx[i] >> hy[i];\n\n    int grid[32][32];\n    memset(grid, 0, sizeof(grid));\n\n    const int dx[4] = {-1, 1, 0, 0};\n    const int dy[4] = {0, 0, -1, 1};\n\n    for (int turn = 0; turn < 300; turn++) {\n        int dist_human[32][32];\n        memset(dist_human, -1, sizeof(dist_human));\n        queue<pair<int,int>> qh;\n        for (int i = 0; i < M; i++) {\n            dist_human[hx[i]][hy[i]] = 0;\n            qh.push({hx[i], hy[i]});\n        }\n        while (!qh.empty()) {\n            auto [x, y] = qh.front(); qh.pop();\n            for (int d = 0; d < 4; d++) {\n                int nx = x + dx[d], ny = y + dy[d];\n                if (nx >= 1 && nx <= 30 && ny >= 1 && ny <= 30 && grid[nx][ny] == 0 && dist_human[nx][ny] == -1) {\n                    dist_human[nx][ny] = dist_human[x][y] + 1;\n                    qh.push({nx, ny});\n                }\n            }\n        }\n\n        int dist_pet[32][32];\n        memset(dist_pet, -1, sizeof(dist_pet));\n        queue<pair<int,int>> qp;\n        for (int i = 0; i < N; i++) {\n            dist_pet[px[i]][py[i]] = 0;\n            qp.push({px[i], py[i]});\n        }\n        while (!qp.empty()) {\n            auto [x, y] = qp.front(); qp.pop();\n            for (int d = 0; d < 4; d++) {\n                int nx = x + dx[d], ny = y + dy[d];\n                if (nx >= 1 && nx <= 30 && ny >= 1 && ny <= 30 && grid[nx][ny] == 0 && dist_pet[nx][ny] == -1) {\n                    dist_pet[nx][ny] = dist_pet[x][y] + 1;\n                    qp.push({nx, ny});\n                }\n            }\n        }\n\n        int pid[32][32];\n        memset(pid, -1, sizeof(pid));\n        vector<pair<int,int>> passable;\n        for (int i = 1; i <= 30; i++)\n            for (int j = 1; j <= 30; j++)\n                if (grid[i][j] == 0) {\n                    pid[i][j] = passable.size();\n                    passable.push_back({i, j});\n                }\n\n        int V = passable.size();\n        int src = 2 * V, sink = 2 * V + 1;\n        Dinic dinic(2 * V + 2);\n\n        for (int u = 0; u < V; u++) {\n            auto [x, y] = passable[u];\n            bool has_human = false, has_pet = false, adj_pet = false;\n            for (int i = 0; i < M; i++) if (hx[i] == x && hy[i] == y) has_human = true;\n            for (int i = 0; i < N; i++) if (px[i] == x && py[i] == y) has_pet = true;\n            if (!has_pet) {\n                for (int d = 0; d < 4; d++) {\n                    int nx = x + dx[d], ny = y + dy[d];\n                    if (nx >= 1 && nx <= 30 && ny >= 1 && ny <= 30) {\n                        for (int i = 0; i < N; i++)\n                            if (px[i] == nx && py[i] == ny) adj_pet = true;\n                    }\n                }\n            }\n            bool can_build = !has_human && !has_pet && !adj_pet;\n            long long cap;\n            if (can_build) {\n                int d = dist_human[x][y];\n                cap = 1 + 10000 / (d + 1);\n            } else {\n                cap = INF_CAP;\n            }\n            dinic.add_edge(2 * u, 2 * u + 1, cap);\n        }\n\n        for (int u = 0; u < V; u++) {\n            auto [x, y] = passable[u];\n            for (int d = 0; d < 4; d++) {\n                int nx = x + dx[d], ny = y + dy[d];\n                if (nx >= 1 && nx <= 30 && ny >= 1 && ny <= 30 && pid[nx][ny] != -1) {\n                    int v = pid[nx][ny];\n                    dinic.add_edge(2 * u + 1, 2 * v, INF_CAP);\n                    dinic.add_edge(2 * v + 1, 2 * u, INF_CAP);\n                }\n            }\n        }\n\n        for (int i = 0; i < M; i++) {\n            int u = pid[hx[i]][hy[i]];\n            if (u != -1) dinic.add_edge(src, 2 * u, INF_CAP);\n        }\n        for (int i = 0; i < N; i++) {\n            int u = pid[px[i]][py[i]];\n            if (u != -1) dinic.add_edge(2 * u + 1, sink, INF_CAP);\n        }\n\n        long long flow = dinic.max_flow(src, sink);\n        vector<pair<int,int>> target_walls;\n        if (flow < INF_CAP / 2) {\n            vector<bool> visited(2 * V + 2, false);\n            queue<int> q;\n            visited[sink] = true; q.push(sink);\n            while (!q.empty()) {\n                int v = q.front(); q.pop();\n                for (auto &e : dinic.g[v])\n                    if (e.cap > 0 && !visited[e.to]) {\n                        visited[e.to] = true;\n                        q.push(e.to);\n                    }\n            }\n            for (int u = 0; u < V; u++) {\n                int in = 2 * u, out = 2 * u + 1;\n                if (!visited[in] && visited[out])\n                    target_walls.push_back(passable[u]);\n            }\n        }\n\n        string actions(M, '.');\n\n        if (!target_walls.empty()) {\n            struct HumanBFS {\n                vector<vector<int>> dist;\n                vector<vector<pair<int,int>>> parent;\n            };\n            vector<HumanBFS> bfs_data(M);\n            for (int i = 0; i < M; i++) {\n                HumanBFS hb;\n                hb.dist.assign(31, vector<int>(31, -1));\n                hb.parent.assign(31, vector<pair<int,int>>(31, {-1, -1}));\n                queue<pair<int,int>> q;\n                hb.dist[hx[i]][hy[i]] = 0;\n                q.push({hx[i], hy[i]});\n                while (!q.empty()) {\n                    auto [x, y] = q.front(); q.pop();\n                    for (int d = 0; d < 4; d++) {\n                        int nx = x + dx[d], ny = y + dy[d];\n                        if (nx >= 1 && nx <= 30 && ny >= 1 && ny <= 30 && grid[nx][ny] == 0 && hb.dist[nx][ny] == -1) {\n                            hb.dist[nx][ny] = hb.dist[x][y] + 1;\n                            hb.parent[nx][ny] = {x, y};\n                            q.push({nx, ny});\n                        }\n                    }\n                }\n                bfs_data[i] = hb;\n            }\n\n            int Wcnt = target_walls.size();\n            vector<bool> wall_assigned(Wcnt, false);\n            vector<int> assigned_wall(M, -1), target_nx(M, -1), target_ny(M, -1);\n\n            for (int i = 0; i < M; i++) {\n                int best_w = -1, best_dist = INF_CAP, best_nx = -1, best_ny = -1;\n                for (int w = 0; w < Wcnt; w++) {\n                    if (wall_assigned[w]) continue;\n                    auto [wx, wy] = target_walls[w];\n                    int mind = INF_CAP, mnx = -1, mny = -1;\n                    for (int d = 0; d < 4; d++) {\n                        int nx = wx + dx[d], ny = wy + dy[d];\n                        if (nx >= 1 && nx <= 30 && ny >= 1 && ny <= 30 && grid[nx][ny] == 0) {\n                            int dist = bfs_data[i].dist[nx][ny];\n                            if (dist != -1 && dist < mind) {\n                                mind = dist;\n                                mnx = nx; mny = ny;\n                            }\n                        }\n                    }\n                    if (mind < best_dist) {\n                        best_dist = mind;\n                        best_w = w;\n                        best_nx = mnx; best_ny = mny;\n                    }\n                }\n                if (best_w != -1) {\n                    assigned_wall[i] = best_w;\n                    wall_assigned[best_w] = true;\n                    target_nx[i] = best_nx;\n                    target_ny[i] = best_ny;\n                }\n            }\n\n            for (int i = 0; i < M; i++) {\n                if (assigned_wall[i] == -1) continue;\n                int nx = target_nx[i], ny = target_ny[i];\n                if (nx == -1) continue;\n                int d = bfs_data[i].dist[nx][ny];\n                if (d == 0) {\n                    auto [wx, wy] = target_walls[assigned_wall[i]];\n                    if (wx < hx[i]) actions[i] = 'u';\n                    else if (wx > hx[i]) actions[i] = 'd';\n                    else if (wy < hy[i]) actions[i] = 'l';\n                    else if (wy > hy[i]) actions[i] = 'r';\n                } else {\n                    int cx = nx, cy = ny;\n                    while (true) {\n                        auto [px, py] = bfs_data[i].parent[cx][cy];\n                        if (px == hx[i] && py == hy[i]) break;\n                        cx = px; cy = py;\n                    }\n                    if (cx < hx[i]) actions[i] = 'U';\n                    else if (cx > hx[i]) actions[i] = 'D';\n                    else if (cy < hy[i]) actions[i] = 'L';\n                    else if (cy > hy[i]) actions[i] = 'R';\n                }\n            }\n\n            set<pair<int,int>> build_set;\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 wx = hx[i], wy = hy[i];\n                    if (c == 'u') wx--;\n                    else if (c == 'd') wx++;\n                    else if (c == 'l') wy--;\n                    else if (c == 'r') wy++;\n                    build_set.insert({wx, wy});\n                }\n            }\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 nx = hx[i], ny = hy[i];\n                    if (c == 'U') nx--;\n                    else if (c == 'D') nx++;\n                    else if (c == 'L') ny--;\n                    else if (c == 'R') ny++;\n                    if (build_set.count({nx, ny})) actions[i] = '.';\n                }\n            }\n        }\n\n        for (int i = 0; i < M; i++) {\n            if (actions[i] == '.') {\n                int best_dist = dist_pet[hx[i]][hy[i]];\n                char best_c = '.';\n                char moves[4] = {'U', 'D', 'L', 'R'};\n                for (int d = 0; d < 4; d++) {\n                    int nx = hx[i] + dx[d], ny = hy[i] + dy[d];\n                    if (nx >= 1 && nx <= 30 && ny >= 1 && ny <= 30 && grid[nx][ny] == 0) {\n                        if (dist_pet[nx][ny] > best_dist) {\n                            best_dist = dist_pet[nx][ny];\n                            best_c = moves[d];\n                        }\n                    }\n                }\n                actions[i] = best_c;\n            }\n        }\n\n        cout << actions << endl;\n\n        for (int i = 0; i < M; i++) {\n            char c = actions[i];\n            if (c == 'u') grid[hx[i] - 1][hy[i]] = 1;\n            else if (c == 'd') grid[hx[i] + 1][hy[i]] = 1;\n            else if (c == 'l') grid[hx[i]][hy[i] - 1] = 1;\n            else if (c == 'r') grid[hx[i]][hy[i] + 1] = 1;\n            else if (c == 'U') hx[i]--;\n            else if (c == 'D') hx[i]++;\n            else if (c == 'L') hy[i]--;\n            else if (c == 'R') hy[i]++;\n        }\n\n        for (int i = 0; i < N; i++) {\n            string s; cin >> s;\n            if (s == \".\") continue;\n            for (char c : s) {\n                if (c == 'U') px[i]--;\n                else if (c == 'D') px[i]++;\n                else if (c == 'L') py[i]--;\n                else if (c == 'R') py[i]++;\n            }\n        }\n    }\n    return 0;\n}","ahc009":"#include <iostream>\n#include <string>\n#include <vector>\n#include <array>\n#include <algorithm>\n#include <random>\n#include <cmath>\n\nusing namespace std;\n\nconst int L = 200;\nconst int H = 20, W = 20;\nconst int N = H * W;\n\nint start_id, target_id;\ndouble p;\nint next_cell[4][N];\ndouble p_stay[4][N];\ndouble p_move[4][N];\nchar dir_chars[4] = {'U', 'D', 'L', 'R'};\ndouble V[201][N]; // V[remaining steps][cell]\n\n// Evaluate exact expected S of a fixed string of length L\ndouble evaluate(const string& s) {\n    array<double, N> prob;\n    prob.fill(0.0);\n    prob[start_id] = 1.0;\n    double er = 0.0;\n    for (int step = 0; step < L; ++step) {\n        array<double, N> next_prob;\n        next_prob.fill(0.0);\n        int d;\n        char c = s[step];\n        if (c == 'U') d = 0;\n        else if (c == 'D') d = 1;\n        else if (c == 'L') d = 2;\n        else d = 3;\n        for (int i = 0; i < N; ++i) {\n            double pr = prob[i];\n            if (pr == 0.0) continue;\n            double stay = p_stay[d][i];\n            double move = p_move[d][i];\n            next_prob[i] += pr * stay;\n            if (move > 0.0) {\n                int nxt = next_cell[d][i];\n                if (nxt == target_id) {\n                    er += pr * move * (401 - (step + 1));\n                } else {\n                    next_prob[nxt] += pr * move;\n                }\n            }\n        }\n        prob = move(next_prob);\n    }\n    return er;\n}\n\nstruct BeamState {\n    string moves;\n    array<double, N> prob;\n    double er;\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    cin >> si >> sj >> ti >> tj >> p;\n    start_id = si * W + sj;\n    target_id = ti * W + tj;\n    \n    vector<string> h(20), v(20);\n    for (int i = 0; i < 20; ++i) cin >> h[i];\n    for (int i = 0; i < 19; ++i) cin >> v[i]; // 19 rows of 20 chars\n    \n    // Precompute walls, next cells, and move/stay probabilities\n    bool wall[4][N];\n    int di[4] = {-1, 1, 0, 0};\n    int dj[4] = {0, 0, -1, 1};\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = i * W + j;\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + di[d];\n                int nj = j + dj[d];\n                bool w = true;\n                if (ni >= 0 && ni < H && nj >= 0 && nj < W) {\n                    if (d == 0) {        // U\n                        if (v[i-1][j] == '0') w = false;\n                    } else if (d == 1) { // D\n                        if (v[i][j] == '0') w = false;\n                    } else if (d == 2) { // L\n                        if (h[i][j-1] == '0') w = false;\n                    } else {             // R\n                        if (h[i][j] == '0') w = false;\n                    }\n                }\n                wall[d][id] = w;\n                if (!w) {\n                    next_cell[d][id] = ni * W + nj;\n                } else {\n                    next_cell[d][id] = id;\n                }\n                if (w) {\n                    p_stay[d][id] = 1.0;\n                    p_move[d][id] = 0.0;\n                } else {\n                    p_stay[d][id] = p;\n                    p_move[d][id] = 1.0 - p;\n                }\n            }\n        }\n    }\n    \n    // Dynamic programming for adaptive upper bound V\n    for (int k = 0; k <= L; ++k) fill(V[k], V[k] + N, 0.0);\n    for (int k = 1; k <= L; ++k) {\n        double target_reward = 200.0 + k; // 401 - turn, turn = 201 - k\n        for (int i = 0; i < N; ++i) {\n            if (i == target_id) continue;\n            double best = 0.0;\n            for (int d = 0; d < 4; ++d) {\n                double stay = p_stay[d][i];\n                double move = p_move[d][i];\n                double val;\n                if (move == 0.0) {\n                    val = V[k-1][i];\n                } else {\n                    int nxt = next_cell[d][i];\n                    double move_val = (nxt == target_id) ? target_reward : V[k-1][nxt];\n                    val = stay * V[k-1][i] + move * move_val;\n                }\n                if (val > best) best = val;\n            }\n            V[k][i] = best;\n        }\n    }\n    \n    // Beam search\n    const int K = 150;\n    vector<BeamState> beam;\n    {\n        BeamState init;\n        init.moves = \"\";\n        init.prob.fill(0.0);\n        init.prob[start_id] = 1.0;\n        init.er = 0.0;\n        init.score = V[L][start_id];\n        beam.push_back(init);\n    }\n    \n    for (int step = 0; step < L; ++step) {\n        vector<BeamState> next_beam;\n        next_beam.reserve(beam.size() * 4);\n        for (const auto& st : beam) {\n            for (int d = 0; d < 4; ++d) {\n                BeamState ns;\n                ns.moves = st.moves + dir_chars[d];\n                ns.prob.fill(0.0);\n                ns.er = st.er;\n                for (int i = 0; i < N; ++i) {\n                    double pr = st.prob[i];\n                    if (pr == 0.0) continue;\n                    double stay = p_stay[d][i];\n                    double move = p_move[d][i];\n                    ns.prob[i] += pr * stay;\n                    if (move > 0.0) {\n                        int nxt = next_cell[d][i];\n                        if (nxt == target_id) {\n                            ns.er += pr * move * (401 - (step + 1));\n                        } else {\n                            ns.prob[nxt] += pr * move;\n                        }\n                    }\n                }\n                int R = L - (step + 1);\n                double future = 0.0;\n                for (int i = 0; i < N; ++i) {\n                    future += ns.prob[i] * V[R][i];\n                }\n                ns.score = ns.er + future;\n                next_beam.push_back(ns);\n            }\n        }\n        if (next_beam.size() > K) {\n            nth_element(next_beam.begin(), next_beam.begin() + K, next_beam.end(),\n                [](const BeamState& a, const BeamState& b) { return a.score > b.score; });\n            next_beam.resize(K);\n        } else {\n            sort(next_beam.begin(), next_beam.end(),\n                [](const BeamState& a, const BeamState& b) { return a.score > b.score; });\n        }\n        beam = move(next_beam);\n    }\n    \n    // Pick best from final beam\n    auto best_it = max_element(beam.begin(), beam.end(),\n        [](const BeamState& a, const BeamState& b) { return a.er < b.er; });\n    string best_s = best_it->moves;\n    double best_er = best_it->er;\n    \n    // Local refinement\n    random_device rd;\n    mt19937 rng(rd());\n    uniform_int_distribution<int> pos_dist(0, L-1);\n    uniform_int_distribution<int> dir_dist(0, 3);\n    for (int it = 0; it < 1500; ++it) {\n        int pos = pos_dist(rng);\n        char old_char = best_s[pos];\n        char new_char = dir_chars[dir_dist(rng)];\n        if (new_char == old_char) continue;\n        best_s[pos] = new_char;\n        double new_er = evaluate(best_s);\n        if (new_er > best_er) {\n            best_er = new_er;\n        } else {\n            best_s[pos] = old_char;\n        }\n    }\n    \n    cout << best_s << \"\\n\";\n    return 0;\n}","ahc010":"#include <iostream>\n#include <string>\n#include <vector>\n#include <cmath>\n#include <chrono>\n#include <cstring>\n#include <cstdint>\n\nusing namespace std;\n\n// xorshift random generator\nuint64_t xor64_state = 88172645463325252ULL;\nuint64_t xor64() {\n    xor64_state ^= xor64_state << 13;\n    xor64_state ^= xor64_state >> 7;\n    xor64_state ^= xor64_state << 17;\n    return xor64_state;\n}\nint rand_int(int n) {\n    return xor64() % n;\n}\ndouble rand_double() {\n    return (xor64() >> 11) * (1.0 / (1ULL << 53));\n}\n\nint main() {\n    // seed\n    xor64_state = chrono::steady_clock::now().time_since_epoch().count();\n    \n    int init[900];\n    for (int i = 0; i < 30; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < 30; ++j) {\n            init[i * 30 + j] = s[j] - '0';\n        }\n    }\n    \n    // rotation mapping: rotate[t][r] = type after r CCW rotations (r=0..3)\n    int rot1[8] = {1, 2, 3, 0, 5, 4, 7, 6};\n    int rotate[8][4];\n    for (int t = 0; t < 8; ++t) {\n        rotate[t][0] = t;\n        for (int r = 1; r < 4; ++r) {\n            rotate[t][r] = rot1[rotate[t][r-1]];\n        }\n    }\n    \n    // neighbor index for each direction (0=left,1=up,2=right,3=down), -1 if boundary\n    int neig[900][4];\n    for (int i = 0; i < 30; ++i) {\n        for (int j = 0; j < 30; ++j) {\n            int idx = i * 30 + j;\n            neig[idx][0] = (j > 0) ? idx - 1 : -1;\n            neig[idx][1] = (i > 0) ? idx - 30 : -1;\n            neig[idx][2] = (j < 29) ? idx + 1 : -1;\n            neig[idx][3] = (i < 29) ? idx + 30 : -1;\n        }\n    }\n    \n    // visited array for evaluation (directed edges)\n    int vis[900][4] = {0};\n    int mark = 0;\n    \n    // transition table from problem statement\n    const int to[8][4] = {\n        {1, 0, -1, -1},\n        {3, -1, -1, 0},\n        {-1, -1, 3, 2},\n        {-1, 2, 1, -1},\n        {1, 0, 3, 2},\n        {3, 2, 1, 0},\n        {2, -1, 0, -1},\n        {-1, 3, -1, 1}\n    };\n    \n    // evaluation: returns L1 * L2 (or 0 if <2 loops)\n    auto evaluate = [&](const int* cur) -> int {\n        mark++;\n        int max1 = 0, max2 = 0;\n        for (int i = 0; i < 900; ++i) {\n            int t = cur[i];\n            for (int d = 0; d < 4; ++d) {\n                if (vis[i][d] == mark) continue;\n                int d0 = to[t][d];\n                if (d0 < 0) continue;\n                int si = i, sd = d;\n                int ci = i, cd = d;\n                int len = 0;\n                while (1) {\n                    vis[ci][cd] = mark;\n                    int d2 = to[cur[ci]][cd];\n                    if (d2 < 0) { len = -1; break; }\n                    int ni = neig[ci][d2];\n                    if (ni < 0) { len = -1; break; }\n                    int nd = (d2 + 2) & 3;\n                    len++;\n                    ci = ni; cd = nd;\n                    if (ci == si && cd == sd) break;\n                }\n                if (len > 0) {\n                    if (len > max1) { max2 = max1; max1 = len; }\n                    else if (len > max2) { max2 = len; }\n                }\n            }\n        }\n        if (max2 == 0) return 0;\n        return max1 * max2;\n    };\n    \n    int cur[900];\n    int rot[900] = {0};\n    for (int i = 0; i < 900; ++i) cur[i] = init[i];\n    \n    int cur_score = evaluate(cur);\n    int best_score = cur_score;\n    int best_rot[900];\n    memcpy(best_rot, rot, sizeof(rot));\n    \n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.95;\n    double T = 100000.0;\n    double alpha = 0.999947;\n    \n    while (true) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n        if (elapsed >= time_limit) break;\n        \n        int idx = rand_int(900);\n        int delta = (rand_int(3) + 1); // 1, 2, or 3\n        int old_rot = rot[idx];\n        int new_rot = (old_rot + delta) & 3;\n        int old_type = cur[idx];\n        int new_type = rotate[init[idx]][new_rot];\n        if (new_type == old_type) continue;\n        \n        cur[idx] = new_type;\n        rot[idx] = new_rot;\n        int new_score = evaluate(cur);\n        \n        if (new_score >= cur_score || rand_double() < exp((new_score - cur_score) / T)) {\n            cur_score = new_score;\n            if (new_score > best_score) {\n                best_score = new_score;\n                memcpy(best_rot, rot, sizeof(rot));\n            }\n        } else {\n            cur[idx] = old_type;\n            rot[idx] = old_rot;\n        }\n        T *= alpha;\n    }\n    \n    // output 900 digits\n    for (int i = 0; i < 900; ++i) {\n        cout << best_rot[i];\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\nusing uint64 = unsigned long long;\nusing uint16 = unsigned short;\n\nconst int MAXN = 10;\nconst int MAXV = MAXN * MAXN; // 100\n\nint N, T, V;\nint EMPTY_ID;\n\n// Directions: 0:left, 1:up, 2:right, 3:down\nint dir_bit[4] = {1, 2, 4, 8};\nint opp_dir[4] = {2, 3, 0, 1};\nint drow[4] = {0, -1, 0, 1};\nint dcol[4] = {-1, 0, 1, 0};\nchar move_chars[4] = {'L', 'U', 'R', 'D'};\nunordered_map<char, char> opp_char_map = {{'L','R'},{'R','L'},{'U','D'},{'D','U'}};\n\nint tile_has[16][4];\nuint16 mask_has[4], mask_no[4];\n\nvoid precompute_tile_masks() {\n    for (int t=0; t<16; ++t) {\n        for (int d=0; d<4; ++d) {\n            tile_has[t][d] = (t & dir_bit[d]) ? 1 : 0;\n        }\n    }\n    for (int d=0; d<4; ++d) {\n        uint16 m_has = 0;\n        for (int t=0; t<16; ++t) if (tile_has[t][d]) m_has |= (1<<t);\n        mask_has[d] = m_has;\n        mask_no[d] = (~m_has) & 0xFFFF;\n    }\n}\n\n// ---------- CSP (target board reconstruction) ----------\nuint16 dom[MAXN][MAXN];\nint csp_board[MAXN][MAXN];\nbool assigned[MAXN][MAXN];\nint csp_tile_counts[16];\n\nbool dfs_csp(int assigned_cnt) {\n    if (assigned_cnt == V) return true;\n    int best_i=-1, best_j=-1, best_pop=999;\n    for (int i=0; i<N; ++i) {\n        for (int j=0; j<N; ++j) {\n            if (!assigned[i][j]) {\n                int pop = __builtin_popcount(dom[i][j]);\n                if (pop < best_pop) {\n                    best_pop = pop;\n                    best_i = i; best_j = j;\n                }\n            }\n        }\n    }\n    if (best_pop == 0) return false;\n    int i=best_i, j=best_j;\n    uint16 cur_dom = dom[i][j];\n    for (int t=0; t<16; ++t) {\n        if (!(cur_dom & (1<<t))) continue;\n        if (csp_tile_counts[t] == 0) continue;\n        bool ok = true;\n        for (int d=0; d<4; ++d) {\n            int ni = i + drow[d], nj = j + dcol[d];\n            if (ni<0 || ni>=N || nj<0 || nj>=N) continue;\n            if (assigned[ni][nj]) {\n                int nt = csp_board[ni][nj];\n                if (tile_has[t][d] != tile_has[nt][opp_dir[d]]) {\n                    ok = false; break;\n                }\n            }\n        }\n        if (!ok) continue;\n        csp_tile_counts[t]--;\n        assigned[i][j] = true;\n        csp_board[i][j] = t;\n        vector<tuple<int,int,uint16>> saved;\n        for (int d=0; d<4; ++d) {\n            int ni = i + drow[d], nj = j + dcol[d];\n            if (ni<0 || ni>=N || nj<0 || nj>=N) continue;\n            if (!assigned[ni][nj]) {\n                uint16 old = dom[ni][nj];\n                uint16 new_dom;\n                if (tile_has[t][d]) {\n                    new_dom = old & mask_has[opp_dir[d]];\n                } else {\n                    new_dom = old & mask_no[opp_dir[d]];\n                }\n                if (new_dom == 0) { ok = false; break; }\n                if (new_dom != old) {\n                    dom[ni][nj] = new_dom;\n                    saved.push_back({ni,nj,old});\n                }\n            }\n        }\n        if (ok) {\n            if (dfs_csp(assigned_cnt+1)) return true;\n        }\n        for (auto& s : saved) {\n            dom[get<0>(s)][get<1>(s)] = get<2>(s);\n        }\n        assigned[i][j] = false;\n        csp_board[i][j] = -1;\n        csp_tile_counts[t]++;\n    }\n    return false;\n}\n\n// ---------- Hungarian algorithm ----------\nvector<int> hungarian(const vector<vector<int>>& cost) {\n    int n = cost.size();\n    if (n == 0) return {};\n    vector<int> u(n+1, 0), v(n+1, 0), p(n+1, 0), way(n+1, 0);\n    const int INF = 1e9;\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) {\n                if (!used[j]) {\n                    int cur = cost[i0-1][j-1] - u[i0] - v[j];\n                    if (cur < minv[j]) { minv[j] = cur; way[j] = j0; }\n                    if (minv[j] < delta) { delta = minv[j]; 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    vector<int> assignment(n, -1);\n    for (int j=1; j<=n; ++j) {\n        if (p[j] > 0) {\n            assignment[p[j]-1] = j-1;\n        }\n    }\n    return assignment;\n}\n\n// ---------- Node for beam search ----------\nstruct Node {\n    uint8_t board[MAXV];\n    int empty;\n    int h;\n    uint64 hash;\n    int parent;\n    char move;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> T;\n    V = N * N;\n    EMPTY_ID = V - 1; // empty tile gets this ID\n\n    precompute_tile_masks();\n\n    vector<string> grid(N);\n    for (int i=0; i<N; ++i) cin >> grid[i];\n\n    int init_type[MAXN][MAXN];\n    int tile_counts[16] = {0};\n    for (int i=0; i<N; ++i) {\n        for (int j=0; j<N; ++j) {\n            char c = grid[i][j];\n            int t = (c >= '0' && c <= '9') ? (c - '0') : (c - 'a' + 10);\n            init_type[i][j] = t;\n            tile_counts[t]++;\n        }\n    }\n\n    // ---------- target board CSP ----------\n    for (int i=0; i<N; ++i) for (int j=0; j<N; ++j) {\n        uint16 mask = 0xFFFF;\n        if (i == 0) mask &= mask_no[1];      // no up\n        if (i == N-1) mask &= mask_no[3];    // no down\n        if (j == 0) mask &= mask_no[0];      // no left\n        if (j == N-1) mask &= mask_no[2];    // no right\n        if (i == N-2 && j == N-1) mask &= mask_no[3]; // no down to empty\n        if (i == N-1 && j == N-2) mask &= mask_no[2]; // no right to empty\n        if (i == N-1 && j == N-1) mask = (1 << 0);    // only empty tile\n        else mask &= ~(1 << 0);              // empty tile already used\n        dom[i][j] = mask;\n    }\n    memset(assigned, 0, sizeof(assigned));\n    memset(csp_board, -1, sizeof(csp_board));\n    memcpy(csp_tile_counts, tile_counts, sizeof(tile_counts));\n    assigned[N-1][N-1] = true;\n    csp_board[N-1][N-1] = 0;\n    csp_tile_counts[0]--;\n    dom[N-1][N-1] = 0;\n\n    bool csp_ok = dfs_csp(1);\n    assert(csp_ok); // problem guarantees solvable\n\n    // ---------- ID assignment and matching ----------\n    int init_id[MAXN][MAXN];\n    int id_to_type[MAXV];\n    int id_count = 0;\n    for (int i=0; i<N; ++i) for (int j=0; j<N; ++j) {\n        if (init_type[i][j] == 0) {\n            init_id[i][j] = EMPTY_ID;\n            id_to_type[EMPTY_ID] = 0;\n        } else {\n            init_id[i][j] = id_count;\n            id_to_type[id_count] = init_type[i][j];\n            id_count++;\n        }\n    }\n\n    int targetPos[MAXV];\n    targetPos[EMPTY_ID] = (N-1)*N + (N-1);\n\n    vector<int> ids_of_type[16];\n    vector<int> cells_of_type[16];\n    for (int i=0; i<N; ++i) for (int j=0; j<N; ++j) {\n        int t = csp_board[i][j];\n        if (t != 0) {\n            cells_of_type[t].push_back(i*N + j);\n        }\n    }\n    for (int id=0; id<EMPTY_ID; ++id) {\n        int t = id_to_type[id];\n        ids_of_type[t].push_back(id);\n    }\n\n    // initial positions of IDs\n    int initPos[MAXV];\n    for (int i=0; i<N; ++i) for (int j=0; j<N; ++j) {\n        initPos[init_id[i][j]] = i*N + j;\n    }\n\n    for (int t=1; t<16; ++t) {\n        int n = ids_of_type[t].size();\n        if (n == 0) continue;\n        vector<vector<int>> cost(n, vector<int>(n));\n        for (int i=0; i<n; ++i) {\n            int id = ids_of_type[t][i];\n            int r1 = initPos[id] / N, c1 = initPos[id] % N;\n            for (int j=0; j<n; ++j) {\n                int cell = cells_of_type[t][j];\n                int r2 = cell / N, c2 = cell % N;\n                cost[i][j] = abs(r1-r2) + abs(c1-c2);\n            }\n        }\n        vector<int> assignment = hungarian(cost);\n        for (int i=0; i<n; ++i) {\n            int id = ids_of_type[t][i];\n            int j = assignment[i];\n            targetPos[id] = cells_of_type[t][j];\n        }\n    }\n\n    // ---------- Manhattan distance table ----------\n    int manDist[MAXV][MAXV];\n    for (int id=0; id<V; ++id) {\n        int tr = targetPos[id] / N, tc = targetPos[id] % N;\n        for (int cell=0; cell<V; ++cell) {\n            int r = cell / N, c = cell % N;\n            manDist[id][cell] = abs(tr-r) + abs(tc-c);\n        }\n    }\n\n    // ---------- Zobrist hashing ----------\n    mt19937_64 rng(12345);\n    uint64 zob[MAXV][MAXV];\n    for (int id=0; id<V; ++id)\n        for (int cell=0; cell<V; ++cell)\n            zob[id][cell] = rng();\n\n    // ---------- Initial state ----------\n    Node root;\n    for (int i=0; i<N; ++i)\n        for (int j=0; j<N; ++j)\n            root.board[i*N+j] = init_id[i][j];\n\n    int init_h = 0;\n    uint64 init_hash = 0;\n    for (int cell=0; cell<V; ++cell) {\n        int id = root.board[cell];\n        if (id == EMPTY_ID) root.empty = cell;\n        init_h += manDist[id][cell];\n        init_hash ^= zob[id][cell];\n    }\n    root.h = init_h;\n    root.hash = init_hash;\n    root.parent = -1;\n    root.move = 0;\n\n    if (init_h == 0) {\n        cout << \"\" << endl;\n        return 0;\n    }\n\n    // ---------- Beam search ----------\n    vector<Node> nodes;\n    nodes.reserve(400000);\n    unordered_set<uint64_t> global_hash;\n    global_hash.reserve(400000);\n\n    nodes.push_back(root);\n    global_hash.insert(root.hash);\n\n    vector<int> current_beam = {0};\n    int goal_node = -1;\n    int best_h_node = 0;\n    int best_h = init_h;\n    const int beam_width = 150;\n\n    clock_t start_time = clock();\n    const double TIME_LIMIT = 2.8 * CLOCKS_PER_SEC;\n\n    for (int depth = 0; depth < T; ++depth) {\n        if (clock() - start_time > TIME_LIMIT) break;\n        vector<int> next_nodes;\n        for (int idx : current_beam) {\n            Node& cur = nodes[idx];\n            int e = cur.empty;\n            int r = e / N, c = e % N;\n            for (int d=0; d<4; ++d) {\n                int nr = r + drow[d], nc = c + dcol[d];\n                if (nr<0 || nr>=N || nc<0 || nc>=N) continue;\n                if (cur.move != 0) {\n                    if (move_chars[d] == opp_char_map[cur.move]) continue;\n                }\n                int neighbor = nr*N + nc;\n                int tileID = cur.board[neighbor];\n\n                Node next;\n                memcpy(next.board, cur.board, V * sizeof(uint8_t));\n                next.board[e] = tileID;\n                next.board[neighbor] = EMPTY_ID;\n                next.empty = neighbor;\n\n                uint64 new_hash = cur.hash;\n                new_hash ^= zob[tileID][e] ^ zob[tileID][neighbor] ^ zob[EMPTY_ID][neighbor] ^ zob[EMPTY_ID][e];\n                next.hash = new_hash;\n                if (global_hash.count(new_hash)) continue;\n\n                int new_h = cur.h;\n                new_h += manDist[tileID][e] - manDist[tileID][neighbor];\n                new_h += manDist[EMPTY_ID][neighbor] - manDist[EMPTY_ID][e];\n                next.h = new_h;\n                next.parent = idx;\n                next.move = move_chars[d];\n\n                if (new_h == 0) goal_node = nodes.size();\n\n                nodes.push_back(next);\n                global_hash.insert(new_hash);\n                next_nodes.push_back(nodes.size()-1);\n\n                if (new_h < best_h) {\n                    best_h = new_h;\n                    best_h_node = nodes.size()-1;\n                }\n                if (goal_node != -1) break;\n            }\n            if (goal_node != -1) break;\n        }\n        if (goal_node != -1) break;\n        if (next_nodes.empty()) break;\n\n        sort(next_nodes.begin(), next_nodes.end(), [&](int a, int b) {\n            return nodes[a].h < nodes[b].h;\n        });\n        if (next_nodes.size() > beam_width) next_nodes.resize(beam_width);\n        current_beam = move(next_nodes);\n    }\n\n    // ---------- Output ----------\n    int out_node = (goal_node != -1) ? goal_node : best_h_node;\n    string seq;\n    while (nodes[out_node].parent != -1) {\n        seq.push_back(nodes[out_node].move);\n        out_node = nodes[out_node].parent;\n    }\n    reverse(seq.begin(), seq.end());\n    if ((int)seq.length() > T) seq = seq.substr(0, T);\n    cout << seq << endl;\n\n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <numeric>\n#include <cstdlib>\n\nusing namespace std;\n\nstruct Point { int x, y; };\nstruct Line { int p1x, p1y, p2x, p2y; };\n\n// global targets\nvector<int> a(11);\nint total_attendees = 0;\n\nlong long cross(const Line& L, const Point& p) {\n    long long dx = L.p2x - L.p1x;\n    long long dy = L.p2y - L.p1y;\n    long long px = p.x - L.p1x;\n    long long py = p.y - L.p1y;\n    return dx * py - dy * px;\n}\n\nbool line_intersects_circle(const Line& L) {\n    long long dx = L.p2x - L.p1x;\n    long long dy = L.p2y - L.p1y;\n    long long cross_val = std::llabs((long long)L.p1x * L.p2y - (long long)L.p1y * L.p2x);\n    long long lhs = cross_val * cross_val;\n    long long rhs = 100000000LL * (dx*dx + dy*dy);\n    return lhs <= rhs;\n}\n\nint side(const Line& L, const Point& p) {\n    long long c = cross(L, p);\n    if (c > 0) return 1;\n    if (c < 0) return -1;\n    return 0;\n}\n\nstruct State {\n    vector<int> cell_of_point;\n    vector<int> cell_count;\n    vector<vector<int>> cell_points;\n    int score;\n};\n\nint compute_score_from_counts(const vector<int>& cell_count) {\n    int b[11] = {0};\n    for (int cnt : cell_count) {\n        if (cnt > 0 && cnt <= 10) b[cnt]++;\n    }\n    int score = 0;\n    for (int d = 1; d <= 10; ++d) score += min(a[d], b[d]);\n    return score;\n}\n\nState build_initial_state(const vector<Point>& pts) {\n    State st;\n    int N = pts.size();\n    st.cell_of_point.assign(N, 0);\n    st.cell_count = {N};\n    st.cell_points = { vector<int>(N) };\n    iota(st.cell_points[0].begin(), st.cell_points[0].end(), 0);\n    st.score = compute_score_from_counts(st.cell_count);\n    return st;\n}\n\ntuple<vector<int>, vector<int>, int> simulate(const State& st, const Line& L, const vector<Point>& pts) {\n    int N = pts.size();\n    int C = st.cell_count.size();\n    vector<int> new_count(2*C, 0);\n    vector<int> bits(N);\n    long long dx = L.p2x - L.p1x;\n    long long dy = L.p2y - L.p1y;\n    for (int i = 0; i < N; ++i) {\n        int old_c = st.cell_of_point[i];\n        long long px = pts[i].x - L.p1x;\n        long long py = pts[i].y - L.p1y;\n        long long c = dx * py - dy * px;\n        if (c == 0) return { {}, {}, -1 };\n        int bit = (c > 0) ? 1 : 0;\n        bits[i] = bit;\n        int nc = old_c * 2 + bit;\n        new_count[nc]++;\n    }\n    int score = compute_score_from_counts(new_count);\n    return {new_count, bits, score};\n}\n\nvoid apply_line(State& st, const Line& L, const vector<int>& new_count, const vector<int>& bits, const vector<Point>& pts) {\n    int N = pts.size();\n    int C = st.cell_count.size();\n    vector<int> new_cell_id(2*C, -1);\n    int new_C = 0;\n    for (int c = 0; c < 2*C; ++c) {\n        if (new_count[c] > 0) {\n            new_cell_id[c] = new_C++;\n        }\n    }\n    st.cell_count.resize(new_C);\n    st.cell_points.assign(new_C, vector<int>());\n    for (int c = 0; c < 2*C; ++c) {\n        if (new_count[c] > 0) {\n            int nid = new_cell_id[c];\n            st.cell_count[nid] = new_count[c];\n            st.cell_points[nid].reserve(new_count[c]);\n        }\n    }\n    for (int i = 0; i < N; ++i) {\n        int old_c = st.cell_of_point[i];\n        int nid = new_cell_id[old_c * 2 + bits[i]];\n        st.cell_of_point[i] = nid;\n        st.cell_points[nid].push_back(i);\n    }\n    st.score = compute_score_from_counts(st.cell_count);\n}\n\n// candidate generators\nLine random_line_through_cake(mt19937& rng) {\n    uniform_int_distribution<int> dist_coord(-10000, 10000);\n    uniform_int_distribution<int> dist_d(-1000, 1000);\n    while (true) {\n        int x = dist_coord(rng);\n        int y = dist_coord(rng);\n        if ((long long)x*x + (long long)y*y < 100000000LL) {\n            int dx = dist_d(rng);\n            int dy = dist_d(rng);\n            if (dx == 0 && dy == 0) dx = 1;\n            return {x, y, x+dx, y+dy};\n        }\n    }\n}\n\nLine random_cell_split_line(const State& st, const vector<Point>& pts, mt19937& rng) {\n    const auto& cell_points = st.cell_points;\n    vector<int> valid_cells;\n    for (int c = 0; c < (int)cell_points.size(); ++c) {\n        if (cell_points[c].size() >= 2) valid_cells.push_back(c);\n    }\n    if (valid_cells.empty()) {\n        return random_line_through_cake(rng);\n    }\n    uniform_int_distribution<int> dist_cell(0, valid_cells.size()-1);\n    int c = valid_cells[dist_cell(rng)];\n    const auto& pvec = cell_points[c];\n    uniform_int_distribution<int> dist_pt(0, pvec.size()-1);\n    int i1 = pvec[dist_pt(rng)];\n    int i2 = pvec[dist_pt(rng)];\n    while (i2 == i1) i2 = pvec[dist_pt(rng)];\n    Point p1 = pts[i1], p2 = pts[i2];\n    int mx = (p1.x + p2.x) / 2;\n    int my = (p1.y + p2.y) / 2;\n    uniform_int_distribution<int> dist_d(-100, 100);\n    int dx = dist_d(rng);\n    int dy = dist_d(rng);\n    if (dx == 0 && dy == 0) dx = 1;\n    Line L = {mx, my, mx+dx, my+dy};\n    int s1 = side(L, p1), s2 = side(L, p2);\n    if (s1 == s2 || s1 == 0 || s2 == 0) {\n        swap(dx, dy); dx = -dx;\n        L = {mx, my, mx+dx, my+dy};\n        s1 = side(L, p1); s2 = side(L, p2);\n        if (s1 == s2 || s1 == 0 || s2 == 0) {\n            return random_line_through_cake(rng);\n        }\n    }\n    return L;\n}\n\nLine random_separating_line(const vector<Point>& pts, int N, mt19937& rng) {\n    uniform_int_distribution<int> dist_pt(0, N-1);\n    int i1 = dist_pt(rng);\n    int i2 = dist_pt(rng);\n    while (i2 == i1) i2 = dist_pt(rng);\n    Point p1 = pts[i1], p2 = pts[i2];\n    int mx = (p1.x + p2.x) / 2;\n    int my = (p1.y + p2.y) / 2;\n    uniform_int_distribution<int> dist_d(-1000, 1000);\n    int dx = dist_d(rng);\n    int dy = dist_d(rng);\n    if (dx == 0 && dy == 0) dx = 1;\n    Line L = {mx, my, mx+dx, my+dy};\n    int s1 = side(L, p1), s2 = side(L, p2);\n    if (s1 == s2 || s1 == 0 || s2 == 0) {\n        swap(dx, dy); dx = -dx;\n        L = {mx, my, mx+dx, my+dy};\n        s1 = side(L, p1); s2 = side(L, p2);\n        if (s1 == s2 || s1 == 0 || s2 == 0) {\n            return random_line_through_cake(rng);\n        }\n    }\n    return L;\n}\n\nLine perturb_existing_line(const vector<Line>& lines, mt19937& rng) {\n    if (lines.empty()) return random_line_through_cake(rng);\n    uniform_int_distribution<int> dist_idx(0, lines.size()-1);\n    uniform_int_distribution<int> dist_delta(-200, 200);\n    uniform_int_distribution<int> dist_coord(0, 3);\n    Line L = lines[dist_idx(rng)];\n    int delta = dist_delta(rng);\n    int coord = dist_coord(rng);\n    if (coord == 0) L.p1x += delta;\n    else if (coord == 1) L.p1y += delta;\n    else if (coord == 2) L.p2x += delta;\n    else L.p2y += delta;\n    if (L.p1x == L.p2x && L.p1y == L.p2y) L.p1x += 1;\n    return L;\n}\n\nint main() {\n    ios::sync_with_stdio(false); cin.tie(0);\n    auto start_time = chrono::steady_clock::now();\n\n    int N, K; cin >> N >> K;\n    for (int d = 1; d <= 10; ++d) { cin >> a[d]; total_attendees += a[d]; }\n    vector<Point> pts(N);\n    for (int i = 0; i < N; ++i) cin >> pts[i].x >> pts[i].y;\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    State st = build_initial_state(pts);\n    vector<Line> lines;\n    int current_score = st.score;\n\n    const int NUM_GREEDY_CANDIDATES = 200;\n    const int NUM_LOCAL_CANDIDATES = 100;\n\n    // Greedy addition\n    while ((int)lines.size() < K && current_score < total_attendees) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n        if (elapsed > 2.5) break;\n\n        int best_score = current_score;\n        Line best_line;\n        vector<int> best_new_count, best_bits;\n\n        for (int t = 0; t < NUM_GREEDY_CANDIDATES; ++t) {\n            Line cand;\n            int type = uniform_int_distribution<int>(0, 9)(rng);\n            if (type < 2) {\n                cand = random_line_through_cake(rng);\n            } else if (type < 6) {\n                cand = random_cell_split_line(st, pts, rng);\n            } else if (type < 9) {\n                cand = random_separating_line(pts, N, rng);\n            } else {\n                cand = perturb_existing_line(lines, rng);\n            }\n            if (!line_intersects_circle(cand)) continue;\n            auto [new_count, bits, score] = simulate(st, cand, pts);\n            if (score < 0) continue;   // hit a strawberry\n            if (score > best_score) {\n                best_score = score;\n                best_line = cand;\n                best_new_count = std::move(new_count);\n                best_bits = std::move(bits);\n            }\n        }\n        if (best_score <= current_score) break;\n        apply_line(st, best_line, best_new_count, best_bits, pts);\n        lines.push_back(best_line);\n        current_score = best_score;\n    }\n\n    // Local search: remove and re-add\n    bool improved = true;\n    int local_iter = 0;\n    while (improved && current_score < total_attendees && local_iter < 3) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n        if (elapsed > 2.8) break;\n        improved = false;\n        local_iter++;\n        vector<int> order(lines.size());\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n        for (int idx : order) {\n            elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n            if (elapsed > 2.8) break;\n            Line old_line = lines[idx];\n            // build state without this line\n            State curr = build_initial_state(pts);\n            for (int j = 0; j < (int)lines.size(); ++j) {\n                if (j == idx) continue;\n                auto [new_count, bits, score] = simulate(curr, lines[j], pts);\n                // score must be valid here\n                apply_line(curr, lines[j], new_count, bits, pts);\n            }\n            int best_score = curr.score;\n            Line best_line;\n            vector<int> best_new_count, best_bits;\n\n            for (int t = 0; t < NUM_LOCAL_CANDIDATES; ++t) {\n                Line cand;\n                int type = uniform_int_distribution<int>(0, 9)(rng);\n                if (type < 2) cand = random_line_through_cake(rng);\n                else if (type < 6) cand = random_cell_split_line(curr, pts, rng);\n                else if (type < 9) cand = random_separating_line(pts, N, rng);\n                else cand = perturb_existing_line(lines, rng);\n                if (!line_intersects_circle(cand)) continue;\n                auto [new_count, bits, score] = simulate(curr, cand, pts);\n                if (score < 0) continue;\n                if (score > best_score) {\n                    best_score = score;\n                    best_line = cand;\n                    best_new_count = std::move(new_count);\n                    best_bits = std::move(bits);\n                }\n            }\n            if (best_score > curr.score) {\n                lines[idx] = best_line;\n                improved = true;\n            } else {\n                lines[idx] = old_line;\n            }\n        }\n        if (improved) {\n            st = build_initial_state(pts);\n            for (const Line& L : lines) {\n                auto [new_count, bits, score] = simulate(st, L, pts);\n                apply_line(st, L, new_count, bits, pts);\n            }\n            current_score = st.score;\n        }\n    }\n\n    // Output\n    cout << lines.size() << \"\\n\";\n    for (const Line& L : lines) {\n        cout << L.p1x << \" \" << L.p1y << \" \" << L.p2x << \" \" << L.p2y << \"\\n\";\n    }\n\n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <array>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nstruct Pt { int x, y; };\n\nint main() {\n    auto start_time = chrono::steady_clock::now();\n\n    // read input\n    int N, M;\n    cin >> N >> M;\n    vector<Pt> initial_dots(M);\n    for (int i = 0; i < M; i++) cin >> initial_dots[i].x >> initial_dots[i].y;\n\n    int c = (N - 1) / 2;\n    vector<vector<int>> weight(N, vector<int>(N));\n    long long S = 0;\n    long long initial_sum = 0;\n    for (int x = 0; x < N; x++) for (int y = 0; y < N; y++) {\n        weight[x][y] = (x - c) * (x - c) + (y - c) * (y - c) + 1;\n        S += weight[x][y];\n    }\n    for (auto& p : initial_dots) initial_sum += weight[p.x][p.y];\n\n    // segment check / mark function\n    auto segment_operation = [&](Pt a, Pt b, bool check_only,\n                                 vector<vector<bool>>& dot,\n                                 vector<vector<bool>>& used_h,\n                                 vector<vector<bool>>& used_v,\n                                 vector<vector<bool>>& used_d1,\n                                 vector<vector<bool>>& used_d2) -> bool {\n        int dx = b.x - a.x, dy = b.y - a.y;\n        int steps = max(abs(dx), abs(dy));\n        int sx = (dx == 0 ? 0 : (dx > 0 ? 1 : -1));\n        int sy = (dy == 0 ? 0 : (dy > 0 ? 1 : -1));\n        int cx = a.x, cy = a.y;\n        for (int s = 1; s <= steps; s++) {\n            int nx = cx + sx, ny = cy + sy;\n            if (s < steps) {\n                if (dot[nx][ny]) return false;\n            }\n            if (sx != 0 && sy == 0) { // horizontal\n                int x = min(cx, nx), y = cy;\n                if (check_only) { if (used_h[x][y]) return false; }\n                else used_h[x][y] = true;\n            } else if (sx == 0 && sy != 0) { // vertical\n                int x = cx, y = min(cy, ny);\n                if (check_only) { if (used_v[x][y]) return false; }\n                else used_v[x][y] = true;\n            } else if (sx == 1 && sy == 1) { // diagonal (1,1)\n                if (check_only) { if (used_d1[cx][cy]) return false; }\n                else used_d1[cx][cy] = true;\n            } else if (sx == -1 && sy == -1) { // diagonal (-1,-1) -> reverse of (1,1)\n                if (check_only) { if (used_d1[nx][ny]) return false; }\n                else used_d1[nx][ny] = true;\n            } else if (sx == 1 && sy == -1) { // diagonal (1,-1)\n                if (check_only) { if (used_d2[cx][cy]) return false; }\n                else used_d2[cx][cy] = true;\n            } else if (sx == -1 && sy == 1) { // diagonal (-1,1) -> reverse of (1,-1)\n                if (check_only) { if (used_d2[nx][ny]) return false; }\n                else used_d2[nx][ny] = true;\n            } else return false;\n            cx = nx; cy = ny;\n        }\n        return true;\n    };\n\n    // one simulation\n    auto run_sim = [&](uint64_t seed) {\n        mt19937 rng(static_cast<unsigned int>(seed));\n\n        vector<vector<bool>> dot(N, vector<bool>(N, false));\n        vector<vector<bool>> used_h(N - 1, vector<bool>(N, false));\n        vector<vector<bool>> used_v(N, vector<bool>(N - 1, false));\n        vector<vector<bool>> used_d1(N - 1, vector<bool>(N - 1, false));\n        vector<vector<bool>> used_d2(N - 1, vector<bool>(N, false));\n        vector<vector<int>> row_dots(N), col_dots(N);\n\n        for (auto& p : initial_dots) {\n            dot[p.x][p.y] = true;\n            row_dots[p.y].push_back(p.x);\n            col_dots[p.x].push_back(p.y);\n        }\n        long long cur_sum = initial_sum;\n        vector<array<Pt, 4>> history;\n\n        auto is_valid = [&](array<Pt, 4>& p) {\n            if (dot[p[0].x][p[0].y]) return false;\n            if (!dot[p[1].x][p[1].y] || !dot[p[2].x][p[2].y] || !dot[p[3].x][p[3].y]) return false;\n            for (int i = 0; i < 4; i++) {\n                if (!segment_operation(p[i], p[(i + 1) % 4], true, dot, used_h, used_v, used_d1, used_d2))\n                    return false;\n            }\n            return true;\n        };\n        auto apply_move = [&](array<Pt, 4>& p) {\n            dot[p[0].x][p[0].y] = true;\n            row_dots[p[0].y].push_back(p[0].x);\n            col_dots[p[0].x].push_back(p[0].y);\n            cur_sum += weight[p[0].x][p[0].y];\n            for (int i = 0; i < 4; i++)\n                segment_operation(p[i], p[(i + 1) % 4], false, dot, used_h, used_v, used_d1, used_d2);\n        };\n\n        auto add_axis_moves = [&](int x, int y, vector<array<Pt, 4>>& cands) {\n            if (x + 1 < N && y + 1 < N) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x + 1, y}, Pt{x + 1, y + 1}, Pt{x, y + 1}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n            if (x > 0 && y + 1 < N) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x, y + 1}, Pt{x - 1, y + 1}, Pt{x - 1, y}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n            if (x > 0 && y > 0) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x - 1, y}, Pt{x - 1, y - 1}, Pt{x, y - 1}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n            if (x + 1 < N && y > 0) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x, y - 1}, Pt{x + 1, y - 1}, Pt{x + 1, y}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n        };\n\n        auto add_diamond_moves = [&](int x, int y, vector<array<Pt, 4>>& cands) {\n            // role 0: bottom\n            if (x + 2 < N && y >= 1 && y + 1 < N) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x + 1, y + 1}, Pt{x + 2, y}, Pt{x + 1, y - 1}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n            // role 1: right\n            if (x >= 1 && x + 1 < N && y >= 2 && y < N) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x + 1, y - 1}, Pt{x, y - 2}, Pt{x - 1, y - 1}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n            // role 2: top\n            if (x >= 2 && y >= 1 && y + 1 < N) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x - 1, y - 1}, Pt{x - 2, y}, Pt{x - 1, y + 1}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n            // role 3: left\n            if (x >= 1 && x + 1 < N && y + 2 < N) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x - 1, y + 1}, Pt{x, y + 2}, Pt{x + 1, y + 1}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n        };\n\n        auto add_large_moves = [&](int x1, int y1, vector<array<Pt, 4>>& cands) {\n            for (int x2 : row_dots[y1]) {\n                if (x2 == x1) continue;\n                for (int y2 : col_dots[x1]) {\n                    if (y2 == y1) continue;\n                    if (!dot[x2][y2]) continue;\n                    array<Pt, 4> p = {Pt{x1, y1}, Pt{x2, y1}, Pt{x2, y2}, Pt{x1, y2}};\n                    if (is_valid(p)) cands.push_back(p);\n                }\n            }\n        };\n\n        while (true) {\n            vector<array<Pt, 4>> cands;\n            // small moves\n            for (int x = 0; x < N; x++) {\n                for (int y = 0; y < N; y++) {\n                    if (dot[x][y]) continue;\n                    add_axis_moves(x, y, cands);\n                    add_diamond_moves(x, y, cands);\n                }\n            }\n            // large moves only if no small moves\n            if (cands.empty()) {\n                for (int x = 0; x < N; x++) {\n                    for (int y = 0; y < N; y++) {\n                        if (dot[x][y]) continue;\n                        add_large_moves(x, y, cands);\n                    }\n                }\n                if (cands.empty()) break;\n            }\n\n            // compute weights\n            vector<int> weights(cands.size());\n            for (size_t i = 0; i < cands.size(); i++)\n                weights[i] = weight[cands[i][0].x][cands[i][0].y];\n\n            int max_w = *max_element(weights.begin(), weights.end());\n            vector<int> top_idx;\n            for (size_t i = 0; i < cands.size(); i++)\n                if (weights[i] == max_w) top_idx.push_back(static_cast<int>(i));\n\n            int pick;\n            // 80% choose among best, 20% random\n            if (top_idx.size() == cands.size() || (rng() % 100) < 80) {\n                pick = top_idx[rng() % top_idx.size()];\n            } else {\n                pick = rng() % cands.size();\n            }\n            apply_move(cands[pick]);\n            history.push_back(cands[pick]);\n        }\n        return make_pair(cur_sum, history);\n    };\n\n    long long best_sum = -1;\n    vector<array<Pt, 4>> best_hist;\n    int sim = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > 4.85) break;\n        uint64_t seed = chrono::steady_clock::now().time_since_epoch().count() + sim * 12345;\n        auto result = run_sim(seed);\n        if (result.first > best_sum) {\n            best_sum = result.first;\n            best_hist = move(result.second);\n        }\n        sim++;\n    }\n\n    // output\n    cout << best_hist.size() << \"\\n\";\n    for (auto& p : best_hist) {\n        cout << p[0].x << \" \" << p[0].y << \" \"\n             << p[1].x << \" \" << p[1].y << \" \"\n             << p[2].x << \" \" << p[2].y << \" \"\n             << p[3].x << \" \" << p[3].y << \"\\n\";\n    }\n    return 0;\n}","ahc015":"#include <iostream>\n#include <cstring>\nusing namespace std;\n\nint comp_id[10][10];\nint comp_size[100];\nint comp_count;\n\nint seen_version[100];\nint version_counter = 0;\n\nvoid compute_components(int board[10][10]) {\n    memset(comp_id, -1, sizeof(comp_id));\n    comp_count = 0;\n    int q[100][2];\n    for (int i = 0; i < 10; ++i) {\n        for (int j = 0; j < 10; ++j) {\n            if (board[i][j] != 0 && comp_id[i][j] == -1) {\n                int f = board[i][j];\n                int head = 0, tail = 0;\n                q[tail][0] = i; q[tail][1] = j; tail++;\n                comp_id[i][j] = comp_count;\n                int size = 0;\n                while (head < tail) {\n                    int r = q[head][0], c = q[head][1]; head++;\n                    size++;\n                    if (r > 0 && board[r-1][c] == f && comp_id[r-1][c] == -1) {\n                        comp_id[r-1][c] = comp_count;\n                        q[tail][0] = r-1; q[tail][1] = c; tail++;\n                    }\n                    if (r < 9 && board[r+1][c] == f && comp_id[r+1][c] == -1) {\n                        comp_id[r+1][c] = comp_count;\n                        q[tail][0] = r+1; q[tail][1] = c; tail++;\n                    }\n                    if (c > 0 && board[r][c-1] == f && comp_id[r][c-1] == -1) {\n                        comp_id[r][c-1] = comp_count;\n                        q[tail][0] = r; q[tail][1] = c-1; tail++;\n                    }\n                    if (c < 9 && board[r][c+1] == f && comp_id[r][c+1] == -1) {\n                        comp_id[r][c+1] = comp_count;\n                        q[tail][0] = r; q[tail][1] = c+1; tail++;\n                    }\n                }\n                comp_size[comp_count] = size;\n                comp_count++;\n            }\n        }\n    }\n}\n\nvoid tilt(int board[10][10], char dir, int out[10][10]) {\n    if (dir == 'F') {\n        for (int c = 0; c < 10; ++c) {\n            int col[10], sz = 0;\n            for (int r = 0; r < 10; ++r) if (board[r][c]) col[sz++] = board[r][c];\n            for (int r = 0; r < 10; ++r) out[r][c] = (r < sz) ? col[r] : 0;\n        }\n    } else if (dir == 'B') {\n        for (int c = 0; c < 10; ++c) {\n            int col[10], sz = 0;\n            for (int r = 0; r < 10; ++r) if (board[r][c]) col[sz++] = board[r][c];\n            int k = sz;\n            for (int r = 0; r < 10; ++r) out[r][c] = (r >= 10 - k) ? col[r - (10 - k)] : 0;\n        }\n    } else if (dir == 'L') {\n        for (int r = 0; r < 10; ++r) {\n            int row[10], sz = 0;\n            for (int c = 0; c < 10; ++c) if (board[r][c]) row[sz++] = board[r][c];\n            for (int c = 0; c < 10; ++c) out[r][c] = (c < sz) ? row[c] : 0;\n        }\n    } else if (dir == 'R') {\n        for (int r = 0; r < 10; ++r) {\n            int row[10], sz = 0;\n            for (int c = 0; c < 10; ++c) if (board[r][c]) row[sz++] = board[r][c];\n            int k = sz;\n            for (int c = 0; c < 10; ++c) out[r][c] = (c >= 10 - k) ? row[c - (10 - k)] : 0;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    int flavors[100];\n    for (int i = 0; i < 100; ++i) {\n        cin >> flavors[i];\n    }\n    \n    int board[10][10] = {0};\n    const char dirs[4] = {'F', 'B', 'L', 'R'};\n    memset(seen_version, 0, sizeof(seen_version));\n    version_counter = 0;\n    \n    for (int t = 0; t < 100; ++t) {\n        int p;\n        cin >> p;\n        // locate the p-th empty cell (1-indexed, front-to-back, left-to-right)\n        int tr = -1, tc = -1;\n        int empty_cnt = 0;\n        for (int r = 0; r < 10; ++r) {\n            for (int c = 0; c < 10; ++c) {\n                if (board[r][c] == 0) {\n                    empty_cnt++;\n                    if (empty_cnt == p) {\n                        tr = r; tc = c;\n                    }\n                }\n            }\n        }\n        board[tr][tc] = flavors[t];\n        \n        int best_dir = 0;\n        double best_score = -1.0;\n        int next_flavor = (t < 99) ? flavors[t+1] : -1;\n        \n        for (int di = 0; di < 4; ++di) {\n            char d = dirs[di];\n            int board_d[10][10];\n            tilt(board, d, board_d);\n            compute_components(board_d);\n            double S_base = 0;\n            for (int i = 0; i < comp_count; ++i) {\n                S_base += comp_size[i] * comp_size[i];\n            }\n            double expected = S_base;\n            if (next_flavor != -1) {\n                int total_delta = 0;\n                int empty_c = 0;\n                for (int r = 0; r < 10; ++r) {\n                    for (int c = 0; c < 10; ++c) {\n                        if (board_d[r][c] == 0) {\n                            empty_c++;\n                            int ver = ++version_counter;\n                            int sum_size = 0, sum_sq = 0;\n                            if (r > 0 && board_d[r-1][c] == next_flavor) {\n                                int id = comp_id[r-1][c];\n                                if (seen_version[id] != ver) {\n                                    seen_version[id] = ver;\n                                    int sz = comp_size[id];\n                                    sum_size += sz;\n                                    sum_sq += sz * sz;\n                                }\n                            }\n                            if (r < 9 && board_d[r+1][c] == next_flavor) {\n                                int id = comp_id[r+1][c];\n                                if (seen_version[id] != ver) {\n                                    seen_version[id] = ver;\n                                    int sz = comp_size[id];\n                                    sum_size += sz;\n                                    sum_sq += sz * sz;\n                                }\n                            }\n                            if (c > 0 && board_d[r][c-1] == next_flavor) {\n                                int id = comp_id[r][c-1];\n                                if (seen_version[id] != ver) {\n                                    seen_version[id] = ver;\n                                    int sz = comp_size[id];\n                                    sum_size += sz;\n                                    sum_sq += sz * sz;\n                                }\n                            }\n                            if (c < 9 && board_d[r][c+1] == next_flavor) {\n                                int id = comp_id[r][c+1];\n                                if (seen_version[id] != ver) {\n                                    seen_version[id] = ver;\n                                    int sz = comp_size[id];\n                                    sum_size += sz;\n                                    sum_sq += sz * sz;\n                                }\n                            }\n                            int delta = (1 + sum_size) * (1 + sum_size) - sum_sq;\n                            total_delta += delta;\n                        }\n                    }\n                }\n                expected = S_base + (double)total_delta / empty_c;\n            }\n            if (expected > best_score) {\n                best_score = expected;\n                best_dir = di;\n            }\n        }\n        cout << dirs[best_dir] << endl;\n        tilt(board, dirs[best_dir], board);\n    }\n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <Eigen/Dense>\n\nusing namespace std;\nusing namespace Eigen;\n\n// compute sorted degree sequence from adjacency matrix\nvector<int> calc_degrees(const vector<vector<bool>>& adj, int N) {\n    vector<int> deg(N, 0);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (adj[i][j]) deg[i]++;\n    sort(deg.begin(), deg.end(), greater<int>());\n    return deg;\n}\n\n// compute top topk eigenvalues (sorted descending)\nvector<double> calc_eigenvalues(const vector<vector<bool>>& adj, int N, int topk) {\n    MatrixXd A(N, N);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            A(i, j) = adj[i][j] ? 1.0 : 0.0;\n    SelfAdjointEigenSolver<MatrixXd> es(A);\n    VectorXd evals = es.eigenvalues();\n    vector<double> ev(evals.data(), evals.data() + N);\n    sort(ev.begin(), ev.end(), greater<double>());\n    if (topk < N) ev.resize(topk);\n    return ev;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int M;\n    double eps;\n    cin >> M >> eps;\n    \n    // choose number of vertices adaptively\n    int N = min(100, max(20, M + 20));\n    int Half = N / 2;          // we will use left part up to Half\n    \n    // predefined ID edges (7 edges among first 6 vertices)\n    const vector<pair<int,int>> id_edges = {\n        {0,1}, {0,2}, {0,3}, {0,4}, {1,2}, {1,3}, {2,3}\n    };\n    \n    // store graphs and their feature vectors\n    vector<vector<vector<bool>>> graphs(M, vector<vector<bool>>(N, vector<bool>(N, false)));\n    vector<vector<double>> features(M);\n    \n    for (int k = 0; k < M; ++k) {\n        auto& adj = graphs[k];\n        // determine size of left part L (5 .. Half)\n        int L;\n        if (M == 1) {\n            L = Half;\n        } else {\n            L = 5 + (k * (Half - 5)) / (M - 1);\n            if (L > Half) L = Half;\n            if (L < 5) L = 5;\n        }\n        int R = N - L;\n        \n        // base: complete bipartite between left part [0, L-1] and right part [L, N-1]\n        for (int i = 0; i < L; ++i) {\n            for (int j = L; j < N; ++j) {\n                adj[i][j] = true;\n                adj[j][i] = true;\n            }\n        }\n        \n        // add ID edges according to the bits of k\n        for (int b = 0; b < 7; ++b) {\n            if (k & (1 << b)) {\n                int u = id_edges[b].first;\n                int v = id_edges[b].second;\n                if (u < L && v < L) {   // only inside left part\n                    adj[u][v] = !adj[u][v];\n                    adj[v][u] = adj[u][v];\n                }\n            }\n        }\n        \n        // compute features for this message\n        vector<int> deg = calc_degrees(adj, N);\n        double edges = 0;\n        for (int d : deg) edges += d;\n        edges /= 2.0;\n        \n        vector<double> evals = calc_eigenvalues(adj, N, 20);\n        \n        // assemble normalised feature vector\n        vector<double> feat;\n        feat.push_back(edges / (N * (N - 1) / 2.0));   // edge density\n        for (int d : deg) feat.push_back((double)d / (N - 1.0));\n        for (double e : evals) feat.push_back(e / N);\n        features[k] = move(feat);\n    }\n    \n    // output the M graphs\n    cout << N << \"\\n\";\n    int L_str = N * (N - 1) / 2;\n    for (int k = 0; k < M; ++k) {\n        string s;\n        s.reserve(L_str);\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) {\n                s.push_back(graphs[k][i][j] ? '1' : '0');\n            }\n        }\n        cout << s << \"\\n\";\n    }\n    cout.flush();\n    \n    // answer 100 queries\n    for (int q = 0; q < 100; ++q) {\n        string H_str;\n        cin >> H_str;\n        if (H_str.empty()) break;\n        \n        vector<vector<bool>> H_adj(N, vector<bool>(N, false));\n        int idx = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) {\n                if (H_str[idx] == '1') {\n                    H_adj[i][j] = H_adj[j][i] = true;\n                }\n                ++idx;\n            }\n        }\n        \n        // extract features of H\n        vector<int> deg = calc_degrees(H_adj, N);\n        double edges = 0;\n        for (int d : deg) edges += d;\n        edges /= 2.0;\n        vector<double> evals = calc_eigenvalues(H_adj, N, 20);\n        \n        vector<double> feat;\n        feat.push_back(edges / (N * (N - 1) / 2.0));\n        for (int d : deg) feat.push_back((double)d / (N - 1.0));\n        for (double e : evals) feat.push_back(e / N);\n        \n        // nearest neighbour in feature space\n        double best_dist = 1e18;\n        int best_k = 0;\n        for (int k = 0; k < M; ++k) {\n            const auto& f = features[k];\n            double dist = 0.0;\n            for (size_t i = 0; i < f.size(); ++i) {\n                double diff = f[i] - feat[i];\n                dist += diff * diff;\n            }\n            if (dist < best_dist) {\n                best_dist = dist;\n                best_k = k;\n            }\n        }\n        cout << best_k << \"\\n\";\n        cout.flush();\n    }\n    \n    return 0;\n}","ahc017":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <chrono>\n#include <limits>\n#include <tuple>\nusing namespace std;\nusing ll = long long;\n\nconst int INF = 1'000'000'000;\n\nint main() {\n    auto start_time = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count();\n    };\n    \n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n    vector<int> U(M), V(M), W(M);\n    vector<vector<tuple<int,int,int>>> orig_adj(N); // to, weight, edge_id\n    vector<int> edge_idx(N*N, -1);\n    for (int i = 0; i < M; ++i) {\n        cin >> U[i] >> V[i] >> W[i];\n        --U[i]; --V[i];\n        orig_adj[U[i]].emplace_back(V[i], W[i], i);\n        orig_adj[V[i]].emplace_back(U[i], W[i], i);\n        edge_idx[U[i]*N + V[i]] = i;\n        edge_idx[V[i]*N + U[i]] = i;\n    }\n    // read and ignore coordinates\n    int dummy;\n    for (int i = 0; i < N; ++i) cin >> dummy >> dummy;\n    \n    // Compute original all-pairs shortest paths and edge centralities\n    vector<int> orig(N*N, INF);\n    vector<ll> cnt(M, 0);\n    vector<int> dist(N);\n    priority_queue<pair<int,int>, vector<pair<int,int>>, greater<>> pq;\n    \n    for (int s = 0; s < N; ++s) {\n        fill(dist.begin(), dist.end(), INF);\n        vector<int> parent_node(N, -1);\n        vector<int> parent_edge(N, -1);\n        dist[s] = 0;\n        pq.push({0, s});\n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop();\n            if (d != dist[u]) continue;\n            for (auto &edge : orig_adj[u]) {\n                int v = get<0>(edge), w = get<1>(edge), eid = get<2>(edge);\n                if (dist[v] > d + w) {\n                    dist[v] = d + w;\n                    parent_node[v] = u;\n                    parent_edge[v] = eid;\n                    pq.push({dist[v], v});\n                }\n            }\n        }\n        for (int t = 0; t < N; ++t) {\n            orig[s*N + t] = dist[t];\n        }\n        // compute subtree sizes for centrality\n        vector<int> sub(N, 1);\n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) { return dist[a] > dist[b]; });\n        for (int v : order) {\n            if (v == s) continue;\n            int p = parent_node[v];\n            if (p != -1) {\n                sub[p] += sub[v];\n                if (parent_edge[v] != -1) {\n                    cnt[parent_edge[v]] += sub[v];\n                }\n            }\n        }\n    }\n    \n    // Greedy assignment based on cnt\n    vector<int> assign(M, -1);\n    vector<int> day_cnt(D, 0);\n    vector<ll> day_sum_cnt(D, 0);\n    vector<int> sorted_edges(M);\n    iota(sorted_edges.begin(), sorted_edges.end(), 0);\n    sort(sorted_edges.begin(), sorted_edges.end(), [&](int a, int b) { return cnt[a] > cnt[b]; });\n    for (int e : sorted_edges) {\n        int best_d = -1;\n        ll best_sum = numeric_limits<ll>::max();\n        for (int d = 0; d < D; ++d) {\n            if (day_cnt[d] < K && day_sum_cnt[d] < best_sum) {\n                best_sum = day_sum_cnt[d];\n                best_d = d;\n            }\n        }\n        assign[e] = best_d;\n        day_cnt[best_d]++;\n        day_sum_cnt[best_d] += cnt[e];\n    }\n    \n    // Store day edges\n    vector<vector<int>> day_edges(D);\n    for (int e = 0; e < M; ++e) {\n        day_edges[assign[e]].push_back(e);\n    }\n    \n    // Exact evaluation helper\n    vector<bool> removed(M);\n    auto compute_day_dist = [&](const vector<int>& removed_edges, vector<int>& out_dist, ll& out_diff) {\n        fill(removed.begin(), removed.end(), false);\n        for (int e : removed_edges) removed[e] = true;\n        out_dist.assign(N*N, INF);\n        out_diff = 0;\n        for (int s = 0; s < N; ++s) {\n            fill(dist.begin(), dist.end(), INF);\n            dist[s] = 0;\n            pq.push({0, s});\n            while (!pq.empty()) {\n                auto [d, u] = pq.top(); pq.pop();\n                if (d != dist[u]) continue;\n                for (auto &edge : orig_adj[u]) {\n                    int v = get<0>(edge), w = get<1>(edge), eid = get<2>(edge);\n                    if (removed[eid]) continue;\n                    if (dist[v] > d + w) {\n                        dist[v] = d + w;\n                        pq.push({dist[v], v});\n                    }\n                }\n            }\n            int base = s * N;\n            for (int t = 0; t < N; ++t) {\n                out_dist[base + t] = dist[t];\n            }\n            for (int t = s+1; t < N; ++t) {\n                out_diff += dist[t] - orig[base + t];\n            }\n        }\n    };\n    \n    // Initial exact evaluation\n    vector<vector<int>> day_dist(D);\n    vector<ll> day_diff(D, 0);\n    ll total_diff = 0;\n    for (int d = 0; d < D; ++d) {\n        compute_day_dist(day_edges[d], day_dist[d], day_diff[d]);\n        total_diff += day_diff[d];\n    }\n    ll best_total_diff = total_diff;\n    vector<int> best_assign = assign;\n    \n    // Local search\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> real_dist(0.0, 1.0);\n    \n    const int TIME_LIMIT_MS = 5800;\n    while (elapsed() < TIME_LIMIT_MS) {\n        // Pick a day A weighted by day_diff\n        ll sum_weights = accumulate(day_diff.begin(), day_diff.end(), 0LL);\n        int A;\n        if (sum_weights > 0) {\n            discrete_distribution<int> day_sel(day_diff.begin(), day_diff.end());\n            A = day_sel(rng);\n        } else {\n            uniform_int_distribution<int> unif(0, D-1);\n            A = unif(rng);\n        }\n        if (day_edges[A].empty()) continue;\n        \n        // Pick a random edge in A\n        uniform_int_distribution<int> edge_sel_A(0, (int)day_edges[A].size() - 1);\n        int e = day_edges[A][edge_sel_A(rng)];\n        \n        // Pick a random B != A with capacity\n        vector<int> candidates;\n        for (int d = 0; d < D; ++d) {\n            if (d != A && day_cnt[d] < K) candidates.push_back(d);\n        }\n        if (candidates.empty()) continue;\n        uniform_int_distribution<int> cand_sel(0, (int)candidates.size() - 1);\n        int B = candidates[cand_sel(rng)];\n        \n        // Evaluate move: remove e from A, add e to B\n        vector<int> new_A_edges = day_edges[A];\n        new_A_edges.erase(remove(new_A_edges.begin(), new_A_edges.end(), e), new_A_edges.end());\n        vector<int> new_dA;\n        ll new_diffA;\n        compute_day_dist(new_A_edges, new_dA, new_diffA);\n        \n        // New B: S_B U {e} (incremental update)\n        vector<int> oldB = day_dist[B];\n        vector<int> new_dB = oldB;\n        int u = U[e], v = V[e], w = W[e];\n        for (int i = 0; i < N; ++i) {\n            int iu = oldB[i*N + u];\n            int iv = oldB[i*N + v];\n            int base_i = i * N;\n            for (int j = 0; j < N; ++j) {\n                int idx = base_i + j;\n                int via_u = iu + w + oldB[v*N + j];\n                int via_v = iv + w + oldB[u*N + j];\n                if (via_u < new_dB[idx]) new_dB[idx] = via_u;\n                if (via_v < new_dB[idx]) new_dB[idx] = via_v;\n            }\n        }\n        ll new_diffB = 0;\n        for (int i = 0; i < N; ++i) {\n            int base = i * N;\n            for (int j = i+1; j < N; ++j) {\n                new_diffB += new_dB[base + j] - orig[base + j];\n            }\n        }\n        \n        ll new_total_diff = total_diff - day_diff[A] - day_diff[B] + new_diffA + new_diffB;\n        if (new_total_diff < total_diff) {\n            // Accept move\n            assign[e] = B;\n            day_cnt[A]--;\n            day_cnt[B]++;\n            auto &vecA = day_edges[A];\n            vecA.erase(remove(vecA.begin(), vecA.end(), e), vecA.end());\n            day_edges[B].push_back(e);\n            day_dist[A] = move(new_dA);\n            day_dist[B] = move(new_dB);\n            day_diff[A] = new_diffA;\n            day_diff[B] = new_diffB;\n            total_diff = new_total_diff;\n            if (total_diff < best_total_diff) {\n                best_total_diff = total_diff;\n                best_assign = assign;\n            }\n        }\n    }\n    \n    // Output best assignment\n    for (int i = 0; i < M; ++i) {\n        if (i) cout << \" \";\n        cout << best_assign[i] + 1;\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc019":"#include <iostream>\n#include <vector>\n#include <string>\n#include <tuple>\n#include <algorithm>\n\nusing namespace std;\n\nint main() {\n    int D;\n    cin >> D;\n    vector<string> f[2], r[2];\n    for (int i = 0; i < 2; i++) {\n        f[i].resize(D);\n        for (int k = 0; k < D; k++) cin >> f[i][k];\n        r[i].resize(D);\n        for (int k = 0; k < D; k++) cin >> r[i][k];\n    }\n\n    int total_cells = D * D * D;\n    vector<bool> allowed[2], used[2];\n    vector<vector<bool>> uncov_f[2], uncov_r[2];\n    vector<int> bid[2];\n\n    for (int i = 0; i < 2; i++) {\n        allowed[i].assign(total_cells, false);\n        used[i].assign(total_cells, false);\n        uncov_f[i].assign(D, vector<bool>(D, false));\n        uncov_r[i].assign(D, vector<bool>(D, false));\n        bid[i].assign(total_cells, 0);\n    }\n\n    auto idx = [&](int x, int y, int z) {\n        return x * D * D + y * D + z;\n    };\n\n    // Initialize allowed and uncovered\n    for (int i = 0; i < 2; i++) {\n        for (int z = 0; z < D; z++) {\n            for (int x = 0; x < D; x++) {\n                if (f[i][z][x] == '1') {\n                    uncov_f[i][z][x] = true;\n                }\n            }\n            for (int y = 0; y < D; y++) {\n                if (r[i][z][y] == '1') {\n                    uncov_r[i][z][y] = true;\n                }\n            }\n        }\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    if (f[i][z][x] == '1' && r[i][z][y] == '1') {\n                        allowed[i][idx(x, y, z)] = true;\n                    }\n                }\n            }\n        }\n    }\n\n    // Helper functions\n    auto can_place = [&](int i, int x0, int y0, int z0, int dx, int dy, int dz) {\n        for (int x = x0; x < x0 + dx; x++) {\n            for (int y = y0; y < y0 + dy; y++) {\n                for (int z = z0; z < z0 + dz; z++) {\n                    int id = idx(x, y, z);\n                    if (!allowed[i][id] || used[i][id]) return false;\n                }\n            }\n        }\n        return true;\n    };\n\n    auto count_covered = [&](int i, int x0, int y0, int z0, int dx, int dy, int dz) {\n        bool f_cov[14][14] = {false}, r_cov[14][14] = {false};\n        for (int x = x0; x < x0 + dx; x++) {\n            for (int y = y0; y < y0 + dy; y++) {\n                for (int z = z0; z < z0 + dz; z++) {\n                    if (uncov_f[i][z][x]) f_cov[z][x] = true;\n                    if (uncov_r[i][z][y]) r_cov[z][y] = true;\n                }\n            }\n        }\n        int cnt = 0;\n        for (int z = 0; z < D; z++) for (int x = 0; x < D; x++) if (f_cov[z][x]) cnt++;\n        for (int z = 0; z < D; z++) for (int y = 0; y < D; y++) if (r_cov[z][y]) cnt++;\n        return cnt;\n    };\n\n    auto apply_placement = [&](int i, int x0, int y0, int z0, int dx, int dy, int dz, int b_id) {\n        for (int x = x0; x < x0 + dx; x++) {\n            for (int y = y0; y < y0 + dy; y++) {\n                for (int z = z0; z < z0 + dz; z++) {\n                    int id = idx(x, y, z);\n                    used[i][id] = true;\n                    bid[i][id] = b_id;\n                    uncov_f[i][z][x] = false;\n                    uncov_r[i][z][y] = false;\n                }\n            }\n        }\n    };\n\n    auto compute_maximal_box = [&](int i, int sx, int sy, int sz,\n                                   int &x0, int &y0, int &z0, int &dx, int &dy, int &dz) {\n        x0 = sx; y0 = sy; z0 = sz;\n        int x1 = sx, y1 = sy, z1 = sz;\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            // x-\n            while (x0 > 0) {\n                bool ok = true;\n                for (int y = y0; y <= y1 && ok; y++)\n                    for (int z = z0; z <= z1 && ok; z++)\n                        if (!allowed[i][idx(x0-1, y, z)] || used[i][idx(x0-1, y, z)]) ok = false;\n                if (ok) { x0--; changed = true; } else break;\n            }\n            // x+\n            while (x1 < D-1) {\n                bool ok = true;\n                for (int y = y0; y <= y1 && ok; y++)\n                    for (int z = z0; z <= z1 && ok; z++)\n                        if (!allowed[i][idx(x1+1, y, z)] || used[i][idx(x1+1, y, z)]) ok = false;\n                if (ok) { x1++; changed = true; } else break;\n            }\n            // y-\n            while (y0 > 0) {\n                bool ok = true;\n                for (int x = x0; x <= x1 && ok; x++)\n                    for (int z = z0; z <= z1 && ok; z++)\n                        if (!allowed[i][idx(x, y0-1, z)] || used[i][idx(x, y0-1, z)]) ok = false;\n                if (ok) { y0--; changed = true; } else break;\n            }\n            // y+\n            while (y1 < D-1) {\n                bool ok = true;\n                for (int x = x0; x <= x1 && ok; x++)\n                    for (int z = z0; z <= z1 && ok; z++)\n                        if (!allowed[i][idx(x, y1+1, z)] || used[i][idx(x, y1+1, z)]) ok = false;\n                if (ok) { y1++; changed = true; } else break;\n            }\n            // z-\n            while (z0 > 0) {\n                bool ok = true;\n                for (int x = x0; x <= x1 && ok; x++)\n                    for (int y = y0; y <= y1 && ok; y++)\n                        if (!allowed[i][idx(x, y, z0-1)] || used[i][idx(x, y, z0-1)]) ok = false;\n                if (ok) { z0--; changed = true; } else break;\n            }\n            // z+\n            while (z1 < D-1) {\n                bool ok = true;\n                for (int x = x0; x <= x1 && ok; x++)\n                    for (int y = y0; y <= y1 && ok; y++)\n                        if (!allowed[i][idx(x, y, z1+1)] || used[i][idx(x, y, z1+1)]) ok = false;\n                if (ok) { z1++; changed = true; } else break;\n            }\n        }\n        dx = x1 - x0 + 1;\n        dy = y1 - y0 + 1;\n        dz = z1 - z0 + 1;\n    };\n\n    int perms[6][3] = {{0,1,2},{0,2,1},{1,0,2},{1,2,0},{2,0,1},{2,1,0}};\n\n    auto find_placements = [&](int i, int dx, int dy, int dz) {\n        vector<tuple<int,int,int,int,int,int>> res;\n        int dims[3] = {dx, dy, dz};\n        for (auto &p : perms) {\n            int g_dx = dims[p[0]];\n            int g_dy = dims[p[1]];\n            int g_dz = dims[p[2]];\n            for (int x0 = 0; x0 <= D - g_dx; x0++) {\n                for (int y0 = 0; y0 <= D - g_dy; y0++) {\n                    for (int z0 = 0; z0 <= D - g_dz; z0++) {\n                        if (can_place(i, x0, y0, z0, g_dx, g_dy, g_dz)) {\n                            res.emplace_back(x0, y0, z0, g_dx, g_dy, g_dz);\n                        }\n                    }\n                }\n            }\n        }\n        return res;\n    };\n\n    struct Block {\n        int dx, dy, dz;\n        int x0_0, y0_0, z0_0, dx_0, dy_0, dz_0;\n        int x0_1, y0_1, z0_1, dx_1, dy_1, dz_1;\n    };\n    vector<Block> blocks;\n\n    while (true) {\n        int uncov_cnt[2] = {0,0};\n        for (int i = 0; i < 2; i++) {\n            for (int z = 0; z < D; z++) {\n                for (int x = 0; x < D; x++) if (uncov_f[i][z][x]) uncov_cnt[i]++;\n                for (int y = 0; y < D; y++) if (uncov_r[i][z][y]) uncov_cnt[i]++;\n            }\n        }\n        if (uncov_cnt[0] == 0 && uncov_cnt[1] == 0) break;\n\n        int i = (uncov_cnt[0] >= uncov_cnt[1]) ? 0 : 1;\n        int j = 1 - i;\n\n        // find an uncovered column in i\n        int z_sel = -1, x_sel = -1, y_sel = -1;\n        bool is_front = false;\n        for (int z = 0; z < D && z_sel == -1; z++) {\n            for (int x = 0; x < D; x++) if (uncov_f[i][z][x]) {\n                z_sel = z; x_sel = x; is_front = true; break;\n            }\n            if (z_sel == -1) {\n                for (int y = 0; y < D; y++) if (uncov_r[i][z][y]) {\n                    z_sel = z; y_sel = y; is_front = false; break;\n                }\n            }\n        }\n\n        // collect seed cells\n        vector<tuple<int,int,int>> seeds;\n        if (is_front) {\n            for (int y = 0; y < D; y++) {\n                if (allowed[i][idx(x_sel, y, z_sel)] && !used[i][idx(x_sel, y, z_sel)])\n                    seeds.emplace_back(x_sel, y, z_sel);\n            }\n        } else {\n            for (int x = 0; x < D; x++) {\n                if (allowed[i][idx(x, y_sel, z_sel)] && !used[i][idx(x, y_sel, z_sel)])\n                    seeds.emplace_back(x, y_sel, z_sel);\n            }\n        }\n\n        if (seeds.empty()) {\n            // fallback: any allowed unused cell in i\n            for (int x = 0; x < D; x++) for (int y = 0; y < D; y++) for (int z = 0; z < D; z++) {\n                if (allowed[i][idx(x, y, z)] && !used[i][idx(x, y, z)]) {\n                    seeds.emplace_back(x,y,z); goto seed_found;\n                }\n            }\n            seed_found:;\n        }\n\n        // evaluate each seed\n        int best_score = -1;\n        int best_x0_i, best_y0_i, best_z0_i, best_dx_i, best_dy_i, best_dz_i;\n        int best_seed_x, best_seed_y, best_seed_z;\n        for (auto [sx,sy,sz] : seeds) {\n            int x0, y0, z0, dx, dy, dz;\n            compute_maximal_box(i, sx, sy, sz, x0, y0, z0, dx, dy, dz);\n            int cc = count_covered(i, x0, y0, z0, dx, dy, dz);\n            int vol = dx * dy * dz;\n            int score = vol * 1000 + cc;\n            if (score > best_score) {\n                best_score = score;\n                best_x0_i = x0; best_y0_i = y0; best_z0_i = z0;\n                best_dx_i = dx; best_dy_i = dy; best_dz_i = dz;\n                best_seed_x = sx; best_seed_y = sy; best_seed_z = sz;\n            }\n        }\n\n        // try placement in j\n        auto placements_j = find_placements(j, best_dx_i, best_dy_i, best_dz_i);\n        if (!placements_j.empty()) {\n            int best_cc_j = -1;\n            int best_x0_j, best_y0_j, best_z0_j, best_dx_j, best_dy_j, best_dz_j;\n            for (auto& [x0,y0,z0,dx,dy,dz] : placements_j) {\n                int cc = count_covered(j, x0, y0, z0, dx, dy, dz);\n                if (cc > best_cc_j) {\n                    best_cc_j = cc;\n                    best_x0_j = x0; best_y0_j = y0; best_z0_j = z0;\n                    best_dx_j = dx; best_dy_j = dy; best_dz_j = dz;\n                }\n            }\n            int id = blocks.size() + 1;\n            apply_placement(i, best_x0_i, best_y0_i, best_z0_i, best_dx_i, best_dy_i, best_dz_i, id);\n            apply_placement(j, best_x0_j, best_y0_j, best_z0_j, best_dx_j, best_dy_j, best_dz_j, id);\n            blocks.push_back({best_dx_i, best_dy_i, best_dz_i,\n                              best_x0_i, best_y0_i, best_z0_i, best_dx_i, best_dy_i, best_dz_i,\n                              best_x0_j, best_y0_j, best_z0_j, best_dx_j, best_dy_j, best_dz_j});\n        } else {\n            // try sub\u2011boxes\n            vector<tuple<int,int,int,int,int,int>> sub_boxes;\n            for (int x0 = best_x0_i; x0 <= best_seed_x; x0++) {\n                for (int x1 = best_seed_x; x1 < best_x0_i + best_dx_i; x1++) {\n                    int dx_sub = x1 - x0 + 1;\n                    for (int y0 = best_y0_i; y0 <= best_seed_y; y0++) {\n                        for (int y1 = best_seed_y; y1 < best_y0_i + best_dy_i; y1++) {\n                            int dy_sub = y1 - y0 + 1;\n                            for (int z0 = best_z0_i; z0 <= best_seed_z; z0++) {\n                                for (int z1 = best_seed_z; z1 < best_z0_i + best_dz_i; z1++) {\n                                    int dz_sub = z1 - z0 + 1;\n                                    sub_boxes.emplace_back(x0, y0, z0, dx_sub, dy_sub, dz_sub);\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n            sort(sub_boxes.begin(), sub_boxes.end(), [](auto &a, auto &b) {\n                return get<3>(a)*get<4>(a)*get<5>(a) > get<3>(b)*get<4>(b)*get<5>(b);\n            });\n\n            bool placed_sub = false;\n            for (auto &sub : sub_boxes) {\n                int x0_i2 = get<0>(sub), y0_i2 = get<1>(sub), z0_i2 = get<2>(sub);\n                int dx_sub = get<3>(sub), dy_sub = get<4>(sub), dz_sub = get<5>(sub);\n                auto placements_j_sub = find_placements(j, dx_sub, dy_sub, dz_sub);\n                if (!placements_j_sub.empty()) {\n                    int best_cc_j = -1;\n                    int bx_j, by_j, bz_j, bdx_j, bdy_j, bdz_j;\n                    for (auto &pl : placements_j_sub) {\n                        int cc = count_covered(j, get<0>(pl), get<1>(pl), get<2>(pl),\n                                               get<3>(pl), get<4>(pl), get<5>(pl));\n                        if (cc > best_cc_j) {\n                            best_cc_j = cc;\n                            bx_j = get<0>(pl); by_j = get<1>(pl); bz_j = get<2>(pl);\n                            bdx_j = get<3>(pl); bdy_j = get<4>(pl); bdz_j = get<5>(pl);\n                        }\n                    }\n                    int id = blocks.size() + 1;\n                    apply_placement(i, x0_i2, y0_i2, z0_i2, dx_sub, dy_sub, dz_sub, id);\n                    apply_placement(j, bx_j, by_j, bz_j, bdx_j, bdy_j, bdz_j, id);\n                    blocks.push_back({dx_sub, dy_sub, dz_sub,\n                                      x0_i2, y0_i2, z0_i2, dx_sub, dy_sub, dz_sub,\n                                      bx_j, by_j, bz_j, bdx_j, bdy_j, bdz_j});\n                    placed_sub = true;\n                    break;\n                }\n            }\n\n            if (!placed_sub) {\n                // fallback 1\u00d71\u00d71\n                int seed_x, seed_y, seed_z;\n                tie(seed_x, seed_y, seed_z) = seeds.front(); // use a seed\n                auto placements_j_1 = find_placements(j, 1, 1, 1);\n                int bx_j = -1, by_j = -1, bz_j = -1;\n                int best_cc_j = -1;\n                for (auto &pl : placements_j_1) {\n                    int cc = count_covered(j, get<0>(pl), get<1>(pl), get<2>(pl), 1,1,1);\n                    if (cc > best_cc_j) {\n                        best_cc_j = cc;\n                        bx_j = get<0>(pl); by_j = get<1>(pl); bz_j = get<2>(pl);\n                    }\n                }\n                if (bx_j == -1) {\n                    // no allowed unused cell in j (should not happen)\n                    for (int x = 0; x < D && bx_j == -1; x++)\n                        for (int y = 0; y < D && bx_j == -1; y++)\n                            for (int z = 0; z < D && bx_j == -1; z++)\n                                if (allowed[j][idx(x,y,z)] && !used[j][idx(x,y,z)])\n                                    bx_j = x, by_j = y, bz_j = z;\n                }\n                int id = blocks.size() + 1;\n                apply_placement(i, seed_x, seed_y, seed_z, 1,1,1, id);\n                apply_placement(j, bx_j, by_j, bz_j, 1,1,1, id);\n                blocks.push_back({1,1,1,\n                                  seed_x, seed_y, seed_z, 1,1,1,\n                                  bx_j, by_j, bz_j, 1,1,1});\n            }\n        }\n    }\n\n    int n = blocks.size();\n    cout << n << \"\\n\";\n    for (int i = 0; i < 2; i++) {\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 (x != 0 || y != 0 || z != 0) cout << \" \";\n                    cout << bid[i][idx(x, y, z)];\n                }\n            }\n        }\n        cout << \"\\n\";\n    }\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\nusing int64 = long long;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start_time = chrono::steady_clock::now();\n    auto elapsed = [&]() { return chrono::duration<double>(chrono::steady_clock::now() - start_time).count(); };\n\n    int N, M, K;\n    cin >> N >> M >> K;\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; ++i) cin >> x[i] >> y[i];\n    vector<int> u(M), v(M), w(M);\n    vector<vector<pair<int, int>>> adj(N);\n    vector<int> edge_id(N * N, -1);\n    for (int j = 0; j < M; ++j) {\n        cin >> u[j] >> v[j] >> w[j];\n        --u[j]; --v[j];\n        adj[u[j]].push_back({v[j], w[j]});\n        adj[v[j]].push_back({u[j], w[j]});\n        edge_id[u[j] * N + v[j]] = j;\n        edge_id[v[j] * N + u[j]] = j;\n    }\n    vector<int> a(K), b(K);\n    for (int k = 0; k < K; ++k) cin >> a[k] >> b[k];\n\n    // all-pairs shortest paths\n    vector<vector<int64>> dist(N, vector<int64>(N));\n    vector<vector<int>> pred(N, vector<int>(N, -1));\n    for (int s = 0; s < N; ++s) {\n        priority_queue<pair<int64, int>, vector<pair<int64, int>>, greater<>> pq;\n        vector<int64> d(N, numeric_limits<int64>::max());\n        d[s] = 0;\n        pred[s][s] = s;\n        pq.push({0, s});\n        while (!pq.empty()) {\n            auto [du, node] = pq.top(); pq.pop();\n            if (du != d[node]) continue;\n            for (auto &[to, weight] : adj[node]) {\n                if (d[node] + weight < d[to]) {\n                    d[to] = d[node] + weight;\n                    pred[s][to] = node;\n                    pq.push({d[to], to});\n                }\n            }\n        }\n        dist[s] = d;\n    }\n\n    // Euclidean distances and sorted vertices for residents\n    vector<vector<double>> vdist(N, vector<double>(K));\n    vector<vector<int>> sorted_vertices(K, vector<int>(N));\n    for (int k = 0; k < K; ++k) {\n        for (int i = 0; i < N; ++i) {\n            double dx = x[i] - a[k];\n            double dy = y[i] - b[k];\n            vdist[i][k] = sqrt(dx * dx + dy * dy);\n        }\n        iota(sorted_vertices[k].begin(), sorted_vertices[k].end(), 0);\n        sort(sorted_vertices[k].begin(), sorted_vertices[k].end(),\n             [&](int i1, int i2) { return vdist[i1][k] < vdist[i2][k]; });\n    }\n\n    // evaluation function\n    auto evaluate = [&](const vector<bool> &active) -> int64 {\n        vector<int> act;\n        for (int i = 0; i < N; ++i) if (active[i]) act.push_back(i);\n        int m = act.size();\n        vector<pair<int, int>> mst_edges;\n        if (m > 1) {\n            vector<bool> inmst(m, false);\n            vector<int64> minw(m, numeric_limits<int64>::max());\n            vector<int> parent(m, -1);\n            minw[0] = 0;\n            for (int i = 0; i < m; ++i) {\n                int u = -1;\n                for (int j = 0; j < m; ++j)\n                    if (!inmst[j] && (u == -1 || minw[j] < minw[u])) u = j;\n                inmst[u] = true;\n                if (parent[u] != -1)\n                    mst_edges.push_back({act[u], act[parent[u]]});\n                for (int v = 0; v < m; ++v) {\n                    if (!inmst[v]) {\n                        int64 wgt = dist[act[u]][act[v]];\n                        if (wgt < minw[v]) {\n                            minw[v] = wgt;\n                            parent[v] = u;\n                        }\n                    }\n                }\n            }\n        }\n        vector<bool> tmp_used(M, false);\n        for (auto [a, b] : mst_edges) {\n            int cur = b;\n            while (cur != a) {\n                int p = pred[a][cur];\n                int eid = edge_id[p * N + cur];\n                if (eid != -1) tmp_used[eid] = true;\n                cur = p;\n            }\n        }\n        vector<bool> reachable(N, false);\n        queue<int> q;\n        reachable[0] = true; q.push(0);\n        while (!q.empty()) {\n            int node = q.front(); q.pop();\n            for (auto &[to, weight] : adj[node]) {\n                int eid = edge_id[node * N + to];\n                if (tmp_used[eid] && !reachable[to]) {\n                    reachable[to] = true;\n                    q.push(to);\n                }\n            }\n        }\n        vector<double> max_d(N, 0.0);\n        for (int k = 0; k < K; ++k) {\n            bool covered = false;\n            for (int i : sorted_vertices[k]) {\n                if (active[i]) {\n                    if (vdist[i][k] <= 5000.0 + 1e-9) covered = true;\n                    double d = vdist[i][k];\n                    if (d > max_d[i]) max_d[i] = d;\n                    break;\n                }\n            }\n            if (!covered) return numeric_limits<int64>::max();\n        }\n        vector<tuple<int64, int, int>> edges;\n        for (int j = 0; j < M; ++j) {\n            if (reachable[u[j]] && reachable[v[j]])\n                edges.push_back({w[j], u[j], v[j]});\n        }\n        sort(edges.begin(), edges.end());\n        vector<int> uf(N);\n        iota(uf.begin(), uf.end(), 0);\n        function<int(int)> find = [&](int x) { return uf[x] == x ? x : uf[x] = find(uf[x]); };\n        int64 conn_cost = 0;\n        int comps = count(reachable.begin(), reachable.end(), true);\n        int used = 0;\n        for (auto &[wt, a, b] : edges) {\n            int ra = find(a), rb = find(b);\n            if (ra != rb) {\n                uf[ra] = rb;\n                conn_cost += wt;\n                if (++used == comps - 1) break;\n            }\n        }\n        if (used != comps - 1) return numeric_limits<int64>::max();\n        int64 power_cost = 0;\n        for (int i = 0; i < N; ++i) {\n            if (active[i]) {\n                int Pi = (int)ceil(max_d[i] - 1e-9);\n                if (Pi > 5000) return numeric_limits<int64>::max();\n                power_cost += (int64)Pi * Pi;\n            }\n        }\n        return conn_cost + power_cost;\n    };\n\n    // initial state\n    vector<bool> cur_A(N, true);\n    int64 cur_cost = evaluate(cur_A);\n    vector<bool> best_A = cur_A;\n    int64 best_cost = cur_cost;\n\n    // Simulated Annealing\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> rand_vertex(1, N - 1);\n    uniform_real_distribution<double> rand_double(0.0, 1.0);\n    double T_start = max(1e6, (double)cur_cost * 0.05);\n    double T_end = T_start * 1e-4;\n\n    while (elapsed() < 1.9) {\n        double frac = elapsed() / 1.9;\n        double T = T_start * pow(T_end / T_start, frac);\n        if (T < 1e-9) T = 1e-9;\n\n        int i = rand_vertex(rng);\n        bool old = cur_A[i];\n        cur_A[i] = !old;\n        int64 new_cost = evaluate(cur_A);\n        if (new_cost != numeric_limits<int64>::max()) {\n            double delta = (double)(new_cost - cur_cost);\n            bool accept = (delta < 0);\n            if (!accept) {\n                double prob = exp(-delta / T);\n                if (rand_double(rng) < prob) accept = true;\n            }\n            if (accept) {\n                cur_cost = new_cost;\n                if (new_cost < best_cost) {\n                    best_cost = new_cost;\n                    best_A = cur_A;\n                }\n            } else {\n                cur_A[i] = old;\n            }\n        } else {\n            cur_A[i] = old;\n        }\n    }\n\n    // final hill-climbing while time permits\n    bool improved = true;\n    while (improved && elapsed() < 1.95) {\n        improved = false;\n        for (int i = 1; i < N; ++i) {\n            bool old = cur_A[i];\n            cur_A[i] = !old;\n            int64 new_cost = evaluate(cur_A);\n            if (new_cost < cur_cost) {\n                cur_cost = new_cost;\n                if (new_cost < best_cost) {\n                    best_cost = new_cost;\n                    best_A = cur_A;\n                }\n                improved = true;\n            } else {\n                cur_A[i] = old;\n            }\n        }\n    }\n\n    // ---- construct final answer from best_A ----\n    vector<int> act;\n    for (int i = 0; i < N; ++i) if (best_A[i]) act.push_back(i);\n    int m = act.size();\n    vector<pair<int, int>> mst_edges;\n    if (m > 1) {\n        vector<bool> inmst(m, false);\n        vector<int64> minw(m, numeric_limits<int64>::max());\n        vector<int> parent(m, -1);\n        minw[0] = 0;\n        for (int i = 0; i < m; ++i) {\n            int u = -1;\n            for (int j = 0; j < m; ++j)\n                if (!inmst[j] && (u == -1 || minw[j] < minw[u])) u = j;\n            inmst[u] = true;\n            if (parent[u] != -1)\n                mst_edges.push_back({act[u], act[parent[u]]});\n            for (int v = 0; v < m; ++v) {\n                if (!inmst[v]) {\n                    int64 wgt = dist[act[u]][act[v]];\n                    if (wgt < minw[v]) {\n                        minw[v] = wgt;\n                        parent[v] = u;\n                    }\n                }\n            }\n        }\n    }\n    vector<bool> tmp_used(M, false);\n    for (auto [a, b] : mst_edges) {\n        int cur = b;\n        while (cur != a) {\n            int p = pred[a][cur];\n            int eid = edge_id[p * N + cur];\n            if (eid != -1) tmp_used[eid] = true;\n            cur = p;\n        }\n    }\n    vector<bool> reachable(N, false);\n    queue<int> q;\n    reachable[0] = true; q.push(0);\n    while (!q.empty()) {\n        int node = q.front(); q.pop();\n        for (auto &[to, weight] : adj[node]) {\n            int eid = edge_id[node * N + to];\n            if (tmp_used[eid] && !reachable[to]) {\n                reachable[to] = true;\n                q.push(to);\n            }\n        }\n    }\n\n    vector<int> final_B(M, 0);\n    {\n        vector<tuple<int64, int, int>> edges;\n        for (int j = 0; j < M; ++j)\n            if (reachable[u[j]] && reachable[v[j]])\n                edges.push_back({w[j], u[j], v[j]});\n        sort(edges.begin(), edges.end());\n        vector<int> uf(N);\n        iota(uf.begin(), uf.end(), 0);\n        function<int(int)> find = [&](int x) { return uf[x] == x ? x : uf[x] = find(uf[x]); };\n        int comps = count(reachable.begin(), reachable.end(), true);\n        int used = 0;\n        for (auto &[wt, a, b] : edges) {\n            int ra = find(a), rb = find(b);\n            if (ra != rb) {\n                uf[ra] = rb;\n                int eid = edge_id[a * N + b];\n                if (eid != -1) final_B[eid] = 1;\n                if (++used == comps - 1) break;\n            }\n        }\n    }\n\n    vector<int> final_P(N, 0);\n    {\n        vector<double> max_d(N, 0.0);\n        for (int k = 0; k < K; ++k) {\n            for (int i : sorted_vertices[k]) {\n                if (reachable[i]) {\n                    double d = vdist[i][k];\n                    if (d > max_d[i]) max_d[i] = d;\n                    break;\n                }\n            }\n        }\n        for (int i = 0; i < N; ++i) {\n            if (reachable[i]) {\n                int Pi = (int)ceil(max_d[i] - 1e-9);\n                if (Pi > 5000) Pi = 5000;\n                final_P[i] = Pi;\n            }\n        }\n    }\n\n    // output\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << final_P[i];\n    }\n    cout << '\\n';\n    for (int j = 0; j < M; ++j) {\n        if (j) cout << ' ';\n        cout << final_B[j];\n    }\n    cout << '\\n';\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30;\nconst int V = N * (N + 1) / 2; // 465\n\nint node_id(int x, int y) {\n    return x * (x + 1) / 2 + y;\n}\n\npair<int,int> coord[V];\nint xcoord[V], ycoord[V];\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    // Precompute coordinates\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int id = node_id(x, y);\n            coord[id] = {x, y};\n            xcoord[id] = x;\n            ycoord[id] = y;\n        }\n    }\n\n    // Read initial state\n    vector<int> grid(V);\n    vector<int> pos(V); // value -> node id\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int v;\n            cin >> v;\n            int id = node_id(x, y);\n            grid[id] = v;\n            pos[v] = id;\n        }\n    }\n\n    // Adjacency list\n    vector<vector<int>> adj(V);\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int u = node_id(x, y);\n            if (x > 0 && y > 0) adj[u].push_back(node_id(x - 1, y - 1));\n            if (x > 0 && y <= x - 1) adj[u].push_back(node_id(x - 1, y));\n            if (y > 0) adj[u].push_back(node_id(x, y - 1));\n            if (y < x) adj[u].push_back(node_id(x, y + 1));\n            if (x < N - 1) {\n                adj[u].push_back(node_id(x + 1, y));\n                adj[u].push_back(node_id(x + 1, y + 1));\n            }\n        }\n    }\n\n    // Target row for each value (sorted order)\n    vector<int> target_r(V);\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c <= r; ++c) {\n            int v = r * (r + 1) / 2 + c;\n            target_r[v] = r;\n        }\n    }\n\n    // Group values by target row\n    vector<vector<int>> row_vals(N);\n    for (int v = 0; v < V; ++v) {\n        row_vals[target_r[v]].push_back(v);\n    }\n\n    // All-pairs distances (BFS)\n    vector<vector<int>> dist(V, vector<int>(V, -1));\n    for (int s = 0; s < V; ++s) {\n        queue<int> q;\n        q.push(s);\n        dist[s][s] = 0;\n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            for (int v : adj[u]) {\n                if (dist[s][v] == -1) {\n                    dist[s][v] = dist[s][u] + 1;\n                    q.push(v);\n                }\n            }\n        }\n    }\n\n    // Hungarian algorithm for minimum cost assignment\n    auto hungarian = [&](const vector<vector<int>>& a) -> vector<int> {\n        int n = a.size(), m = a[0].size();\n        vector<int> u(n + 1), v(m + 1), p(m + 1), way(m + 1);\n        for (int i = 1; i <= n; ++i) {\n            p[0] = i;\n            int j0 = 0;\n            vector<int> minv(m + 1, INT_MAX);\n            vector<char> used(m + 1, false);\n            do {\n                used[j0] = true;\n                int i0 = p[j0], delta = INT_MAX, j1 = 0;\n                for (int j = 1; j <= m; ++j) {\n                    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                }\n                for (int j = 0; j <= m; ++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        vector<int> ass(n);\n        for (int j = 1; j <= m; ++j) {\n            if (p[j] != 0) {\n                ass[p[j] - 1] = j - 1;\n            }\n        }\n        return ass;\n    };\n\n    // Assign optimal target node for each value within its row\n    vector<int> target_node(V);\n    for (int r = 0; r < N; ++r) {\n        int m = row_vals[r].size();\n        vector<vector<int>> cost(m, vector<int>(m));\n        for (int i = 0; i < m; ++i) {\n            int v = row_vals[r][i];\n            int sid = pos[v];\n            for (int j = 0; j < m; ++j) {\n                int tid = node_id(r, j);\n                cost[i][j] = dist[sid][tid];\n            }\n        }\n        vector<int> assign = hungarian(cost);\n        for (int i = 0; i < m; ++i) {\n            int v = row_vals[r][i];\n            int col = assign[i];\n            target_node[v] = node_id(r, col);\n        }\n    }\n\n    // Inverse mapping: node -> value\n    vector<int> target_val(V, -1);\n    for (int v = 0; v < V; ++v) {\n        target_val[target_node[v]] = v;\n    }\n\n    // Bottom-up token placement\n    vector<bool> locked(V, false);\n    vector<pair<int,int>> moves; // (node1, node2)\n\n    for (int r = N - 1; r >= 0; --r) {\n        for (int c = 0; c <= r; ++c) {\n            int tgt_id = node_id(r, c);\n            int v = target_val[tgt_id];\n            while (pos[v] != tgt_id) {\n                int start = pos[v];\n                // BFS to find path avoiding locked nodes\n                queue<int> q;\n                vector<int> parent(V, -1);\n                q.push(start);\n                parent[start] = start;\n                while (!q.empty()) {\n                    int u = q.front(); q.pop();\n                    if (u == tgt_id) break;\n                    for (int w : adj[u]) {\n                        if (!locked[w] && parent[w] == -1) {\n                            parent[w] = u;\n                            q.push(w);\n                        }\n                    }\n                }\n                // Reconstruct path\n                vector<int> path;\n                int cur = tgt_id;\n                while (cur != start) {\n                    path.push_back(cur);\n                    cur = parent[cur];\n                }\n                path.push_back(start);\n                reverse(path.begin(), path.end());\n\n                // Execute swaps along the path\n                for (size_t i = 0; i + 1 < path.size(); ++i) {\n                    int u1 = path[i], u2 = path[i + 1];\n                    int val1 = grid[u1], val2 = grid[u2];\n                    swap(grid[u1], grid[u2]);\n                    pos[val1] = u2;\n                    pos[val2] = u1;\n                    moves.emplace_back(u1, u2);\n                    if ((int)moves.size() > 10000) {\n                        // Extremely unlikely; truncate to stay within limit\n                        moves.resize(10000);\n                        goto output_moves;\n                    }\n                }\n            }\n            locked[tgt_id] = true;\n        }\n    }\n\noutput_moves:\n    cout << moves.size() << \"\\n\";\n    for (auto [u1, u2] : moves) {\n        cout << xcoord[u1] << \" \" << ycoord[u1] << \" \"\n             << xcoord[u2] << \" \" << ycoord[u2] << \"\\n\";\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <functional>\n#include <utility>\n\nusing namespace std;\n\nint main() {\n    // Read initial information\n    int D, N;\n    cin >> D >> N;\n    int ent_r = 0, ent_c = (D - 1) / 2;\n    int start = ent_r * D + ent_c;\n\n    // Mark cells that cannot hold containers (entrance + obstacles)\n    vector<vector<bool>> blocked(D, vector<bool>(D, false));\n    blocked[ent_r][ent_c] = true;  // entrance\n    for (int i = 0; i < N; i++) {\n        int r, c;\n        cin >> r >> c;\n        blocked[r][c] = true;\n    }\n\n    int K = D * D - 1 - N;  // number of containers\n\n    // BFS distances from entrance over free cells\n    vector<int> dist(D * D, -1);\n    queue<int> q;\n    dist[start] = 0;\n    q.push(start);\n    const int dr[4] = {-1, 1, 0, 0};\n    const int dc[4] = {0, 0, -1, 1};\n\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        int r = u / D, c = u % D;\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n            if (blocked[nr][nc]) continue;\n            int v = nr * D + nc;\n            if (dist[v] == -1) {\n                dist[v] = dist[u] + 1;\n                q.push(v);\n            }\n        }\n    }\n\n    // Collect all free cells (non-blocked, non-entrance)\n    vector<int> free_cells;\n    for (int r = 0; r < D; r++) {\n        for (int c = 0; c < D; c++) {\n            if (!blocked[r][c]) {\n                free_cells.push_back(r * D + c);\n            }\n        }\n    }\n\n    // Sort free cells by distance, then by ID (row-major)\n    sort(free_cells.begin(), free_cells.end(), [&](int a, int b) {\n        if (dist[a] != dist[b]) return dist[a] < dist[b];\n        return a < b;\n    });\n\n    // Prepare mapping: order of each cell, and ideal cell for each rank\n    vector<int> ord(D * D, -1);\n    vector<int> ideal(K);\n    for (int i = 0; i < K; i++) {\n        int cell = free_cells[i];\n        ord[cell] = i;\n        ideal[i] = cell;\n    }\n\n    // State of the warehouse\n    vector<bool> occupied(D * D, false);\n    vector<int> rank_at(D * D, -1);\n\n    // Process arrivals\n    for (int d = 0; d < K; d++) {\n        int rank;\n        cin >> rank;\n\n        // Get all empty cells currently reachable from entrance\n        vector<int> reachable;\n        vector<bool> vis(D * D, false);\n        queue<int> bfs;\n        bfs.push(start);\n        vis[start] = true;\n        while (!bfs.empty()) {\n            int u = bfs.front(); bfs.pop();\n            reachable.push_back(u);\n            int r = u / D, c = u % D;\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (blocked[nr][nc]) continue;\n                int v = nr * D + nc;\n                if (occupied[v]) continue;\n                if (!vis[v]) {\n                    vis[v] = true;\n                    bfs.push(v);\n                }\n            }\n        }\n\n        // Build adjacency among reachable cells\n        vector<vector<int>> adj(D * D);\n        for (int u : reachable) {\n            int r = u / D, c = u % D;\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (blocked[nr][nc]) continue;\n                int v = nr * D + nc;\n                if (occupied[v]) continue;\n                if (vis[v]) {\n                    adj[u].push_back(v);\n                }\n            }\n        }\n\n        // Find articulation points (cells that would disconnect the empty area)\n        vector<int> disc(D * D, -1), low(D * D, -1);\n        vector<bool> is_art(D * D, false);\n        int timer = 0;\n        function<void(int, int)> dfs = [&](int u, int parent) {\n            disc[u] = low[u] = timer++;\n            int children = 0;\n            for (int v : adj[u]) {\n                if (v == parent) continue;\n                if (disc[v] == -1) {\n                    dfs(v, u);\n                    low[u] = min(low[u], low[v]);\n                    if (parent != -1 && low[v] >= disc[u]) {\n                        is_art[u] = true;\n                    }\n                    children++;\n                } else {\n                    low[u] = min(low[u], disc[v]);\n                }\n            }\n            if (parent == -1 && children > 1) {\n                is_art[u] = true;\n            }\n        };\n        dfs(start, -1);\n\n        // Safe cells = reachable empty cells except entrance and articulation points\n        vector<int> safe;\n        for (int u : reachable) {\n            if (u == start) continue;\n            if (!is_art[u]) {\n                safe.push_back(u);\n            }\n        }\n\n        // Choose placement cell\n        int target = ideal[rank];\n        int chosen = -1;\n        bool target_safe = false;\n        for (int u : safe) if (u == target) { target_safe = true; break; }\n\n        if (target_safe) {\n            chosen = target;\n        } else {\n            int best_diff = 1e9;\n            for (int u : safe) {\n                int diff = abs(ord[u] - rank);\n                if (diff < best_diff) {\n                    best_diff = diff;\n                    chosen = u;\n                } else if (diff == best_diff) {\n                    if (ord[u] < ord[chosen]) {\n                        chosen = u;\n                    }\n                }\n            }\n        }\n\n        // Place the container\n        occupied[chosen] = true;\n        rank_at[chosen] = rank;\n        cout << chosen / D << \" \" << chosen % D << endl;\n    }\n\n    // Removal phase\n    vector<bool> removed(D * D, false);\n    vector<pair<int, int>> removal_seq;\n\n    while (removal_seq.size() < K) {\n        queue<int> bfs;\n        vector<bool> vis(D * D, false);\n        bfs.push(start);\n        vis[start] = true;\n        vector<int> candidates;\n\n        while (!bfs.empty()) {\n            int u = bfs.front(); bfs.pop();\n            int r = u / D, c = u % D;\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (blocked[nr][nc]) continue;\n                int v = nr * D + nc;\n                if (vis[v]) continue;\n                if (removed[v] || v == start) {\n                    vis[v] = true;\n                    bfs.push(v);\n                } else if (occupied[v] && !removed[v]) {\n                    candidates.push_back(v);\n                }\n            }\n        }\n\n        sort(candidates.begin(), candidates.end());\n        candidates.erase(unique(candidates.begin(), candidates.end()), candidates.end());\n\n        int best = -1, best_rank = 1e9;\n        for (int v : candidates) {\n            if (rank_at[v] < best_rank) {\n                best_rank = rank_at[v];\n                best = v;\n            }\n        }\n\n        removed[best] = true;\n        removal_seq.emplace_back(best / D, best % D);\n    }\n\n    for (auto [r, c] : removal_seq) {\n        cout << r << \" \" << c << endl;\n    }\n\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 50;\nconst int N2 = N * N;\nconst int MAXC = 101; // 0..100\n\nbool adj_req[MAXC][MAXC];\nint vis[N2];\nint vis_token = 0;\nint bfs_queue[N2];\nvector<array<int,4>> nb(N2);\nvector<int> boundary_idx;\n\nvoid compute_energy(const int* g, int m, int& E, int& viol_conn, int& viol_adj) {\n    ++vis_token;\n    E = 0;\n    viol_conn = 0;\n    viol_adj = 0;\n    int comp_count[MAXC] = {0};\n    int cell_count[MAXC] = {0};\n\n    // Connectivity for colors 1..m\n    for (int i = 0; i < N2; ++i) {\n        int c = g[i];\n        if (c == 0) {\n            ++E;\n        } else {\n            cell_count[c]++;\n            if (vis[i] != vis_token) {\n                comp_count[c]++;\n                int head = 0, tail = 0;\n                bfs_queue[tail++] = i;\n                vis[i] = vis_token;\n                while (head < tail) {\n                    int v = bfs_queue[head++];\n                    for (int nbr : nb[v]) {\n                        if (nbr != -1 && g[nbr] == c && vis[nbr] != vis_token) {\n                            vis[nbr] = vis_token;\n                            bfs_queue[tail++] = nbr;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    for (int c = 1; c <= m; ++c) {\n        if (cell_count[c] == 0) viol_conn += 1;\n        else if (comp_count[c] != 1) viol_conn += comp_count[c] - 1;\n    }\n\n    // Connectivity for 0 (must be connected to the outside)\n    int head = 0, tail = 0;\n    for (int idx : boundary_idx) {\n        if (g[idx] == 0 && vis[idx] != vis_token) {\n            vis[idx] = vis_token;\n            bfs_queue[tail++] = idx;\n        }\n    }\n    while (head < tail) {\n        int v = bfs_queue[head++];\n        for (int nbr : nb[v]) {\n            if (nbr != -1 && g[nbr] == 0 && vis[nbr] != vis_token) {\n                vis[nbr] = vis_token;\n                bfs_queue[tail++] = nbr;\n            }\n        }\n    }\n    int unvisited_0 = 0;\n    for (int i = 0; i < N2; ++i) {\n        if (g[i] == 0 && vis[i] != vis_token) ++unvisited_0;\n    }\n    viol_conn += unvisited_0;\n\n    // Adjacency\n    int adj[MAXC][MAXC] = {0};\n    for (int i = 0; i < N2; ++i) {\n        int c1 = g[i];\n        if (i % N < N - 1) {\n            int c2 = g[i + 1];\n            if (c1 != c2) { adj[c1][c2]++; adj[c2][c1]++; }\n        }\n        if (i / N < N - 1) {\n            int c2 = g[i + N];\n            if (c1 != c2) { adj[c1][c2]++; adj[c2][c1]++; }\n        }\n    }\n    // Boundary edges with outside 0\n    for (int idx : boundary_idx) {\n        int c = g[idx];\n        if (c != 0) {\n            adj[c][0]++;\n            adj[0][c]++;\n        }\n    }\n    for (int a = 0; a <= m; ++a) {\n        for (int b = a + 1; b <= m; ++b) {\n            if (adj_req[a][b]) {\n                if (adj[a][b] == 0) viol_adj++;\n            } else {\n                if (adj[a][b] > 0) viol_adj += adj[a][b];\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start_time = chrono::high_resolution_clock::now();\n    auto elapsed_ms = [&]() {\n        return chrono::duration_cast<chrono::milliseconds>(\n            chrono::high_resolution_clock::now() - start_time).count();\n    };\n\n    int n, m;\n    cin >> n >> m;\n    vector<vector<int>> orig(n, vector<int>(n));\n    for (int i = 0; i < n; ++i)\n        for (int j = 0; j < n; ++j)\n            cin >> orig[i][j];\n\n    // Build required adjacency graph from the original map\n    memset(adj_req, 0, sizeof(adj_req));\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c1 = orig[i][j];\n            if (j < n - 1) {\n                int c2 = orig[i][j + 1];\n                if (c1 != c2) adj_req[c1][c2] = adj_req[c2][c1] = true;\n            }\n            if (i < n - 1) {\n                int c2 = orig[i + 1][j];\n                if (c1 != c2) adj_req[c1][c2] = adj_req[c2][c1] = true;\n            }\n            if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                adj_req[c1][0] = adj_req[0][c1] = true;\n            }\n        }\n    }\n\n    // Precompute 4\u2011neighbors and boundary indices\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int idx = i * n + j;\n            nb[idx][0] = (i > 0) ? idx - n : -1;\n            nb[idx][1] = (i < n - 1) ? idx + n : -1;\n            nb[idx][2] = (j > 0) ? idx - 1 : -1;\n            nb[idx][3] = (j < n - 1) ? idx + 1 : -1;\n            if (i == 0 || i == n - 1 || j == 0 || j == n - 1)\n                boundary_idx.push_back(idx);\n        }\n    }\n\n    // ----- Phase 1: greedy erosion from the boundary -----\n    int g2d[N][N];\n    int count[MAXC] = {0};\n    int adj[MAXC][MAXC] = {0};\n\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            g2d[i][j] = orig[i][j];\n            count[orig[i][j]]++;\n        }\n    }\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c1 = g2d[i][j];\n            if (j < n - 1) {\n                int c2 = g2d[i][j + 1];\n                if (c1 != c2) { adj[c1][c2]++; adj[c2][c1]++; }\n            }\n            if (i < n - 1) {\n                int c2 = g2d[i + 1][j];\n                if (c1 != c2) { adj[c1][c2]++; adj[c2][c1]++; }\n            }\n            if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                if (c1 != 0) { adj[c1][0]++; adj[0][c1]++; }\n            }\n        }\n    }\n\n    int vis_g[N][N];\n    int vis_token_g = 0;\n    auto has_zero_neighbor = [&](int i, int j) -> bool {\n        if (i == 0 || i == n - 1 || j == 0 || j == n - 1) return true;\n        if (g2d[i - 1][j] == 0 || g2d[i + 1][j] == 0 ||\n            g2d[i][j - 1] == 0 || g2d[i][j + 1] == 0) return true;\n        return false;\n    };\n\n    auto try_remove = [&](int i, int j) -> bool {\n        int c = g2d[i][j];\n        if (c == 0 || count[c] <= 1) return false;\n        const int di[] = {-1, 1, 0, 0};\n        const int dj[] = {0, 0, -1, 1};\n\n        int lost[MAXC] = {0}, gain[MAXC] = {0};\n        for (int k = 0; k < 4; ++k) {\n            int ni = i + di[k], nj = j + dj[k];\n            int d;\n            if (ni < 0 || ni >= n || nj < 0 || nj >= n) d = 0;\n            else d = g2d[ni][nj];\n            if (d == c) continue;\n            lost[d]++;\n            if (d != 0) gain[d]++;\n        }\n        for (int d = 0; d <= m; ++d) {\n            if (lost[d] > 0 && adj_req[c][d] && adj[c][d] - lost[d] < 1) return false;\n            if (gain[d] > 0 && !adj_req[0][d]) return false;\n        }\n\n        // Connectivity of color c after removal\n        int si = -1, sj = -1;\n        for (int k = 0; k < 4; ++k) {\n            int ni = i + di[k], nj = j + dj[k];\n            if (ni >= 0 && ni < n && nj >= 0 && nj < n && g2d[ni][nj] == c) {\n                si = ni; sj = nj; break;\n            }\n        }\n        if (si == -1) return false;\n        ++vis_token_g;\n        queue<pair<int,int>> q;\n        q.push({si, sj});\n        vis_g[si][sj] = vis_token_g;\n        int visited = 0;\n        while (!q.empty()) {\n            auto [x, y] = q.front(); q.pop();\n            visited++;\n            for (int k = 0; k < 4; ++k) {\n                int nx = x + di[k], ny = y + dj[k];\n                if (nx >= 0 && nx < n && ny >= 0 && ny < n &&\n                    !(nx == i && ny == j) && g2d[nx][ny] == c &&\n                    vis_g[nx][ny] != vis_token_g) {\n                    vis_g[nx][ny] = vis_token_g;\n                    q.push({nx, ny});\n                }\n            }\n        }\n        if (visited != count[c] - 1) return false;\n        return true;\n    };\n\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                if (g2d[i][j] == 0 || !has_zero_neighbor(i, j)) continue;\n                if (try_remove(i, j)) {\n                    int c = g2d[i][j];\n                    const int di[] = {-1, 1, 0, 0};\n                    const int dj[] = {0, 0, -1, 1};\n                    for (int k = 0; k < 4; ++k) {\n                        int ni = i + di[k], nj = j + dj[k];\n                        int d;\n                        if (ni < 0 || ni >= n || nj < 0 || nj >= n) d = 0;\n                        else d = g2d[ni][nj];\n                        if (d == c) continue;\n                        adj[c][d]--; adj[d][c]--;\n                        if (d != 0) { adj[0][d]++; adj[d][0]++; }\n                    }\n                    g2d[i][j] = 0;\n                    count[c]--;\n                    changed = true;\n                }\n            }\n        }\n    }\n\n    // Convert greedy result to 1D\n    int init_g[N2];\n    for (int i = 0; i < n; ++i)\n        for (int j = 0; j < n; ++j)\n            init_g[i * n + j] = g2d[i][j];\n\n    // ----- Phase 2: Simulated Annealing -----\n    int cur_g[N2];\n    memcpy(cur_g, init_g, sizeof(cur_g));\n    int best_valid_g[N2];\n    memcpy(best_valid_g, init_g, sizeof(best_valid_g));\n    int best_valid_E = -1;\n\n    int testE, testVc, testVa;\n    compute_energy(init_g, m, testE, testVc, testVa);\n    if (testVc == 0 && testVa == 0) best_valid_E = testE;\n\n    const double W_CONN = 5000.0;\n    const double W_ADJ  = 5000.0;\n    const double T_start = 100000.0;\n    const double T_end   = 0.1;\n\n    int cur_E, cur_vc, cur_va;\n    compute_energy(cur_g, m, cur_E, cur_vc, cur_va);\n    double cur_energy = -cur_E + W_CONN * cur_vc + W_ADJ * cur_va;\n    double best_energy = cur_energy;\n\n    uint64_t rng_state = 123456789;\n    auto rng_next = [&]() -> uint64_t {\n        rng_state = rng_state * 6364136223846793005ULL + 1442695040888963407ULL;\n        return rng_state >> 33;\n    };\n    auto rng_int = [&](int n) { return rng_next() % n; };\n    auto rng_double = [&]() { return (rng_next() & 0xFFFFFFFF) / 4294967296.0; };\n\n    while (elapsed_ms() < 1800) {\n        double progress = elapsed_ms() / 1800.0;\n        double T = T_start * pow(T_end / T_start, progress);\n\n        int idx = rng_int(N2);\n        int old_c = cur_g[idx];\n        int new_c = (rng_double() < 0.5) ? 0 : (rng_int(m) + 1);\n        if (new_c == old_c) continue;\n\n        cur_g[idx] = new_c;\n        int new_E, new_vc, new_va;\n        compute_energy(cur_g, m, new_E, new_vc, new_va);\n        double new_energy = -new_E + W_CONN * new_vc + W_ADJ * new_va;\n        double delta = new_energy - cur_energy;\n\n        bool accept = (delta <= 0) || (rng_double() < exp(-delta / T));\n        if (accept) {\n            cur_energy = new_energy;\n            cur_E = new_E; cur_vc = new_vc; cur_va = new_va;\n            if (new_energy < best_energy) best_energy = new_energy;\n            if (new_vc == 0 && new_va == 0 && new_E > best_valid_E) {\n                best_valid_E = new_E;\n                memcpy(best_valid_g, cur_g, sizeof(best_valid_g));\n            }\n        } else {\n            cur_g[idx] = old_c;\n        }\n    }\n\n    // Output the best valid grid found (fallback to the original if none)\n    if (best_valid_E < 0) {\n        // Use the original input (always valid)\n        for (int i = 0; i < n; ++i)\n            for (int j = 0; j < n; ++j)\n                best_valid_g[i * n + j] = orig[i][j];\n    }\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (j) cout << ' ';\n            cout << best_valid_g[i * n + j];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <cmath>\n\nusing namespace std;\n\nstruct Query {\n    vector<int> L, R;\n    char res;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    int N, D, Q;\n    cin >> N >> D >> Q;\n    \n    vector<double> w(N, 1.0);\n    const double MIN_W = 1.0;\n    const double MAX_W = 1e9;\n    \n    // best partition so far (evaluated on estimated weights)\n    vector<int> P_best(N);\n    for (int i = 0; i < N; ++i) P_best[i] = i % D;\n    double best_var = 1e18;\n    \n    vector<Query> history;\n    history.reserve(Q);\n    \n    // Update estimated weights based on one query result\n    auto update_weights_online = [&](const vector<int>& L, const vector<int>& R, char res, double lr) {\n        double sL = 0.0, sR = 0.0;\n        for (int i : L) sL += w[i];\n        for (int i : R) sR += w[i];\n        \n        const double margin = 0.0;\n        if (res == '<') {\n            if (sL >= sR - margin) {\n                double error = sL - sR + margin;\n                double adjL = lr * error / max(1, (int)L.size());\n                double adjR = lr * error / max(1, (int)R.size());\n                for (int i : L) w[i] -= adjL;\n                for (int i : R) w[i] += adjR;\n            }\n        } else if (res == '>') {\n            if (sL <= sR + margin) {\n                double error = sR - sL + margin;\n                double adjL = lr * error / max(1, (int)L.size());\n                double adjR = lr * error / max(1, (int)R.size());\n                for (int i : L) w[i] += adjL;\n                for (int i : R) w[i] -= adjR;\n            }\n        } else { // '='\n            double diff = sL - sR;\n            if (fabs(diff) > margin) {\n                double adjL = lr * diff / max(1, (int)L.size());\n                double adjR = lr * diff / max(1, (int)R.size());\n                for (int i : L) w[i] -= adjL;\n                for (int i : R) w[i] += adjR;\n            }\n        }\n        // clip to feasible range\n        for (int i : L) { if (w[i] < MIN_W) w[i] = MIN_W; if (w[i] > MAX_W) w[i] = MAX_W; }\n        for (int i : R) { if (w[i] < MIN_W) w[i] = MIN_W; if (w[i] > MAX_W) w[i] = MAX_W; }\n    };\n    \n    // Greedy best-fit decreasing partition using current weight estimates\n    auto compute_partition = [&](vector<int>& out_P) -> double {\n        vector<pair<double,int>> items(N);\n        for (int i = 0; i < N; ++i) items[i] = {w[i], i};\n        sort(items.begin(), items.end(), [](auto& a, auto& b) { return a.first > b.first; });\n        \n        vector<double> bin_sum(D, 0.0);\n        out_P.assign(N, 0);\n        for (auto& p : items) {\n            int idx = p.second;\n            int best_b = 0;\n            for (int b = 1; b < D; ++b)\n                if (bin_sum[b] < bin_sum[best_b]) best_b = b;\n            out_P[idx] = best_b;\n            bin_sum[best_b] += p.first;\n        }\n        double mean = accumulate(bin_sum.begin(), bin_sum.end(), 0.0) / D;\n        double var = 0.0;\n        for (double s : bin_sum) var += (s - mean) * (s - mean);\n        var /= D;\n        return var;\n    };\n    \n    auto update_best = [&]() {\n        vector<int> P_curr(N);\n        double var = compute_partition(P_curr);\n        if (var < best_var) {\n            best_var = var;\n            P_best = P_curr;\n        }\n    };\n    \n    mt19937 rng(12345);\n    uniform_real_distribution<double> prob(0.0, 1.0);\n    \n    // Main query loop\n    for (int q = 0; q < Q; ++q) {\n        vector<int> L, R;\n        bool use_bin = (q >= 0.3 * Q);  // 30% exploration, 70% exploitation\n        \n        if (use_bin) {\n            // Compare two bins whose current estimated sums are closest\n            vector<double> bin_sum(D, 0.0);\n            for (int i = 0; i < N; ++i) bin_sum[P_best[i]] += w[i];\n            int b1 = -1, b2 = -1;\n            double min_diff = 1e18;\n            for (int i = 0; i < D; ++i) {\n                if (bin_sum[i] == 0) continue;\n                for (int j = i + 1; j < D; ++j) {\n                    if (bin_sum[j] == 0) continue;\n                    double diff = fabs(bin_sum[i] - bin_sum[j]);\n                    if (diff < min_diff) {\n                        min_diff = diff;\n                        b1 = i; b2 = j;\n                    }\n                }\n            }\n            if (b1 != -1 && b2 != -1) {\n                for (int i = 0; i < N; ++i) {\n                    if (P_best[i] == b1) L.push_back(i);\n                    else if (P_best[i] == b2) R.push_back(i);\n                }\n            } else {\n                use_bin = false; // fallback\n            }\n        }\n        \n        if (!use_bin) {\n            // Random balanced split: choose a random subset of items\n            int K = max(2, N / 2 + (int)(rng() % (N / 2 + 1)));\n            vector<int> indices(N);\n            iota(indices.begin(), indices.end(), 0);\n            shuffle(indices.begin(), indices.end(), rng);\n            vector<int> pool(indices.begin(), indices.begin() + K);\n            // sort by descending weight estimate\n            sort(pool.begin(), pool.end(), [&](int a, int b) { return w[a] > w[b]; });\n            L.clear(); R.clear();\n            double sumL = 0.0, sumR = 0.0;\n            for (int idx : pool) {\n                if (L.empty()) { L.push_back(idx); sumL += w[idx]; }\n                else if (R.empty()) { R.push_back(idx); sumR += w[idx]; }\n                else {\n                    if (sumL <= sumR) { L.push_back(idx); sumL += w[idx]; }\n                    else { R.push_back(idx); sumR += w[idx]; }\n                }\n            }\n        }\n        \n        // Output the query\n        cout << L.size() << \" \" << R.size();\n        for (int x : L) cout << \" \" << x;\n        for (int x : R) cout << \" \" << x;\n        cout << endl;\n        \n        char res;\n        cin >> res;\n        history.push_back({L, R, res});\n        \n        // Online weight update\n        double lr = 0.1 / (1.0 + q * 0.1);\n        update_weights_online(L, R, res, lr);\n        \n        // Periodically run a batch correction on all history\n        if ((q + 1) % 100 == 0) {\n            for (int epoch = 0; epoch < 3; ++epoch) {\n                double blr = 0.01;\n                for (auto& hist : history) {\n                    update_weights_online(hist.L, hist.R, hist.res, blr);\n                }\n            }\n        }\n        \n        // Refresh best partition based on current estimates\n        update_best();\n    }\n    \n    // Post-query local search using the final weight estimates\n    vector<int> P = P_best;\n    vector<double> bin_sum(D, 0.0);\n    double total_w = 0.0;\n    for (int i = 0; i < N; ++i) {\n        bin_sum[P[i]] += w[i];\n        total_w += w[i];\n    }\n    double mean = total_w / D;\n    double var = 0.0;\n    for (int b = 0; b < D; ++b) var += (bin_sum[b] - mean) * (bin_sum[b] - mean);\n    var /= D;\n    \n    mt19937 rng2(54321);\n    uniform_int_distribution<int> dist_item(0, N - 1);\n    uniform_int_distribution<int> dist_bin(0, D - 1);\n    const int SA_ITERS = 500000;\n    \n    for (int it = 0; it < SA_ITERS; ++it) {\n        int i = dist_item(rng2);\n        int old_b = P[i];\n        int new_b = dist_bin(rng2);\n        if (new_b == old_b) continue;\n        \n        double new_sum_old = bin_sum[old_b] - w[i];\n        double new_sum_new = bin_sum[new_b] + w[i];\n        \n        double old_term_old = (bin_sum[old_b] - mean) * (bin_sum[old_b] - mean);\n        double old_term_new = (bin_sum[new_b] - mean) * (bin_sum[new_b] - mean);\n        double new_term_old = (new_sum_old - mean) * (new_sum_old - mean);\n        double new_term_new = (new_sum_new - mean) * (new_sum_new - mean);\n        double delta = (new_term_old - old_term_old + new_term_new - old_term_new) / D;\n        double new_var = var + delta;\n        \n        if (new_var < var) {\n            var = new_var;\n            P[i] = new_b;\n            bin_sum[old_b] = new_sum_old;\n            bin_sum[new_b] = new_sum_new;\n        }\n    }\n    P_best = P;\n    \n    // Final output\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << \" \";\n        cout << P_best[i];\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc026":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <utility>\n\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    int n, m;\n    cin >> n >> m;\n    \n    vector<vector<int>> stacks(m);\n    // pos[box] = {stack_index, position_from_bottom}\n    vector<pair<int,int>> pos(n + 1);\n    \n    for (int i = 0; i < m; i++) {\n        stacks[i].resize(n / m);\n        for (int j = 0; j < n / m; j++) {\n            cin >> stacks[i][j];\n            pos[stacks[i][j]] = {i, j};\n        }\n    }\n    \n    vector<pair<int,int>> ops;\n    \n    for (int v = 1; v <= n; v++) {\n        auto [s, p] = pos[v];\n        // v should always be present in the current state\n        if (p == (int)stacks[s].size() - 1) {\n            // v is on top, carry it out directly\n            ops.push_back({v, 0});\n            stacks[s].pop_back();\n            pos[v] = {-1, -1};\n        } else {\n            // Boxes above v form a block that needs to be moved\n            int u = stacks[s][p + 1]; // bottom of the block just above v\n            // Compute max value in the block\n            int max_B = 0;\n            for (int i = p + 1; i < (int)stacks[s].size(); i++) {\n                max_B = max(max_B, stacks[s][i]);\n            }\n            \n            // Choose destination stack t\n            int best_t = -1;\n            int best_priority = -1; // 2: ideal, 1: empty, 0: violation\n            int best_key = 0;\n            \n            for (int t = 0; t < m; t++) {\n                if (t == s) continue;\n                if (stacks[t].empty()) {\n                    if (best_priority < 1) {\n                        best_priority = 1;\n                        best_t = t;\n                    }\n                } else {\n                    int min_t = *min_element(stacks[t].begin(), stacks[t].end());\n                    if (min_t > max_B) {\n                        // ideal: all boxes in t are larger than the whole block\n                        if (best_priority < 2) {\n                            best_priority = 2;\n                            best_key = min_t;\n                            best_t = t;\n                        } else if (best_priority == 2 && min_t < best_key) {\n                            best_key = min_t;\n                            best_t = t;\n                        }\n                    } else {\n                        // violation: some boxes in t may be blocked\n                        if (best_priority < 0) {\n                            best_priority = 0;\n                            best_key = min_t;\n                            best_t = t;\n                        } else if (best_priority == 0 && min_t > best_key) {\n                            best_key = min_t;\n                            best_t = t;\n                        }\n                    }\n                }\n            }\n            \n            // Perform move operation (1-indexed stack in output)\n            ops.push_back({u, best_t + 1});\n            vector<int> block(stacks[s].begin() + p + 1, stacks[s].end());\n            stacks[s].erase(stacks[s].begin() + p + 1, stacks[s].end());\n            for (int val : block) {\n                stacks[best_t].push_back(val);\n                pos[val] = {best_t, (int)stacks[best_t].size() - 1};\n            }\n            \n            // Now v is on top, carry it out\n            ops.push_back({v, 0});\n            stacks[s].pop_back();\n            pos[v] = {-1, -1};\n        }\n    }\n    \n    // Output all operations\n    for (auto [val, dst] : ops) {\n        cout << val << \" \" << dst << \"\\n\";\n    }\n    \n    return 0;\n}","ahc027":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <functional>\n\nusing namespace std;\n\nint64_t calc_sum_sq(const vector<int>& times, int L) {\n    if (times.empty()) return 0;\n    int64_t res = 0;\n    int k = times.size();\n    for (int i = 0; i < k - 1; ++i) {\n        int64_t diff = times[i + 1] - times[i];\n        res += diff * diff;\n    }\n    int64_t diff = times[0] + L - times.back();\n    res += diff * diff;\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int N;\n    cin >> N;\n    int V = N * N;\n    vector<string> h(N - 1), v(N);\n    for (int i = 0; i < N - 1; ++i) cin >> h[i];\n    for (int i = 0; i < N; ++i) cin >> v[i];\n    vector<int> d(V);\n    for (int i = 0; i < V; ++i) cin >> d[i];\n\n    auto id = [&](int i, int j) { return i * N + j; };\n\n    vector<vector<int>> adj(V);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = id(i, j);\n            if (j + 1 < N && v[i][j] == '0') {\n                int w = id(i, j + 1);\n                adj[u].push_back(w);\n                adj[w].push_back(u);\n            }\n            if (i + 1 < N && h[i][j] == '0') {\n                int w = id(i + 1, j);\n                adj[u].push_back(w);\n                adj[w].push_back(u);\n            }\n        }\n    }\n\n    // BFS from (0,0) to obtain shortest paths\n    vector<int> dist(V, -1), parent(V, -1);\n    queue<int> q;\n    q.push(0);\n    dist[0] = 0;\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (int w : adj[u]) {\n            if (dist[w] == -1) {\n                dist[w] = dist[u] + 1;\n                parent[w] = u;\n                q.push(w);\n            }\n        }\n    }\n\n    // Iterative DFS to build a base route (doubled spanning tree)\n    vector<int> base_seq;\n    vector<bool> visited(V, false);\n    vector<int> stack = {0};\n    vector<int> edge_idx(V, 0);\n    visited[0] = true;\n    while (!stack.empty()) {\n        int u = stack.back();\n        if (edge_idx[u] < (int)adj[u].size()) {\n            int w = adj[u][edge_idx[u]++];\n            if (!visited[w]) {\n                visited[w] = true;\n                base_seq.push_back(w);\n                stack.push_back(w);\n            }\n        } else {\n            stack.pop_back();\n            if (!stack.empty()) {\n                base_seq.push_back(stack.back());\n            }\n        }\n    }\n    // base_seq ends with 0\n\n    int L0 = base_seq.size();\n    vector<int> cur_k(V, 0);\n    for (int c : base_seq) cur_k[c]++;\n\n    int L_target = 100000;\n    vector<int> seq = base_seq;\n    int L = L0;\n\n    // simple target proportions\n    double sum_sqrt = 0;\n    for (int i = 0; i < V; ++i) sum_sqrt += sqrt(d[i]);\n    vector<double> target_k(V);\n    for (int i = 0; i < V; ++i) target_k[i] = L_target * sqrt(d[i]) / sum_sqrt;\n\n    // add extra cycles until we reach the length limit\n    while (L < L_target) {\n        int best = -1;\n        double best_score = -1;\n        for (int i = 0; i < V; ++i) {\n            double deficit = target_k[i] - cur_k[i];\n            if (deficit > 0) {\n                double score = d[i] * deficit;\n                if (score > best_score) {\n                    best_score = score;\n                    best = i;\n                }\n            }\n        }\n        if (best == -1) break;\n        int dest = best;\n\n        vector<int> path;\n        for (int u = dest; u != 0; u = parent[u]) path.push_back(u);\n        reverse(path.begin(), path.end()); // a1 ... dest\n        int cycle_len = 2 * (int)path.size();\n        if (L + cycle_len > L_target) break;\n\n        // append the cycle 0 -> ... -> dest -> ... -> 0\n        for (int c : path) seq.push_back(c);\n        for (int i = (int)path.size() - 2; i >= 0; --i) seq.push_back(path[i]);\n        seq.push_back(0);\n\n        // update visit counts\n        for (int i = 0; i < (int)path.size(); ++i) {\n            int c = path[i];\n            if (i == (int)path.size() - 1) cur_k[c] += 1; // dest\n            else cur_k[c] += 2;                             // intermediate\n        }\n        cur_k[0] += 1;\n        L += cycle_len;\n    }\n\n    // Build visit times and initial objective\n    vector<vector<int>> times(V);\n    for (int i = 0; i < L; ++i) times[seq[i]].push_back(i);\n\n    int64_t total_O = 0;\n    for (int i = 0; i < V; ++i) total_O += d[i] * calc_sum_sq(times[i], L);\n\n    vector<int> best_seq = seq;\n    int64_t best_O = total_O;\n\n    // Simulated Annealing\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> uni01(0.0, 1.0);\n\n    double T_start = max(1e7, (double)total_O / 1000.0);\n    double T_end = 1e2;\n    double total_time = 1.95;\n    auto start_time = chrono::steady_clock::now();\n\n    vector<int> affected;\n    vector<bool> is_aff(V, false);\n    vector<vector<int>> old_pos(V);\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed >= total_time) break;\n        double ratio = elapsed / total_time;\n        if (ratio > 1.0) ratio = 1.0;\n        double T = T_start * pow(T_end / T_start, ratio);\n\n        // clean up from previous iteration\n        for (int c : affected) {\n            old_pos[c].clear();\n            is_aff[c] = false;\n        }\n        affected.clear();\n\n        if (L < 3) break;\n        int max_len = min(200, L - 2);\n        if (max_len < 1) continue;\n        uniform_int_distribution<int> l_dist(1, L - 3);\n        int l = l_dist(rng);\n        int max_r = min(L - 2, l + max_len - 1);\n        if (max_r < l) continue;\n        uniform_int_distribution<int> r_dist(l, max_r);\n        int r = r_dist(rng);\n\n        int prev = l - 1, next = r + 1;\n        int u1 = seq[prev], v1 = seq[r];\n        int u2 = seq[l], v2 = seq[next];\n        bool adj1 = false, adj2 = false;\n        for (int w : adj[u1]) if (w == v1) { adj1 = true; break; }\n        for (int w : adj[u2]) if (w == v2) { adj2 = true; break; }\n        if (!adj1 || !adj2) continue;\n\n        // collect segment information\n        for (int p = l; p <= r; ++p) {\n            int c = seq[p];\n            if (!is_aff[c]) {\n                is_aff[c] = true;\n                affected.push_back(c);\n            }\n            old_pos[c].push_back(p);\n        }\n\n        int64_t delta = 0;\n        vector<pair<int, vector<int>>> updates;\n        for (int c : affected) {\n            const vector<int>& old_times = times[c];\n            const vector<int>& op = old_pos[c];\n            int64_t old_sq = calc_sum_sq(old_times, L);\n\n            vector<int> new_times;\n            for (int t : old_times) if (t < l) new_times.push_back(t);\n            vector<int> np;\n            for (int p : op) np.push_back(l + r - p);\n            sort(np.begin(), np.end());\n            for (int t : np) new_times.push_back(t);\n            for (int t : old_times) if (t > r) new_times.push_back(t);\n\n            int64_t new_sq = calc_sum_sq(new_times, L);\n            delta += d[c] * (new_sq - old_sq);\n            updates.emplace_back(c, std::move(new_times));\n        }\n\n        bool accept = (delta <= 0);\n        if (!accept) {\n            double prob = exp(-delta / T);\n            if (uni01(rng) < prob) accept = true;\n        }\n\n        if (accept) {\n            reverse(seq.begin() + l, seq.begin() + r + 1);\n            for (auto& p : updates) {\n                times[p.first] = std::move(p.second);\n            }\n            total_O += delta;\n            if (total_O < best_O) {\n                best_O = total_O;\n                best_seq = seq;\n            }\n        }\n    }\n\n    // Output the best route found\n    string ans;\n    int cur = 0;\n    for (int i = 0; i < L; ++i) {\n        int nxt = best_seq[i];\n        int ci = cur / N, cj = cur % N;\n        int ni = nxt / N, nj = nxt % N;\n        if (ni == ci - 1) ans += 'U';\n        else if (ni == ci + 1) ans += 'D';\n        else if (nj == cj - 1) ans += 'L';\n        else if (nj == cj + 1) ans += 'R';\n        else ans += 'U'; // fallback\n        cur = nxt;\n    }\n    cout << ans << endl;\n\n    return 0;\n}","ahc028":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <chrono>\n#include <cmath>\n#include <cstdlib>\n\nusing namespace std;\n\n// Xorshift random generator for speed\nstruct Xorshift {\n    unsigned int x, y, z, w;\n    Xorshift() {\n        auto seed = chrono::steady_clock::now().time_since_epoch().count();\n        x = seed & 0xFFFFFFFF;\n        y = (seed >> 32) ^ 0x12345678;\n        z = seed ^ 0x9abcdef0;\n        w = seed ^ 0xdeadbeef;\n    }\n    unsigned int next() {\n        unsigned int t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = w ^ (w >> 19) ^ t ^ (t >> 8);\n    }\n    int nextInt(int n) { return next() % n; }\n    double nextDouble() { return next() * (1.0 / 4294967296.0); }\n};\n\nconst int INF = 1e9;\nint N, M;\nint start_i, start_j;\nchar grid[15][15];\nvector<string> t;\nvector<int> pos[26];\nint dist[225][225];\nint start_idx;\n\nint dp_prev[225], dp_cur[225];\n\n// Compute minimal total cost for a given string S (without storing the path)\nint compute_DP_cost(const string& S) {\n    if (S.empty()) return 0;\n    char c0 = S[0] - 'A';\n    auto& cells0 = pos[c0];\n    int sz0 = cells0.size();\n    for (int i = 0; i < sz0; ++i) {\n        dp_prev[i] = dist[start_idx][cells0[i]] + 1;\n    }\n    const int* cells_prev = cells0.data();\n    int sz_prev = sz0;\n    for (size_t k = 1; k < S.size(); ++k) {\n        char c = S[k] - 'A';\n        auto& cells_cur = pos[c];\n        int sz_cur = cells_cur.size();\n        fill_n(dp_cur, sz_cur, INF);\n        for (int j = 0; j < sz_prev; ++j) {\n            int prev_cell = cells_prev[j];\n            int base = dp_prev[j] + 1;\n            const int* drow = dist[prev_cell];\n            for (int i = 0; i < sz_cur; ++i) {\n                int cost = base + drow[cells_cur[i]];\n                if (cost < dp_cur[i]) dp_cur[i] = cost;\n            }\n        }\n        swap(dp_prev, dp_cur);\n        cells_prev = cells_cur.data();\n        sz_prev = sz_cur;\n    }\n    return *min_element(dp_prev, dp_prev + sz_prev);\n}\n\n// Compute minimal total cost and the optimal cell path for a given string S\npair<int, vector<int>> compute_DP_path(const string& S) {\n    int L = S.size();\n    vector<int> path(L);\n    if (L == 0) return {0, path};\n    vector<vector<int>> step_cells(L);\n    vector<vector<int>> step_prev(L);\n    char c0 = S[0] - 'A';\n    auto& cells0 = pos[c0];\n    int sz0 = cells0.size();\n    step_cells[0] = cells0;\n    step_prev[0].assign(sz0, -1);\n    for (int i = 0; i < sz0; ++i) dp_prev[i] = dist[start_idx][cells0[i]] + 1;\n    const int* cells_prev = cells0.data();\n    int sz_prev = sz0;\n    for (int k = 1; k < L; ++k) {\n        char c = S[k] - 'A';\n        auto& cells_cur = pos[c];\n        int sz_cur = cells_cur.size();\n        step_cells[k] = cells_cur;\n        step_prev[k].assign(sz_cur, -1);\n        fill_n(dp_cur, sz_cur, INF);\n        for (int j = 0; j < sz_prev; ++j) {\n            int prev_cell = cells_prev[j];\n            int base = dp_prev[j] + 1;\n            const int* drow = dist[prev_cell];\n            for (int i = 0; i < sz_cur; ++i) {\n                int cost = base + drow[cells_cur[i]];\n                if (cost < dp_cur[i]) {\n                    dp_cur[i] = cost;\n                    step_prev[k][i] = j;\n                }\n            }\n        }\n        swap(dp_prev, dp_cur);\n        cells_prev = cells_cur.data();\n        sz_prev = sz_cur;\n    }\n    int best_idx = min_element(dp_prev, dp_prev + sz_prev) - dp_prev;\n    int cost = dp_prev[best_idx];\n    for (int k = L - 1; k >= 0; --k) {\n        path[k] = step_cells[k][best_idx];\n        best_idx = step_prev[k][best_idx];\n    }\n    return {cost, path};\n}\n\n// Build superstring by always appending words with maximal overlap (no skipping)\nvoid build_S_always(string& S, const vector<int>& perm) {\n    S.clear();\n    S += t[perm[0]];\n    for (int i = 1; i < M; ++i) {\n        const string& w = t[perm[i]];\n        int max_ov = min((int)S.size(), 5);\n        int ov = 0;\n        for (int k = max_ov; k >= 1; --k) {\n            if (S.compare(S.size() - k, k, w, 0, k) == 0) {\n                ov = k; break;\n            }\n        }\n        S += w.substr(ov);\n    }\n}\n\n// Build superstring skipping words already contained, with maximal overlap otherwise\nstring build_S_skipped(const vector<int>& perm) {\n    string S;\n    for (int idx : perm) {\n        if (S.find(t[idx]) == string::npos) {\n            if (S.empty()) {\n                S = t[idx];\n            } else {\n                int max_ov = min((int)S.size(), 5);\n                int ov = 0;\n                for (int k = max_ov; k >= 1; --k) {\n                    if (S.compare(S.size() - k, k, t[idx], 0, k) == 0) {\n                        ov = k; break;\n                    }\n                }\n                S += t[idx].substr(ov);\n            }\n        }\n    }\n    return S;\n}\n\nint main() {\n    auto start_time = chrono::steady_clock::now();\n\n    // ---- input ----\n    cin >> N >> M;\n    cin >> start_i >> start_j;\n    for (int i = 0; i < N; ++i) {\n        string line;\n        cin >> line;\n        for (int j = 0; j < N; ++j) grid[i][j] = line[j];\n    }\n    t.resize(M);\n    for (int i = 0; i < M; ++i) cin >> t[i];\n\n    // ---- precomputation ----\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            int idx = i * N + j;\n            pos[grid[i][j] - 'A'].push_back(idx);\n        }\n    start_idx = start_i * N + start_j;\n    for (int i = 0; i < 225; ++i) {\n        int xi = i / N, yi = i % N;\n        for (int j = 0; j < 225; ++j) {\n            int xj = j / N, yj = j % N;\n            dist[i][j] = abs(xi - xj) + abs(yi - yj);\n        }\n    }\n\n    // ---- initial greedy: try all possible start words, always-append ----\n    int best_init_cost = INF;\n    vector<int> best_init_perm;\n    string best_init_S;\n    string S_temp;\n\n    for (int start = 0; start < M; ++start) {\n        vector<int> perm;\n        perm.push_back(start);\n        vector<bool> used(M, false);\n        used[start] = true;\n        S_temp = t[start];\n        int rem = M - 1;\n        while (rem > 0) {\n            int best_idx = -1, best_ov = -1;\n            for (int i = 0; i < M; ++i) {\n                if (used[i]) continue;\n                int max_ov = min((int)S_temp.size(), 5);\n                int ov = 0;\n                for (int k = max_ov; k >= 1; --k) {\n                    if (S_temp.compare(S_temp.size() - k, k, t[i], 0, k) == 0) {\n                        ov = k; break;\n                    }\n                }\n                if (ov > best_ov) {\n                    best_ov = ov;\n                    best_idx = i;\n                }\n            }\n            perm.push_back(best_idx);\n            used[best_idx] = true;\n            S_temp += t[best_idx].substr(best_ov);\n            rem--;\n        }\n        int cost = compute_DP_cost(S_temp);\n        if (cost < best_init_cost) {\n            best_init_cost = cost;\n            best_init_perm = perm;\n            best_init_S = S_temp;\n        }\n    }\n\n    // ---- Simulated Annealing ----\n    Xorshift rnd;\n    vector<int> current_perm = best_init_perm;\n    string S_always;\n    S_always.reserve(5000);\n    S_always = best_init_S;\n    int current_cost = best_init_cost;\n\n    vector<int> best_sa_perm = current_perm;\n    int best_sa_cost = current_cost;\n\n    double T0 = 500.0;\n    const double time_limit_ms = 1950.0;\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double, milli>(now - start_time).count();\n        if (elapsed > time_limit_ms) break;\n        double T = T0 * exp(-elapsed / 1900.0 * 5.0);\n        if (T < 0.01) T = 0.01;\n\n        for (int batch = 0; batch < 50; ++batch) {\n            vector<int> new_perm = current_perm;\n            int type = rnd.nextInt(3);\n            if (type == 0) {  // swap two elements\n                int i = rnd.nextInt(M), j = rnd.nextInt(M);\n                while (i == j) j = rnd.nextInt(M);\n                swap(new_perm[i], new_perm[j]);\n            } else if (type == 1) {  // reverse a segment\n                int l = rnd.nextInt(M), r = rnd.nextInt(M);\n                if (l > r) swap(l, r);\n                if (l < r) reverse(new_perm.begin() + l, new_perm.begin() + r + 1);\n            } else {  // move one element\n                int i = rnd.nextInt(M), j = rnd.nextInt(M);\n                if (i == j) continue;\n                int val = new_perm[i];\n                new_perm.erase(new_perm.begin() + i);\n                new_perm.insert(new_perm.begin() + j, val);\n            }\n            build_S_always(S_always, new_perm);\n            int new_cost = compute_DP_cost(S_always);\n            int delta = new_cost - current_cost;\n            if (delta <= 0 || exp(-delta / T) > rnd.nextDouble()) {\n                current_perm = new_perm;\n                current_cost = new_cost;\n                if (current_cost < best_sa_cost) {\n                    best_sa_cost = current_cost;\n                    best_sa_perm = current_perm;\n                }\n            }\n        }\n    }\n\n    // ---- final polish with skipping ----\n    string S1 = build_S_skipped(best_sa_perm);\n    string S2 = build_S_skipped(best_init_perm);\n    auto [cost1, path1] = compute_DP_path(S1);\n    auto [cost2, path2] = compute_DP_path(S2);\n\n    vector<int> final_path = (cost1 <= cost2) ? path1 : path2;\n\n    // ---- output ----\n    for (int cell : final_path) {\n        int i = cell / 15;\n        int j = cell % 15;\n        cout << i << \" \" << j << \"\\n\";\n    }\n\n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <bitset>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <numeric>\n#include <iomanip>\n#include <cassert>\n\nusing namespace std;\n\nconstexpr int MAX_N2 = 400;\nconstexpr double INF = 1e100;\nconstexpr double HUGE_PENALTY = 1e9;\n\ndouble normal_cdf(double x) {\n    return 0.5 * erfc(-x / sqrt(2.0));\n}\n\nint N, M;\ndouble eps;\nint V_total;\n\nstruct Placement {\n    int dx, dy;\n    bitset<MAX_N2> cells;\n    vector<int> overlaps;        // size Q, overlap with each query\n    vector<int> drill_contribs;  // size D, contribution to each drilled cell\n};\n\nstruct Field {\n    vector<pair<int,int>> shape;\n    vector<Placement> placements;\n    int max_i, max_j, size;\n};\n\nvector<Field> fields;\n\nvector<bitset<MAX_N2>> query_sets;\nvector<int> query_k;\nvector<int> query_y;\nvector<vector<double>> log_prob; // [Q][V_total+1]\nint Q;\n\nvector<int> observed_drills; // value for each drilled cell\nvector<int> drill_cells;    // cell index of each drill\nint D = 0;\n\nvector<vector<bool>> placement_valid;  // [M][P] hard invalidation (v=0 or v=M)\n\ninline int idx(int i, int j) { return i * N + j; }\ninline pair<int,int> unidx(int id) { return {id / N, id % N}; }\n\nvoid read_input() {\n    cin >> N >> M >> eps;\n    fields.resize(M);\n    V_total = 0;\n    for (int k = 0; k < M; ++k) {\n        int d; cin >> d;\n        fields[k].shape.resize(d);\n        fields[k].size = d;\n        V_total += d;\n        for (int a = 0; a < d; ++a) {\n            cin >> fields[k].shape[a].first >> fields[k].shape[a].second;\n        }\n    }\n}\n\nvoid precompute_placements() {\n    for (int k = 0; k < M; ++k) {\n        auto &sh = fields[k].shape;\n        int max_i = 0, max_j = 0;\n        for (auto &p : sh) {\n            max_i = max(max_i, p.first);\n            max_j = max(max_j, p.second);\n        }\n        fields[k].max_i = max_i;\n        fields[k].max_j = max_j;\n        for (int dx = 0; dx <= N - 1 - max_i; ++dx) {\n            for (int dy = 0; dy <= N - 1 - max_j; ++dy) {\n                Placement pl;\n                pl.dx = dx; pl.dy = dy;\n                bitset<MAX_N2> b;\n                for (auto &p : sh) {\n                    int r = dx + p.first;\n                    int c = dy + p.second;\n                    b.set(idx(r, c));\n                }\n                pl.cells = b;\n                fields[k].placements.push_back(pl);\n            }\n        }\n    }\n}\n\nvoid generate_initial_queries(int Q) {\n    query_sets.resize(Q);\n    query_k.resize(Q);\n    query_y.resize(Q);\n\n    random_device rd;\n    mt19937 gen(rd());\n    uniform_int_distribution<> k_dist(max(2, N*N/10), N*N); // favour large sets\n\n    for (int q = 0; q < Q; ++q) {\n        int k = k_dist(gen);\n        vector<int> indices(N*N);\n        iota(indices.begin(), indices.end(), 0);\n        shuffle(indices.begin(), indices.end(), gen);\n        bitset<MAX_N2> s;\n        for (int t = 0; t < k; ++t) s.set(indices[t]);\n        query_sets[q] = s;\n        query_k[q] = k;\n    }\n}\n\nvoid perform_initial_queries() {\n    for (int i = 0; i < Q; ++i) {\n        cout << \"q \" << query_k[i];\n        for (int r = 0; r < N*N; ++r) {\n            if (query_sets[i].test(r)) {\n                auto [rr, cc] = unidx(r);\n                cout << \" \" << rr << \" \" << cc;\n            }\n        }\n        cout << endl << flush;\n        cin >> query_y[i];\n    }\n}\n\nvoid precompute_log_prob() {\n    log_prob.resize(Q, vector<double>(V_total + 1));\n    for (int i = 0; i < Q; ++i) {\n        int k = query_k[i];\n        int y = query_y[i];\n        double sigma = sqrt(k * eps * (1.0 - eps));\n        for (int v = 0; v <= V_total; ++v) {\n            double mu = k * eps + v * (1.0 - 2.0 * eps);\n            double prob;\n            if (y == 0) {\n                prob = normal_cdf((0.5 - mu) / sigma);\n            } else {\n                prob = normal_cdf((y + 0.5 - mu) / sigma) - normal_cdf((y - 0.5 - mu) / sigma);\n            }\n            if (prob <= 0.0) prob = 1e-300;\n            log_prob[i][v] = log(prob);\n        }\n    }\n}\n\nvoid precompute_overlaps() {\n    for (int k = 0; k < M; ++k) {\n        for (auto &pl : fields[k].placements) {\n            pl.overlaps.resize(Q);\n            for (int i = 0; i < Q; ++i) {\n                pl.overlaps[i] = (pl.cells & query_sets[i]).count();\n            }\n            pl.drill_contribs.reserve(MAX_N2);\n        }\n    }\n}\n\nstruct State {\n    vector<int> assigns;          // length M\n    vector<int> query_overlaps;   // length Q\n    vector<int> drill_counts;     // length D\n    double energy;\n\n    State() {\n        assigns.assign(M, 0);\n        query_overlaps.assign(Q, 0);\n        drill_counts.assign(D, 0);\n        energy = -INF;\n    }\n\n    void init_random(mt19937 &gen) {\n        for (int k = 0; k < M; ++k) {\n            auto &valid = placement_valid[k];\n            vector<int> candidates;\n            for (int p = 0; p < (int)fields[k].placements.size(); ++p) {\n                if (valid[p]) candidates.push_back(p);\n            }\n            if (!candidates.empty()) {\n                uniform_int_distribution<> dis(0, candidates.size()-1);\n                assigns[k] = candidates[dis(gen)];\n            }\n            // if no valid placement, keep 0 (should not happen)\n        }\n        recalc_overlaps();\n        recalc_drills();\n        energy = compute_energy();\n    }\n\n    void recalc_overlaps() {\n        fill(query_overlaps.begin(), query_overlaps.end(), 0);\n        for (int k = 0; k < M; ++k) {\n            int p = assigns[k];\n            for (int i = 0; i < Q; ++i) {\n                query_overlaps[i] += fields[k].placements[p].overlaps[i];\n            }\n        }\n    }\n\n    void recalc_drills() {\n        fill(drill_counts.begin(), drill_counts.end(), 0);\n        for (int k = 0; k < M; ++k) {\n            int p = assigns[k];\n            auto &dc = fields[k].placements[p].drill_contribs;\n            for (int d = 0; d < D; ++d) {\n                drill_counts[d] += dc[d];\n            }\n        }\n    }\n\n    double compute_energy() const {\n        double en = 0.0;\n        for (int i = 0; i < Q; ++i) {\n            en += log_prob[i][query_overlaps[i]];\n        }\n        double penalty = 0.0;\n        for (int d = 0; d < D; ++d) {\n            if (drill_counts[d] != observed_drills[d]) penalty -= HUGE_PENALTY;\n        }\n        return en + penalty;\n    }\n\n    void update_energy() {\n        energy = compute_energy();\n    }\n};\n\nState run_sa(chrono::milliseconds time_limit, State initial_state) {\n    auto start = chrono::steady_clock::now();\n    mt19937 gen(random_device{}());\n\n    State state = initial_state;\n    State best_state = state;\n    double best_energy = state.energy;\n\n    double T = 10.0;\n    double T_end = 0.01;\n    double alpha = 0.999;\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        if (now - start > time_limit) break;\n\n        for (int sweep = 0; sweep < 5; ++sweep) {\n            vector<int> order(M);\n            iota(order.begin(), order.end(), 0);\n            shuffle(order.begin(), order.end(), gen);\n\n            for (int k : order) {\n                int old_p = state.assigns[k];\n                auto &pls = fields[k].placements;\n                auto &valid = placement_valid[k];\n\n                vector<int> base_overlap(Q);\n                for (int i = 0; i < Q; ++i) {\n                    base_overlap[i] = state.query_overlaps[i] - pls[old_p].overlaps[i];\n                }\n                vector<int> base_drill(D);\n                auto &old_dc = pls[old_p].drill_contribs;\n                for (int d = 0; d < D; ++d) {\n                    base_drill[d] = state.drill_counts[d] - old_dc[d];\n                }\n\n                vector<int> candidates;\n                vector<double> energies;\n                double max_energy = -INF;\n\n                for (int p = 0; p < (int)pls.size(); ++p) {\n                    if (!valid[p]) continue;\n                    auto &ov = pls[p].overlaps;\n                    auto &dc = pls[p].drill_contribs;\n\n                    double en = 0.0;\n                    for (int i = 0; i < Q; ++i) {\n                        en += log_prob[i][base_overlap[i] + ov[i]];\n                    }\n                    double penalty = 0.0;\n                    for (int d = 0; d < D; ++d) {\n                        if (base_drill[d] + dc[d] != observed_drills[d])\n                            penalty -= HUGE_PENALTY;\n                    }\n                    en += penalty;\n                    candidates.push_back(p);\n                    energies.push_back(en);\n                    if (en > max_energy) max_energy = en;\n                }\n\n                if (candidates.empty()) continue;\n\n                vector<double> probs(candidates.size());\n                double sum_p = 0.0;\n                for (size_t c = 0; c < candidates.size(); ++c) {\n                    probs[c] = exp((energies[c] - max_energy) / T);\n                    sum_p += probs[c];\n                }\n\n                uniform_real_distribution<> dis(0.0, sum_p);\n                double r = dis(gen);\n                double cum = 0.0;\n                size_t chosen = 0;\n                for (size_t c = 0; c < candidates.size(); ++c) {\n                    cum += probs[c];\n                    if (r <= cum) { chosen = c; break; }\n                }\n                int new_p = candidates[chosen];\n\n                // update state\n                state.assigns[k] = new_p;\n                auto &new_ov = pls[new_p].overlaps;\n                for (int i = 0; i < Q; ++i) {\n                    state.query_overlaps[i] = base_overlap[i] + new_ov[i];\n                }\n                auto &new_dc = pls[new_p].drill_contribs;\n                for (int d = 0; d < D; ++d) {\n                    state.drill_counts[d] = base_drill[d] + new_dc[d];\n                }\n                state.energy = energies[chosen];\n\n                if (state.energy > best_energy) {\n                    best_energy = state.energy;\n                    best_state = state;\n                }\n            }\n        }\n        T *= alpha;\n        if (T < T_end) break;\n    }\n    return best_state;\n}\n\nbitset<MAX_N2> get_mask(const State &state) {\n    bitset<MAX_N2> mask;\n    for (int k = 0; k < M; ++k) {\n        int p = state.assigns[k];\n        mask |= fields[k].placements[p].cells;\n    }\n    return mask;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cout << fixed << setprecision(10);\n\n    read_input();\n    precompute_placements();\n\n    int max_ops = 2 * N * N;\n    int ops_used = 0;\n\n    Q = min(150, max_ops - 10);\n    generate_initial_queries(Q);\n    perform_initial_queries();\n    ops_used += Q;\n\n    precompute_log_prob();\n    precompute_overlaps();\n\n    // placement_valid initialization\n    placement_valid.resize(M);\n    for (int k = 0; k < M; ++k) {\n        placement_valid[k].assign(fields[k].placements.size(), true);\n    }\n\n    D = 0;\n    mt19937 gen_init(random_device{}());\n\n    State best;\n    best.init_random(gen_init);\n    best = run_sa(chrono::milliseconds(200), best);\n\n    while (ops_used < max_ops - 1) {\n        // collect several SA states\n        vector<State> top_states;\n        top_states.push_back(best);\n        for (int i = 0; i < 2; ++i) {\n            State s;\n            s.init_random(gen_init);\n            s = run_sa(chrono::milliseconds(100), s);\n            top_states.push_back(s);\n        }\n\n        // check mask agreement\n        bitset<MAX_N2> union_mask, intersect_mask;\n        bool first = true;\n        for (auto &st : top_states) {\n            bitset<MAX_N2> m = get_mask(st);\n            if (first) {\n                union_mask = m;\n                intersect_mask = m;\n                first = false;\n            } else {\n                union_mask |= m;\n                intersect_mask &= m;\n            }\n        }\n\n        if (union_mask == intersect_mask) {\n            vector<pair<int,int>> cells;\n            for (int r = 0; r < N; ++r)\n                for (int c = 0; c < N; ++c)\n                    if (intersect_mask.test(idx(r,c)))\n                        cells.emplace_back(r, c);\n            cout << \"a \" << cells.size();\n            for (auto &p : cells) cout << \" \" << p.first << \" \" << p.second;\n            cout << endl << flush;\n            ++ops_used;\n            int result; cin >> result;\n            if (result == 1) return 0;\n            // if wrong, continue and drill more\n        }\n\n        // find most disputed cell\n        vector<int> pos_count(N*N, 0);\n        for (auto &st : top_states) {\n            bitset<MAX_N2> m = get_mask(st);\n            for (int r = 0; r < N*N; ++r) {\n                if (m.test(r)) pos_count[r]++;\n            }\n        }\n        int best_cell = -1;\n        double best_disagreement = -1.0;\n        for (int r = 0; r < N*N; ++r) {\n            bool drilled = false;\n            for (int d = 0; d < D; ++d) {\n                if (drill_cells[d] == r) { drilled = true; break; }\n            }\n            if (drilled) continue;\n            double frac = (double)pos_count[r] / top_states.size();\n            double dis = min(frac, 1.0 - frac);\n            if (dis > best_disagreement) {\n                best_disagreement = dis;\n                best_cell = r;\n            }\n        }\n        if (best_cell == -1) {\n            // all cells either drilled or agreed? guess best\n            bitset<MAX_N2> m = get_mask(best);\n            vector<pair<int,int>> cells;\n            for (int r = 0; r < N; ++r)\n                for (int c = 0; c < N; ++c)\n                    if (m.test(idx(r,c)))\n                        cells.emplace_back(r, c);\n            cout << \"a \" << cells.size();\n            for (auto &p : cells) cout << \" \" << p.first << \" \" << p.second;\n            cout << endl << flush;\n            ++ops_used;\n            int result; cin >> result;\n            if (result == 1) return 0;\n            // fallback: drill a random undrilled cell\n            for (int r = 0; r < N*N; ++r) {\n                bool drilled = false;\n                for (int d = 0; d < D; ++d) if (drill_cells[d] == r) drilled = true;\n                if (!drilled) { best_cell = r; break; }\n            }\n            if (best_cell == -1) break;\n        }\n\n        // drill best_cell\n        auto [ri, rj] = unidx(best_cell);\n        cout << \"q 1 \" << ri << \" \" << rj << endl << flush;\n        ++ops_used;\n        int v_cell; cin >> v_cell;\n\n        drill_cells.push_back(best_cell);\n        observed_drills.push_back(v_cell);\n        int new_d = D;\n        ++D;\n\n        // extend drill_contribs\n        for (int k = 0; k < M; ++k) {\n            for (int p = 0; p < (int)fields[k].placements.size(); ++p) {\n                bool covers = fields[k].placements[p].cells.test(best_cell);\n                fields[k].placements[p].drill_contribs.push_back(covers ? 1 : 0);\n            }\n        }\n\n        // hard invalidation\n        if (v_cell == 0) {\n            for (int k = 0; k < M; ++k) {\n                for (int p = 0; p < (int)fields[k].placements.size(); ++p) {\n                    if (fields[k].placements[p].cells.test(best_cell)) {\n                        placement_valid[k][p] = false;\n                    }\n                }\n            }\n        } else if (v_cell == M) {\n            for (int k = 0; k < M; ++k) {\n                for (int p = 0; p < (int)fields[k].placements.size(); ++p) {\n                    if (!fields[k].placements[p].cells.test(best_cell)) {\n                        placement_valid[k][p] = false;\n                    }\n                }\n            }\n        }\n\n        // update drill counts for state objects? We just reinitialize best for next SA.\n        // Check if current best satisfies new drill\n        bool best_ok = true;\n        {\n            int cnt = 0;\n            for (int k = 0; k < M; ++k) {\n                int p = best.assigns[k];\n                if (fields[k].placements[p].cells.test(best_cell)) cnt++;\n            }\n            if (cnt != v_cell) best_ok = false;\n        }\n        if (!best_ok) {\n            best.init_random(gen_init);\n        } else {\n            // update its internal drill_counts and energy to include new drill\n            best.drill_counts.push_back(0);\n            for (int k = 0; k < M; ++k) {\n                int p = best.assigns[k];\n                if (fields[k].placements[p].cells.test(best_cell))\n                    best.drill_counts[new_d]++;\n            }\n            best.update_energy();\n        }\n\n        // run SA again\n        int sa_time = min(200, (max_ops - ops_used) * 5); // dynamic\n        if (sa_time < 20) sa_time = 20;\n        best = run_sa(chrono::milliseconds(sa_time), best);\n    }\n\n    // final guess\n    bitset<MAX_N2> mask = get_mask(best);\n    vector<pair<int,int>> cells;\n    for (int r = 0; r < N; ++r)\n        for (int c = 0; c < N; ++c)\n            if (mask.test(idx(r,c)))\n                cells.emplace_back(r, c);\n    cout << \"a \" << cells.size();\n    for (auto &p : cells) cout << \" \" << p.first << \" \" << p.second;\n    cout << endl << flush;\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int i0, j0, i1, j1;\n    int area() const { return (i1 - i0) * (j1 - j0); }\n};\n\nint W, D, N;\nvector<vector<int>> a;\nvector<vector<Rect>> rects;\nint HORIZ_COUNT, VERT_COUNT, SEG;\nvector<uint8_t> wall_counts;\nint total_area_penalty = 0;\nint total_L_sum = 0;\n\n// xorshift random\nunsigned int rng_state = 123456789;\nunsigned int xorshift() {\n    rng_state ^= rng_state << 13;\n    rng_state ^= rng_state >> 17;\n    rng_state ^= rng_state << 5;\n    return rng_state;\n}\ndouble rand_double() {\n    return (xorshift() & 0xFFFFFFFF) / 4294967296.0;\n}\nint rand_int(int n) {\n    return xorshift() % n;\n}\n\nbool overlap(const Rect& a, const Rect& b) {\n    return a.i0 < b.i1 && b.i0 < a.i1 && a.j0 < b.j1 && b.j0 < a.j1;\n}\n\nvoid get_boundaries(const Rect& r, vector<int>& segs) {\n    segs.clear();\n    if (r.i0 >= 1 && r.i0 <= W - 1) {\n        int base = (r.i0 - 1) * W + r.j0;\n        for (int j = 0; j < r.j1 - r.j0; ++j) segs.push_back(base + j);\n    }\n    if (r.i1 >= 1 && r.i1 <= W - 1) {\n        int base = (r.i1 - 1) * W + r.j0;\n        for (int j = 0; j < r.j1 - r.j0; ++j) segs.push_back(base + j);\n    }\n    if (r.j0 >= 1 && r.j0 <= W - 1) {\n        int base = HORIZ_COUNT + (r.j0 - 1);\n        for (int i = r.i0; i < r.i1; ++i) segs.push_back(base + i * (W - 1));\n    }\n    if (r.j1 >= 1 && r.j1 <= W - 1) {\n        int base = HORIZ_COUNT + (r.j1 - 1);\n        for (int i = r.i0; i < r.i1; ++i) segs.push_back(base + i * (W - 1));\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> W >> D >> N;\n    a.resize(D, vector<int>(N));\n    for (int d = 0; d < D; ++d)\n        for (int k = 0; k < N; ++k)\n            cin >> a[d][k];\n\n    HORIZ_COUNT = (W - 1) * W;\n    VERT_COUNT = W * (W - 1);\n    SEG = HORIZ_COUNT + VERT_COUNT;\n\n    rects.resize(D, vector<Rect>(N));\n\n    // ----- initial packing per day (maxrects best\u2011fit) -----\n    for (int d = 0; d < D; ++d) {\n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int x, int y) {\n            return a[d][x] > a[d][y];\n        });\n\n        struct FreeRect { int i0, j0, i1, j1; };\n        vector<FreeRect> free;\n        free.push_back({0, 0, W, W});\n        vector<Rect> placed(N);\n        bool ok = true;\n\n        for (int idx : order) {\n            int req = a[d][idx];\n\n            // best\u2011fit free rectangle\n            int best = -1;\n            int best_area = INT_MAX;\n            for (int i = 0; i < (int)free.size(); ++i) {\n                int fa = (free[i].i1 - free[i].i0) * (free[i].j1 - free[i].j0);\n                if (fa >= req && fa < best_area) {\n                    best_area = fa;\n                    best = i;\n                }\n            }\n            if (best == -1) {\n                // fallback : take first that fits (should not happen)\n                for (int i = 0; i < (int)free.size(); ++i) {\n                    int fa = (free[i].i1 - free[i].i0) * (free[i].j1 - free[i].j0);\n                    if (fa >= req) { best = i; break; }\n                }\n            }\n            if (best == -1) { ok = false; break; }\n\n            FreeRect fr = free[best];\n            free.erase(free.begin() + best);\n\n            int avail_w = fr.j1 - fr.j0;\n            int avail_h = fr.i1 - fr.i0;\n            int w = min(avail_w, max(1, (int)ceil(sqrt(req))));\n            int h = (req + w - 1) / w;\n            if (h > avail_h) {\n                h = avail_h;\n                w = (req + h - 1) / h;\n                if (w > avail_w) w = avail_w;\n            }\n            Rect r;\n            r.i0 = fr.i0; r.j0 = fr.j0;\n            r.i1 = r.i0 + h; r.j1 = r.j0 + w;\n\n            if (r.j1 < fr.j1) free.push_back({fr.i0, r.j1, r.i1, fr.j1});\n            if (r.i1 < fr.i1) free.push_back({r.i1, fr.j0, fr.i1, fr.j1});\n\n            placed[idx] = r;\n        }\n\n        if (!ok) {\n            // fallback : simple row strip packing (height = 1)\n            free.clear();\n            free.push_back({0, 0, W, W});\n            for (int idx : order) {\n                int req = a[d][idx];\n                int best = -1;\n                for (int i = 0; i < (int)free.size(); ++i) {\n                    if ((free[i].i1 - free[i].i0) * (free[i].j1 - free[i].j0) >= req) {\n                        best = i; break;\n                    }\n                }\n                FreeRect fr = free[best];\n                free.erase(free.begin() + best);\n                int w = min(fr.j1 - fr.j0, req);\n                int h = (req + w - 1) / w;\n                if (h > fr.i1 - fr.i0) h = fr.i1 - fr.i0;\n                Rect r;\n                r.i0 = fr.i0; r.j0 = fr.j0;\n                r.i1 = fr.i0 + h; r.j1 = fr.j0 + w;\n                if (r.j1 < fr.j1) free.push_back({fr.i0, r.j1, r.i1, fr.j1});\n                if (r.i1 < fr.i1) free.push_back({r.i1, fr.j0, fr.i1, fr.j1});\n                placed[idx] = r;\n            }\n        }\n        rects[d] = placed;\n    }\n\n    // ----- build wall_counts and initial cost -----\n    wall_counts.assign(D * SEG, 0);\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            vector<int> segs;\n            get_boundaries(rects[d][k], segs);\n            for (int s : segs) wall_counts[d * SEG + s]++;\n        }\n    }\n\n    total_area_penalty = 0;\n    for (int d = 0; d < D; ++d)\n        for (int k = 0; k < N; ++k) {\n            int area = rects[d][k].area();\n            if (area < a[d][k]) total_area_penalty += 100 * (a[d][k] - area);\n        }\n\n    total_L_sum = 0;\n    for (int d = 1; d < D; ++d) {\n        int off_prev = (d - 1) * SEG;\n        int off_cur = d * SEG;\n        for (int s = 0; s < SEG; ++s) {\n            total_L_sum += ((wall_counts[off_prev + s] > 0) != (wall_counts[off_cur + s] > 0));\n        }\n    }\n\n    int best_cost = total_area_penalty + total_L_sum;\n    vector<vector<Rect>> best_rects = rects;\n\n    // ----- SA -----\n    double T0 = 10000.0;\n    double time_limit = 2.9;\n    auto start_time = chrono::steady_clock::now();\n\n    vector<int> old_segs, new_segs;\n    old_segs.reserve(4000);\n    new_segs.reserve(4000);\n    vector<int> only_old, only_new;\n    only_old.reserve(4000);\n    only_new.reserve(4000);\n\n    while (true) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n        if (elapsed > time_limit) break;\n        double T = T0 * (1.0 - elapsed / time_limit);\n        if (T < 0.1) T = 0.1;\n\n        for (int sub = 0; sub < 200; ++sub) {\n            int d = rand_int(D);\n            int k = rand_int(N);\n            int move_type = rand_int(3);\n            Rect old_rect = rects[d][k];\n            Rect new_rect;\n\n            if (move_type == 0) {   // shift\n                int dx = rand_int(7) - 3;\n                int dy = rand_int(7) - 3;\n                if (dx == 0 && dy == 0) continue;\n                new_rect = {old_rect.i0 + dx, old_rect.j0 + dy, old_rect.i1 + dx, old_rect.j1 + dy};\n            } else if (move_type == 1) {  // resize\n                int side = rand_int(4);\n                int delta = rand_int(11) - 5;\n                if (delta == 0) continue;\n                new_rect = old_rect;\n                if (side == 0) new_rect.i0 += delta;\n                else if (side == 1) new_rect.i1 += delta;\n                else if (side == 2) new_rect.j0 += delta;\n                else new_rect.j1 += delta;\n            } else {  // copy from adjacent day\n                int adj = d + (rand_int(2) == 0 ? -1 : 1);\n                if (adj < 0 || adj >= D) continue;\n                new_rect = rects[adj][k];\n            }\n\n            // fast validity checks\n            if (new_rect.i0 < 0 || new_rect.j0 < 0 || new_rect.i1 > W || new_rect.j1 > W) continue;\n            if (new_rect.i0 >= new_rect.i1 || new_rect.j0 >= new_rect.j1) continue;\n            bool bad = false;\n            for (int k2 = 0; k2 < N; ++k2) {\n                if (k2 == k) continue;\n                if (overlap(new_rect, rects[d][k2])) { bad = true; break; }\n            }\n            if (bad) continue;\n\n            // area penalty change\n            int old_area = old_rect.area();\n            int new_area = new_rect.area();\n            int old_short = max(0, a[d][k] - old_area);\n            int new_short = max(0, a[d][k] - new_area);\n            int delta_area = 100 * (new_short - old_short);\n\n            // boundary segments (old / new)\n            get_boundaries(old_rect, old_segs);\n            get_boundaries(new_rect, new_segs);\n            sort(old_segs.begin(), old_segs.end());\n            sort(new_segs.begin(), new_segs.end());\n\n            only_old.clear(); only_new.clear();\n            size_t i = 0, j = 0;\n            while (i < old_segs.size() || j < new_segs.size()) {\n                if (i < old_segs.size() && (j == new_segs.size() || old_segs[i] < new_segs[j])) {\n                    only_old.push_back(old_segs[i]); ++i;\n                } else if (j < new_segs.size() && (i == old_segs.size() || new_segs[j] < old_segs[i])) {\n                    only_new.push_back(new_segs[j]); ++j;\n                } else {\n                    ++i; ++j;\n                }\n            }\n\n            int delta_L = 0;\n            int off_d = d * SEG;\n\n            for (int seg : only_old) {\n                int wc = wall_counts[off_d + seg];\n                bool old_st = (wc > 0);\n                bool new_st = ((wc - 1) > 0);\n                if (old_st != new_st) {\n                    if (d > 0) {\n                        bool prev_st = (wall_counts[(d - 1) * SEG + seg] > 0);\n                        delta_L += (new_st != prev_st) - (old_st != prev_st);\n                    }\n                    if (d + 1 < D) {\n                        bool next_st = (wall_counts[(d + 1) * SEG + seg] > 0);\n                        delta_L += (new_st != next_st) - (old_st != next_st);\n                    }\n                }\n            }\n            for (int seg : only_new) {\n                int wc = wall_counts[off_d + seg];\n                bool old_st = (wc > 0);\n                bool new_st = ((wc + 1) > 0);\n                if (old_st != new_st) {\n                    if (d > 0) {\n                        bool prev_st = (wall_counts[(d - 1) * SEG + seg] > 0);\n                        delta_L += (new_st != prev_st) - (old_st != prev_st);\n                    }\n                    if (d + 1 < D) {\n                        bool next_st = (wall_counts[(d + 1) * SEG + seg] > 0);\n                        delta_L += (new_st != next_st) - (old_st != next_st);\n                    }\n                }\n            }\n\n            int delta_cost = delta_area + delta_L;\n            if (delta_cost <= 0 || rand_double() < exp(-delta_cost / T)) {\n                // accept\n                rects[d][k] = new_rect;\n                total_area_penalty += delta_area;\n                total_L_sum += delta_L;\n                for (int seg : only_old) wall_counts[off_d + seg]--;\n                for (int seg : only_new) wall_counts[off_d + seg]++;\n            }\n        }\n\n        int cur_cost = total_area_penalty + total_L_sum;\n        if (cur_cost < best_cost) {\n            best_cost = cur_cost;\n            best_rects = rects;\n        }\n    }\n\n    // ----- output best solution -----\n    for (int d = 0; d < D; ++d)\n        for (int k = 0; k < N; ++k) {\n            Rect r = best_rects[d][k];\n            cout << r.i0 << \" \" << r.j0 << \" \" << r.i1 << \" \" << r.j1 << \"\\n\";\n        }\n\n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <array>\n#include <cmath>\n#include <chrono>\n#include <random>\n#include <climits>\n#include <algorithm>\n\nusing namespace std;\nusing ll = long long;\nusing ull = unsigned long long;\n\nconst int MOD = 998244353;\n\nstruct Move {\n    int m, p, q;\n    array<pair<int, int>, 9> cells;\n};\n\nstruct Xorshift {\n    ull state;\n    Xorshift(ull seed) : state(seed) {}\n    ull next() {\n        state ^= state << 13;\n        state ^= state >> 7;\n        state ^= state << 17;\n        return state;\n    }\n    int next_int(int mod) {\n        return next() % mod;\n    }\n    double next_double() {\n        return (next() >> 11) * (1.0 / (1ULL << 53));\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K;\n    cin >> N >> M >> K;\n\n    vector<vector<int>> a(N, vector<int>(N));\n    for(int i=0;i<N;i++) for(int j=0;j<N;j++) cin >> a[i][j];\n\n    vector<vector<vector<int>>> stamps(M, vector<vector<int>>(3, vector<int>(3)));\n    for(int m=0; m<M; m++) {\n        for(int i=0;i<3;i++) for(int j=0;j<3;j++) cin >> stamps[m][i][j];\n    }\n\n    array<int, 81> board_rem;\n    ll score = 0;\n    for(int i=0;i<N;i++) {\n        for(int j=0;j<N;j++) {\n            int idx = i*N + j;\n            board_rem[idx] = a[i][j];\n            score += board_rem[idx];\n        }\n    }\n\n    vector<Move> moves;\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                Move mv;\n                mv.m = m; mv.p = p; mv.q = q;\n                for(int i=0;i<3;i++) {\n                    for(int j=0;j<3;j++) {\n                        int cell = (p+i)*N + (q+j);\n                        int val = stamps[m][i][j];\n                        mv.cells[i*3+j] = {cell, val};\n                    }\n                }\n                moves.push_back(mv);\n            }\n        }\n    }\n    int total_moves = moves.size();\n\n    auto eval_add = [&](int move_id) -> ll {\n        ll d = 0;\n        for(auto [cell, val] : moves[move_id].cells) {\n            int old_rem = board_rem[cell];\n            int new_rem = old_rem + val;\n            if(new_rem >= MOD) new_rem -= MOD;\n            d += new_rem - old_rem;\n        }\n        return d;\n    };\n    auto eval_remove = [&](int move_id) -> ll {\n        ll d = 0;\n        for(auto [cell, val] : moves[move_id].cells) {\n            int old_rem = board_rem[cell];\n            int new_rem = old_rem - val;\n            if(new_rem < 0) new_rem += MOD;\n            d += new_rem - old_rem;\n        }\n        return d;\n    };\n    auto apply_add = [&](int move_id) {\n        for(auto [cell, val] : moves[move_id].cells) {\n            int old_rem = board_rem[cell];\n            int new_rem = old_rem + val;\n            if(new_rem >= MOD) new_rem -= MOD;\n            score += new_rem - old_rem;\n            board_rem[cell] = new_rem;\n        }\n    };\n    auto apply_remove = [&](int move_id) {\n        for(auto [cell, val] : moves[move_id].cells) {\n            int old_rem = board_rem[cell];\n            int new_rem = old_rem - val;\n            if(new_rem < 0) new_rem += MOD;\n            score += new_rem - old_rem;\n            board_rem[cell] = new_rem;\n        }\n    };\n\n    random_device rd;\n    ull seed = ((ull)rd() << 32) | rd();\n    Xorshift rng(seed);\n\n    // Greedy initial solution\n    vector<int> actions;\n    for(int step=0; step<K; step++) {\n        ll best_delta = LLONG_MIN;\n        int best_move = -1;\n        for(int m=0; m<total_moves; m++) {\n            ll d = eval_add(m);\n            if(d > best_delta) {\n                best_delta = d;\n                best_move = m;\n            }\n        }\n        if(best_delta <= 0) break;\n        apply_add(best_move);\n        actions.push_back(best_move);\n    }\n\n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.95;\n    int max_iter = 10000000;\n    double T_start = 1e9;\n    double T_end = 1e5;\n    double T = T_start;\n    double alpha = pow(T_end / T_start, 1.0 / max_iter);\n\n    ll best_score = score;\n    vector<int> best_actions = actions;\n\n    for(int iter=0; iter<max_iter; iter++) {\n        if(iter % 10000 == 0) {\n            auto now = chrono::steady_clock::now();\n            if(chrono::duration<double>(now - start_time).count() > time_limit) break;\n        }\n        int L = actions.size();\n        double r = rng.next_double();\n        if(L == 0) {\n            int new_move = rng.next_int(total_moves);\n            ll delta = eval_add(new_move);\n            if(delta >= 0 || rng.next_double() < exp(delta / T)) {\n                apply_add(new_move);\n                actions.push_back(new_move);\n                if(score > best_score) {\n                    best_score = score;\n                    best_actions = actions;\n                }\n            }\n        } else if(L == K) {\n            if(r < 0.5) {\n                int idx = rng.next_int(L);\n                int old_move = actions[idx];\n                ll delta = eval_remove(old_move);\n                if(delta >= 0 || rng.next_double() < exp(delta / T)) {\n                    apply_remove(old_move);\n                    actions[idx] = actions.back();\n                    actions.pop_back();\n                    if(score > best_score) {\n                        best_score = score;\n                        best_actions = actions;\n                    }\n                }\n            } else {\n                int idx = rng.next_int(L);\n                int old_move = actions[idx];\n                ll score_before = score;\n                apply_remove(old_move);\n                int new_move = rng.next_int(total_moves);\n                ll delta_add = eval_add(new_move);\n                ll total_delta = (score - score_before) + delta_add;\n                if(total_delta >= 0 || rng.next_double() < exp(total_delta / T)) {\n                    apply_add(new_move);\n                    actions[idx] = new_move;\n                    if(score > best_score) {\n                        best_score = score;\n                        best_actions = actions;\n                    }\n                } else {\n                    apply_add(old_move);\n                }\n            }\n        } else {\n            if(r < 0.4) {\n                int new_move = rng.next_int(total_moves);\n                ll delta = eval_add(new_move);\n                if(delta >= 0 || rng.next_double() < exp(delta / T)) {\n                    apply_add(new_move);\n                    actions.push_back(new_move);\n                    if(score > best_score) {\n                        best_score = score;\n                        best_actions = actions;\n                    }\n                }\n            } else if(r < 0.7) {\n                int idx = rng.next_int(L);\n                int old_move = actions[idx];\n                ll score_before = score;\n                apply_remove(old_move);\n                int new_move = rng.next_int(total_moves);\n                ll delta_add = eval_add(new_move);\n                ll total_delta = (score - score_before) + delta_add;\n                if(total_delta >= 0 || rng.next_double() < exp(total_delta / T)) {\n                    apply_add(new_move);\n                    actions[idx] = new_move;\n                    if(score > best_score) {\n                        best_score = score;\n                        best_actions = actions;\n                    }\n                } else {\n                    apply_add(old_move);\n                }\n            } else {\n                int idx = rng.next_int(L);\n                int old_move = actions[idx];\n                ll delta = eval_remove(old_move);\n                if(delta >= 0 || rng.next_double() < exp(delta / T)) {\n                    apply_remove(old_move);\n                    actions[idx] = actions.back();\n                    actions.pop_back();\n                    if(score > best_score) {\n                        best_score = score;\n                        best_actions = actions;\n                    }\n                }\n            }\n        }\n        T *= alpha;\n    }\n\n    cout << best_actions.size() << \"\\n\";\n    for(int m_id : best_actions) {\n        cout << moves[m_id].m << \" \" << moves[m_id].p << \" \" << moves[m_id].q << \"\\n\";\n    }\n\n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <tuple>\n#include <queue>\nusing namespace std;\n\nint main() {\n    const int N = 5;\n    vector<vector<int>> A(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> A[i][j];\n\n    vector<int> id_to_row(N * N);\n    vector<int> arrival_order[N];\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            id_to_row[A[i][j]] = i;\n            arrival_order[i].push_back(A[i][j]);\n        }\n    }\n\n    int arrival_idx[N] = {0};\n    int ground[N][N];\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            ground[i][j] = -1;\n\n    int container_pos[25];\n    for (int i = 0; i < 25; ++i) container_pos[i] = -1;  // -1: not on ground, -2: dispatched\n\n    int L_r = 0, L_c = 0;\n    int L_holding = -1;\n    int cur_target = 0;\n    string L_actions;\n    int turn = 0;\n\n    auto move_towards = [&](int tr, int tc) -> char {\n        if (L_r < tr) return 'D';\n        if (L_r > tr) return 'U';\n        if (L_c < tc) return 'R';\n        if (L_c > tc) return 'L';\n        return '.';\n    };\n\n    auto find_buffer_cell = [&](int cont) -> pair<int,int> {\n        int tr = cont / 5;\n        // 1) current cell if it is empty and not a dispatch gate\n        if (ground[L_r][L_c] == -1) {\n            if (L_c != 4 && !(L_c == 0 && arrival_idx[L_r] < N)) {\n                return {L_r, L_c};\n            }\n        }\n        // 2) target row, preferred columns 3,2,1\n        for (int c : {3, 2, 1}) {\n            if (ground[tr][c] == -1) return {tr, c};\n        }\n        if (arrival_idx[tr] >= N && ground[tr][0] == -1) return {tr, 0};\n        // 3) other rows\n        for (int r = 0; r < N; ++r) {\n            if (r == tr) continue;\n            for (int c : {3, 2, 1}) {\n                if (ground[r][c] == -1) return {r, c};\n            }\n            if (arrival_idx[r] >= N && ground[r][0] == -1) return {r, 0};\n        }\n        // 4) any other cell except dispatch gates (col 4) and receiving gates that still have pending containers\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c <= 3; ++c) {\n                if (ground[r][c] == -1) {\n                    if (c == 0 && arrival_idx[r] < N) continue;\n                    return {r, c};\n                }\n            }\n        }\n        // absolute fallback (should never be reached)\n        return {L_r, L_c};\n    };\n\n    while (cur_target < 25 && turn < 10000) {\n        // ---------- Step 1 : Receiving ----------\n        for (int i = 0; i < N; ++i) {\n            if (ground[i][0] == -1 && arrival_idx[i] < N) {\n                // arrival is blocked only if a crane holding a container is present\n                bool blocked = (L_holding != -1 && L_r == i && L_c == 0);\n                if (!blocked) {\n                    int cont = arrival_order[i][arrival_idx[i]++];\n                    ground[i][0] = cont;\n                    container_pos[cont] = i * 5 + 0;\n                }\n            }\n        }\n\n        // ---------- Step 2 : Large crane action ----------\n        char act = '.';\n        if (L_holding != -1) {\n            int cont = L_holding;\n            if (cont == cur_target) {\n                int tr = cont / 5;\n                int tc = 4;\n                if (L_r == tr && L_c == tc) {\n                    act = 'Q';\n                } else {\n                    act = move_towards(tr, tc);\n                }\n            } else {\n                auto [tr, tc] = find_buffer_cell(cont);\n                if (L_r == tr && L_c == tc) {\n                    act = 'Q';\n                } else {\n                    act = move_towards(tr, tc);\n                }\n            }\n        } else {\n            int c = cur_target;\n            int r = id_to_row[c];\n            if (container_pos[c] >= 0) {\n                int pos = container_pos[c];\n                int tr = pos / 5, tc = pos % 5;\n                if (L_r == tr && L_c == tc) {\n                    act = 'P';\n                } else {\n                    act = move_towards(tr, tc);\n                }\n            } else {\n                // not on ground\n                if (ground[r][0] == c) {\n                    if (L_r == r && L_c == 0) {\n                        act = 'P';\n                    } else {\n                        act = move_towards(r, 0);\n                    }\n                } else if (ground[r][0] != -1) {\n                    // gate blocked by another container\n                    if (L_r == r && L_c == 0) {\n                        act = 'P';\n                    } else {\n                        act = move_towards(r, 0);\n                    }\n                } else {\n                    // wait near the gate\n                    int tr = r, tc = 1;\n                    if (L_r == tr && L_c == tc) {\n                        act = '.';\n                    } else {\n                        act = move_towards(tr, tc);\n                    }\n                }\n            }\n        }\n\n        // Apply L action\n        if (act == 'U') L_r--;\n        else if (act == 'D') L_r++;\n        else if (act == 'L') L_c--;\n        else if (act == 'R') L_c++;\n        else if (act == 'P') {\n            int cont = ground[L_r][L_c];\n            ground[L_r][L_c] = -1;\n            L_holding = cont;\n            container_pos[cont] = -1;\n        } else if (act == 'Q') {\n            ground[L_r][L_c] = L_holding;\n            container_pos[L_holding] = L_r * 5 + L_c;\n            L_holding = -1;\n        }\n        L_actions.push_back(act);\n\n        // ---------- Step 3 : Dispatching ----------\n        for (int i = 0; i < N; ++i) {\n            if (ground[i][4] != -1) {\n                int cont = ground[i][4];\n                ground[i][4] = -1;\n                container_pos[cont] = -2;\n                if (cont == cur_target) {\n                    ++cur_target;\n                }\n            }\n        }\n\n        ++turn;\n    }\n\n    // Output\n    cout << L_actions << \"\\n\";\n    for (int i = 1; i < N; ++i) {\n        cout << \"B\\n\";\n    }\n\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Task {\n    int r, c, h;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N; // N = 20\n    vector<vector<int>> H(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> H[i][j];\n        }\n    }\n\n    // Collect non-zero cells as tasks\n    vector<Task> tasks;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (H[i][j] != 0) {\n                tasks.push_back({i, j, H[i][j]});\n            }\n        }\n    }\n    int S = tasks.size();\n    if (S == 0) {\n        // All zero, no operations\n        return 0;\n    }\n\n    // Manhattan distance\n    auto manhattan = [&](int r1, int c1, int r2, int c2) {\n        return abs(r1 - r2) + abs(c1 - c2);\n    };\n\n    // Precompute distances\n    vector<int> start_dist(S);\n    for (int i = 0; i < S; ++i) {\n        start_dist[i] = manhattan(0, 0, tasks[i].r, tasks[i].c);\n    }\n    vector<vector<int>> dist(S, vector<int>(S));\n    for (int i = 0; i < S; ++i) {\n        for (int j = 0; j < S; ++j) {\n            dist[i][j] = manhattan(tasks[i].r, tasks[i].c, tasks[j].r, tasks[j].c);\n        }\n    }\n\n    // Evaluate a permutation (movement cost only, infeasible if load < 0 at any point)\n    auto evaluate = [&](const vector<int>& perm) -> pair<long long, bool> {\n        long long cost = 0;\n        int load = 0;\n        int pos = -1; // -1 means (0,0)\n        for (int idx : perm) {\n            int d = (pos == -1) ? start_dist[idx] : dist[pos][idx];\n            cost += d * (100LL + load);\n            load += tasks[idx].h;\n            if (load < 0) return {0, false};\n            pos = idx;\n        }\n        // load should be 0 at the end because sum of h = 0, but we don't strictly check\n        return {cost, true};\n    };\n\n    // Build initial solution: all positives first, then negatives\n    vector<int> pos_idx, neg_idx;\n    for (int i = 0; i < S; ++i) {\n        if (tasks[i].h > 0) pos_idx.push_back(i);\n        else neg_idx.push_back(i);\n    }\n\n    // Greedy construction for positives (nearest neighbor from (0,0))\n    auto build_greedy_positives = [&]() {\n        vector<int> order;\n        vector<bool> used(S, false);\n        int cur_r = 0, cur_c = 0;\n        while ((int)order.size() < (int)pos_idx.size()) {\n            int best = -1;\n            int best_d = 1e9;\n            for (int i : pos_idx) {\n                if (used[i]) continue;\n                int d = manhattan(cur_r, cur_c, tasks[i].r, tasks[i].c);\n                if (d < best_d) {\n                    best_d = d;\n                    best = i;\n                }\n            }\n            order.push_back(best);\n            used[best] = true;\n            cur_r = tasks[best].r;\n            cur_c = tasks[best].c;\n        }\n        return order;\n    };\n\n    // Greedy construction for negatives (nearest neighbor from last positive)\n    auto build_greedy_negatives = [&](int start_r, int start_c) {\n        vector<int> order;\n        vector<bool> used(S, false);\n        // mark positives as used (they are already in the positive order, but we just need to pick negatives)\n        // simpler: just pass used negatives\n        int cur_r = start_r, cur_c = start_c;\n        while ((int)order.size() < (int)neg_idx.size()) {\n            int best = -1;\n            int best_d = 1e9;\n            for (int i : neg_idx) {\n                // we don't have a global used here; we just pick from neg_idx each time\n                // Use a local bool array or just ensure we don't pick already chosen\n                // We'll use a vector<bool> local_used(neg_idx.size(), false) manually.\n                // But easier: just iterate over neg_idx and skip already in order.\n                if (find(order.begin(), order.end(), i) != order.end()) continue;\n                int d = manhattan(cur_r, cur_c, tasks[i].r, tasks[i].c);\n                if (d < best_d) {\n                    best_d = d;\n                    best = i;\n                }\n            }\n            order.push_back(best);\n            cur_r = tasks[best].r;\n            cur_c = tasks[best].c;\n        }\n        return order;\n    };\n\n    int last_pos_r = 0, last_pos_c = 0;\n    vector<int> best_perm;\n    if (!pos_idx.empty()) {\n        vector<int> pos_order = build_greedy_positives();\n        last_pos_r = tasks[pos_order.back()].r;\n        last_pos_c = tasks[pos_order.back()].c;\n        vector<int> neg_order = build_greedy_negatives(last_pos_r, last_pos_c);\n        best_perm = pos_order;\n        best_perm.insert(best_perm.end(), neg_order.begin(), neg_order.end());\n    } else {\n        // All negatives? Should not happen with sum=0 and non-zero tasks, but just in case.\n        // Start from (0,0) with load 0, cannot unload, so put negatives first would be infeasible.\n        // Actually if all negatives, sum != 0, so impossible.\n        // We'll leave best_perm empty; program will likely fail but won't happen.\n    }\n\n    auto [best_cost, feasible] = evaluate(best_perm);\n    // If the greedy result is infeasible (shouldn't be), fallback to simple all positives first by sorting.\n    if (!feasible) {\n        // Just concatenate positives then negatives in arbitrary order\n        best_perm = pos_idx;\n        best_perm.insert(best_perm.end(), neg_idx.begin(), neg_idx.end());\n        auto res = evaluate(best_perm);\n        best_cost = res.first;\n    }\n\n    // Try a few random shuffles of positives and negatives separately to improve initial solution\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto rand_int = [&](int lo, int hi) {\n        return uniform_int_distribution<int>(lo, hi)(rng);\n    };\n    auto shuffle_vec = [&](vector<int>& v) {\n        shuffle(v.begin(), v.end(), rng);\n    };\n\n    int initial_trials = 50;\n    for (int t = 0; t < initial_trials; ++t) {\n        vector<int> pos = pos_idx, neg = neg_idx;\n        shuffle_vec(pos);\n        shuffle_vec(neg);\n        vector<int> cand = pos;\n        cand.insert(cand.end(), neg.begin(), neg.end());\n        auto [cst, ok] = evaluate(cand);\n        if (ok && cst < best_cost) {\n            best_cost = cst;\n            best_perm = move(cand);\n        }\n    }\n\n    // SA parameters\n    auto start_time = chrono::steady_clock::now();\n    double T = 1000000.0;\n    double T_min = 0.1;\n    double alpha = 0.9999;\n    int iter = 0;\n    vector<int> cur_perm = best_perm;\n    long long cur_cost = best_cost;\n\n    uniform_real_distribution<double> rand_double(0.0, 1.0);\n\n    while (true) {\n        int move_type = rand_int(0, 2); // 0:swap, 1:reverse, 2:insert\n        bool improved = false;\n        if (move_type == 0) { // swap\n            int i = rand_int(0, S - 1);\n            int j = rand_int(0, S - 1);\n            if (i == j) continue;\n            swap(cur_perm[i], cur_perm[j]);\n            auto [new_cost, feas] = evaluate(cur_perm);\n            if (feas && (new_cost < cur_cost || rand_double(rng) < exp((cur_cost - new_cost) / T))) {\n                cur_cost = new_cost;\n                improved = true;\n            } else {\n                swap(cur_perm[i], cur_perm[j]); // revert\n            }\n        } else if (move_type == 1) { // reverse\n            if (S < 2) continue;\n            int i = rand_int(0, S - 2);\n            int j = rand_int(i + 1, S - 1);\n            reverse(cur_perm.begin() + i, cur_perm.begin() + j + 1);\n            auto [new_cost, feas] = evaluate(cur_perm);\n            if (feas && (new_cost < cur_cost || rand_double(rng) < exp((cur_cost - new_cost) / T))) {\n                cur_cost = new_cost;\n                improved = true;\n            } else {\n                reverse(cur_perm.begin() + i, cur_perm.begin() + j + 1); // revert\n            }\n        } else { // insert\n            int i = rand_int(0, S - 1);\n            int j = rand_int(0, S - 1);\n            if (i == j) continue;\n            vector<int> new_perm = cur_perm;\n            int val = new_perm[i];\n            new_perm.erase(new_perm.begin() + i);\n            new_perm.insert(new_perm.begin() + j, val);\n            auto [new_cost, feas] = evaluate(new_perm);\n            if (feas && (new_cost < cur_cost || rand_double(rng) < exp((cur_cost - new_cost) / T))) {\n                cur_perm = move(new_perm);\n                cur_cost = new_cost;\n                improved = true;\n            }\n        }\n\n        if (improved && cur_cost < best_cost) {\n            best_cost = cur_cost;\n            best_perm = cur_perm;\n        }\n\n        T *= alpha;\n        if (T < T_min) T = T_min;\n        ++iter;\n        if (iter % 1000 == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > 1.9) break;\n        }\n    }\n\n    // Final hill-climbing (T=0)\n    for (int rep = 0; rep < 5000; ++rep) {\n        int move_type = rand_int(0, 2);\n        if (move_type == 0) {\n            int i = rand_int(0, S - 1), j = rand_int(0, S - 1);\n            if (i == j) continue;\n            swap(cur_perm[i], cur_perm[j]);\n            auto [new_cost, feas] = evaluate(cur_perm);\n            if (feas && new_cost < cur_cost) {\n                cur_cost = new_cost;\n                if (cur_cost < best_cost) {\n                    best_cost = cur_cost;\n                    best_perm = cur_perm;\n                }\n            } else {\n                swap(cur_perm[i], cur_perm[j]);\n            }\n        } else if (move_type == 1) {\n            if (S < 2) continue;\n            int i = rand_int(0, S - 2), j = rand_int(i + 1, S - 1);\n            reverse(cur_perm.begin() + i, cur_perm.begin() + j + 1);\n            auto [new_cost, feas] = evaluate(cur_perm);\n            if (feas && new_cost < cur_cost) {\n                cur_cost = new_cost;\n                if (cur_cost < best_cost) {\n                    best_cost = cur_cost;\n                    best_perm = cur_perm;\n                }\n            } else {\n                reverse(cur_perm.begin() + i, cur_perm.begin() + j + 1);\n            }\n        } else {\n            int i = rand_int(0, S - 1), j = rand_int(0, S - 1);\n            if (i == j) continue;\n            vector<int> new_perm = cur_perm;\n            int val = new_perm[i];\n            new_perm.erase(new_perm.begin() + i);\n            new_perm.insert(new_perm.begin() + j, val);\n            auto [new_cost, feas] = evaluate(new_perm);\n            if (feas && new_cost < cur_cost) {\n                cur_perm = move(new_perm);\n                cur_cost = new_cost;\n                if (cur_cost < best_cost) {\n                    best_cost = cur_cost;\n                    best_perm = cur_perm;\n                }\n            }\n        }\n    }\n\n    // Generate output\n    vector<string> ops;\n    int cur_r = 0, cur_c = 0;\n    for (int idx : best_perm) {\n        int tr = tasks[idx].r, tc = tasks[idx].c;\n        while (cur_r < tr) { ops.push_back(\"D\"); cur_r++; }\n        while (cur_r > tr) { ops.push_back(\"U\"); cur_r--; }\n        while (cur_c < tc) { ops.push_back(\"R\"); cur_c++; }\n        while (cur_c > tc) { ops.push_back(\"L\"); cur_c--; }\n        if (tasks[idx].h > 0) {\n            ops.push_back(\"+\" + to_string(tasks[idx].h));\n        } else {\n            ops.push_back(\"-\" + to_string(-tasks[idx].h));\n        }\n    }\n\n    for (auto& s : ops) cout << s << '\\n';\n\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <utility>\n\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, T;\n    cin >> N >> M >> T;\n    const int seed_count = 2 * N * (N - 1); // 60\n\n    vector<vector<int>> seeds(seed_count, vector<int>(M));\n    for (int i = 0; i < seed_count; ++i) {\n        for (int j = 0; j < M; ++j) {\n            cin >> seeds[i][j];\n        }\n    }\n\n    vector<int> sum_seeds(seed_count);\n    for (int i = 0; i < seed_count; ++i) {\n        sum_seeds[i] = accumulate(seeds[i].begin(), seeds[i].end(), 0);\n    }\n\n    for (int t = 0; t < T; ++t) {\n        // Current maximum for each feature\n        vector<int> cur_max(M, 0);\n        for (int i = 0; i < seed_count; ++i) {\n            for (int j = 0; j < M; ++j) {\n                if (seeds[i][j] > cur_max[j]) cur_max[j] = seeds[i][j];\n            }\n        }\n\n        // Identify important seeds (contain at least one current maximum)\n        vector<bool> important(seed_count, false);\n        vector<int> max_count(seed_count, 0);\n        for (int i = 0; i < seed_count; ++i) {\n            int cnt = 0;\n            for (int j = 0; j < M; ++j) {\n                if (seeds[i][j] == cur_max[j]) ++cnt;\n            }\n            if (cnt > 0) {\n                important[i] = true;\n                max_count[i] = cnt;\n            }\n        }\n\n        vector<int> selected;\n        vector<int> imp;\n        for (int i = 0; i < seed_count; ++i) {\n            if (important[i]) imp.push_back(i);\n        }\n\n        if (imp.size() > 36) {\n            // Too many important seeds; keep those with most max features and highest sum\n            sort(imp.begin(), imp.end(), [&](int a, int b) {\n                if (max_count[a] != max_count[b]) return max_count[a] > max_count[b];\n                return sum_seeds[a] > sum_seeds[b];\n            });\n            for (int i = 0; i < 36; ++i) selected.push_back(imp[i]);\n        } else {\n            selected = imp;\n            // Fill remaining slots with non-important seeds having highest sum\n            vector<pair<int, int>> rest;\n            for (int i = 0; i < seed_count; ++i) {\n                if (!important[i]) rest.push_back({sum_seeds[i], i});\n            }\n            sort(rest.begin(), rest.end(), greater<>());\n            for (auto &p : rest) {\n                if (selected.size() >= 36) break;\n                selected.push_back(p.second);\n            }\n        }\n\n        // Find the pair among selected with maximum potential (componentwise max sum)\n        int max_pot = -1;\n        int bestA = selected[0], bestB = selected[1];\n        for (int i = 0; i < 36; ++i) {\n            int si = selected[i];\n            for (int j = i + 1; j < 36; ++j) {\n                int sj = selected[j];\n                int pot = 0;\n                for (int l = 0; l < M; ++l) {\n                    pot += max(seeds[si][l], seeds[sj][l]);\n                }\n                if (pot > max_pot) {\n                    max_pot = pot;\n                    bestA = si;\n                    bestB = sj;\n                }\n            }\n        }\n\n        // Remove the best pair from selected list\n        vector<int> remaining;\n        for (int idx : selected) {\n            if (idx != bestA && idx != bestB) remaining.push_back(idx);\n        }\n\n        // Grid initialization\n        vector<vector<int>> grid(N, vector<int>(N, -1));\n        // Place the best pair at two adjacent interior cells (2,2) and (2,3)\n        grid[2][2] = bestA;\n        grid[2][3] = bestB;\n\n        // Collect neighbor cells of the best pair\n        const int dr[4] = {-1, 1, 0, 0};\n        const int dc[4] = {0, 0, -1, 1};\n        vector<pair<int, int>> neighbors;\n        auto add_neighbors = [&](int r, int c) {\n            for (int d = 0; d < 4; ++d) {\n                int nr = r + dr[d], nc = c + dc[d];\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N && grid[nr][nc] == -1) {\n                    // avoid duplicates\n                    bool found = false;\n                    for (auto &p : neighbors) {\n                        if (p.first == nr && p.second == nc) { found = true; break; }\n                    }\n                    if (!found) neighbors.push_back({nr, nc});\n                }\n            }\n        };\n        add_neighbors(2, 2);\n        add_neighbors(2, 3);\n\n        // Score each remaining seed by its potential with either A or B\n        vector<pair<int, int>> scored; // (score, seed_index)\n        for (int idx : remaining) {\n            int potA = 0, potB = 0;\n            for (int l = 0; l < M; ++l) {\n                potA += max(seeds[bestA][l], seeds[idx][l]);\n                potB += max(seeds[bestB][l], seeds[idx][l]);\n            }\n            scored.push_back({max(potA, potB), idx});\n        }\n        sort(scored.begin(), scored.end(), greater<>());\n\n        // Place best scored seeds into the neighbor cells\n        int place_cnt = min((int)neighbors.size(), (int)scored.size());\n        vector<bool> placed_flag(seed_count, false);\n        placed_flag[bestA] = placed_flag[bestB] = true;\n        for (int i = 0; i < place_cnt; ++i) {\n            int r = neighbors[i].first, c = neighbors[i].second;\n            int sid = scored[i].second;\n            grid[r][c] = sid;\n            placed_flag[sid] = true;\n        }\n\n        // Remaining seeds after placing neighbors\n        vector<int> final_remaining;\n        for (int idx : remaining) {\n            if (!placed_flag[idx]) final_remaining.push_back(idx);\n        }\n\n        // Collect empty cells\n        vector<pair<int, int>> empty_cells;\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                if (grid[r][c] == -1) empty_cells.push_back({r, c});\n            }\n        }\n\n        // Sort empty cells by degree descending (to put good seeds in highly connected positions)\n        auto degree = [&](int r, int c) {\n            int d = 0;\n            for (int dir = 0; dir < 4; ++dir) {\n                int nr = r + dr[dir], nc = c + dc[dir];\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N) ++d;\n            }\n            return d;\n        };\n        sort(empty_cells.begin(), empty_cells.end(), [&](const pair<int, int> &a, const pair<int, int> &b) {\n            int da = degree(a.first, a.second);\n            int db = degree(b.first, b.second);\n            if (da != db) return da > db;\n            if (a.first != b.first) return a.first < b.first;\n            return a.second < b.second;\n        });\n\n        // Sort remaining seeds by sum descending\n        vector<pair<int, int>> rem_sum;\n        for (int idx : final_remaining) rem_sum.push_back({sum_seeds[idx], idx});\n        sort(rem_sum.begin(), rem_sum.end(), greater<>());\n\n        // Assign\n        for (int i = 0; i < (int)empty_cells.size(); ++i) {\n            grid[empty_cells[i].first][empty_cells[i].second] = rem_sum[i].second;\n        }\n\n        // Output grid\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                if (c) cout << ' ';\n                cout << grid[r][c];\n            }\n            cout << '\\n';\n        }\n        cout.flush();\n\n        // Read new seeds\n        for (int i = 0; i < seed_count; ++i) {\n            for (int j = 0; j < M; ++j) {\n                cin >> seeds[i][j];\n            }\n            sum_seeds[i] = accumulate(seeds[i].begin(), seeds[i].end(), 0);\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    int N, M, V;\n    cin >> N >> M >> V;\n    vector<string> s_str(N), t_str(N);\n    for (int i = 0; i < N; ++i) cin >> s_str[i];\n    for (int i = 0; i < N; ++i) cin >> t_str[i];\n    \n    vector<vector<bool>> s(N, vector<bool>(N, false));\n    vector<vector<bool>> t(N, vector<bool>(N, false));\n    int src_cnt = 0, tgt_cnt = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (s_str[i][j] == '1') { s[i][j] = true; src_cnt++; }\n            if (t_str[i][j] == '1') { t[i][j] = true; tgt_cnt++; }\n        }\n    }\n    \n    int Vp = V;\n    int C = V - 1;                     // number of leaves\n    vector<int> dirs(C), lens(C);\n    for (int i = 0; i < C; ++i) {\n        dirs[i] = i % 4;               // 0:right, 1:down, 2:left, 3:up\n        lens[i] = i + 1;               // lengths 1...C\n    }\n    \n    // Output tree design\n    cout << Vp << \"\\n\";\n    for (int i = 0; i < C; ++i) {\n        cout << 0 << \" \" << lens[i] << \"\\n\";\n    }\n    cout << \"0 0\\n\";                   // initial root position\n    \n    // Direction vectors\n    const int ddx[4] = {0, 1, 0, -1}; // row change: right, down, left, up\n    const int ddy[4] = {1, 0, -1, 0}; // col change\n    \n    vector<int> dx(C), dy(C);\n    for (int i = 0; i < C; ++i) {\n        dx[i] = ddx[dirs[i]] * lens[i];\n        dy[i] = ddy[dirs[i]] * lens[i];\n    }\n    \n    // Helper to obtain rotation command for the initial 2-turn setup\n    auto get_rot_cmd = [&](int leaf_idx, int turn) -> char {\n        int target = dirs[leaf_idx];\n        if (target == 0) return '.';\n        if (target == 1) return (turn == 0) ? 'R' : '.';\n        if (target == 2) return (turn == 0 || turn == 1) ? 'R' : '.';\n        if (target == 3) return (turn == 0) ? 'L' : '.';\n        return '.';\n    };\n    \n    // Two initial turns to set leaves to their permanent directions\n    string turn0(2 * Vp, '.'), turn1(2 * Vp, '.');\n    for (int i = 0; i < C; ++i) {\n        turn0[1 + i] = get_rot_cmd(i, 0);\n        turn1[1 + i] = get_rot_cmd(i, 1);\n    }\n    cout << turn0 << \"\\n\";\n    cout << turn1 << \"\\n\";\n    \n    // State after initial setup\n    int rx = 0, ry = 0;\n    vector<bool> occ(C, false);\n    int held = 0;\n    \n    // Output one turn (move and/or actions)\n    auto output_turn = [&](int nx, int ny, bool do_actions, bool is_move, int prev_x, int prev_y) {\n        string S(2 * Vp, '.');\n        char move_char = '.';\n        if (is_move) {\n            if (nx > prev_x) move_char = 'D';\n            else if (nx < prev_x) move_char = 'U';\n            else if (ny > prev_y) move_char = 'R';\n            else if (ny < prev_y) move_char = 'L';\n        }\n        S[0] = move_char;\n        // rotations are always '.' after the initial phase\n        if (do_actions) {\n            vector<bool> act(C, false);\n            for (int i = 0; i < C; ++i) {\n                int tx = nx + dx[i];\n                int ty = ny + dy[i];\n                if (tx >= 0 && tx < N && ty >= 0 && ty < N) {\n                    if (!occ[i] && s[tx][ty]) {\n                        act[i] = true;\n                    } else if (occ[i] && t[tx][ty]) {\n                        act[i] = true;\n                    }\n                }\n            }\n            for (int i = 0; i < C; ++i) {\n                if (act[i]) {\n                    S[Vp + i + 1] = 'P';\n                    int tx = nx + dx[i];\n                    int ty = ny + dy[i];\n                    if (!occ[i]) {      // pick\n                        occ[i] = true;\n                        s[tx][ty] = false;\n                        src_cnt--;\n                        held++;\n                    } else {            // place\n                        occ[i] = false;\n                        t[tx][ty] = false;\n                        tgt_cnt--;\n                        held--;\n                    }\n                }\n            }\n        }\n        cout << S << \"\\n\";\n    };\n    \n    // Main greedy loop\n    while (src_cnt > 0 || held > 0) {\n        // Find best root position (maximum immediate actions)\n        int best_A = -1, best_x = -1, best_y = -1, min_dist = 1e9;\n        for (int nx = 0; nx < N; ++nx) {\n            for (int ny = 0; ny < N; ++ny) {\n                int A = 0;\n                for (int i = 0; i < C; ++i) {\n                    int tx = nx + dx[i];\n                    int ty = ny + dy[i];\n                    if (tx >= 0 && tx < N && ty >= 0 && ty < N) {\n                        if (!occ[i] && s[tx][ty]) A++;\n                        else if (occ[i] && t[tx][ty]) A++;\n                    }\n                }\n                if (A > best_A) {\n                    best_A = A;\n                    best_x = nx; best_y = ny;\n                    min_dist = abs(nx - rx) + abs(ny - ry);\n                } else if (A == best_A) {\n                    int d = abs(nx - rx) + abs(ny - ry);\n                    if (d < min_dist) {\n                        min_dist = d;\n                        best_x = nx; best_y = ny;\n                    }\n                }\n            }\n        }\n        \n        // Should never happen, but fallback just in case\n        if (best_A <= 0) break;\n        \n        // Build Manhattan path (row first, then column)\n        vector<pair<int,int>> path;\n        int cx = rx, cy = ry;\n        while (cx != best_x) {\n            cx += (best_x > cx) ? 1 : -1;\n            path.emplace_back(cx, cy);\n        }\n        while (cy != best_y) {\n            cy += (best_y > cy) ? 1 : -1;\n            path.emplace_back(cx, cy);\n        }\n        \n        if (path.empty()) {\n            // Already at best position, just perform actions\n            output_turn(rx, ry, true, false, rx, ry);\n        } else {\n            // Move step by step; the last step also performs actions\n            for (size_t k = 0; k + 1 < path.size(); ++k) {\n                int nx = path[k].first, ny = path[k].second;\n                output_turn(nx, ny, false, true, cx, cy);\n                cx = nx; cy = ny;\n            }\n            int nx = path.back().first, ny = path.back().second;\n            output_turn(nx, ny, true, true, cx, cy);\n            cx = nx; cy = ny;\n        }\n        rx = best_x; ry = best_y;\n    }\n    \n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <unordered_map>\n#include <utility>\nusing namespace std;\n\nconst int S = 800;                     // cell size\nconst int W = 125;                     // grid width  (100000 / 800)\nconst int H = 125;                     // grid height\nconst int MAX_PERIMETER = 400000;\n\nstruct Edge {\n    int to, rev;\n    long long cap;\n};\n\nstruct Dinic {\n    int N;\n    vector<vector<Edge>> g;\n    vector<int> level, iter;\n\n    Dinic(int n) : N(n), g(n), level(n), iter(n) {}\n\n    void add_edge(int from, int to, long long cap) {\n        g[from].push_back({to, (int)g[to].size(), cap});\n        g[to].push_back({from, (int)g[from].size() - 1, 0});\n    }\n\n    void add_undirected(int u, int v, long long cap) {\n        add_edge(u, v, cap);\n        add_edge(v, u, cap);\n    }\n\n    bool bfs(int s, int t) {\n        fill(level.begin(), level.end(), -1);\n        queue<int> q;\n        level[s] = 0;\n        q.push(s);\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (auto &e : g[v]) {\n                if (e.cap > 0 && level[e.to] == -1) {\n                    level[e.to] = level[v] + 1;\n                    q.push(e.to);\n                }\n            }\n        }\n        return level[t] != -1;\n    }\n\n    long long dfs(int s, int t, long long f) {\n        vector<pair<int, long long>> st;\n        vector<int> prev(N, -1), prev_edge(N, -1);\n        st.push({s, f});\n        prev[s] = s;\n        while (!st.empty()) {\n            auto [v, flow] = st.top();\n            if (v == t) {\n                // augment\n                for (int u = t; u != s; u = prev[u]) {\n                    int ei = prev_edge[u];\n                    Edge &e = g[prev[u]][ei];\n                    e.cap -= flow;\n                    g[u][e.rev].cap += flow;\n                }\n                return flow;\n            }\n            bool found = false;\n            for (int &i = iter[v]; i < (int)g[v].size(); i++) {\n                Edge &e = g[v][i];\n                if (e.cap > 0 && level[v] + 1 == level[e.to]) {\n                    prev[e.to] = v;\n                    prev_edge[e.to] = i;\n                    st.push({e.to, min(flow, e.cap)});\n                    found = true;\n                    break;\n                }\n            }\n            if (!found) {\n                st.pop();\n            }\n        }\n        return 0;\n    }\n\n    long long max_flow(int s, int t) {\n        long long flow = 0;\n        while (bfs(s, t)) {\n            fill(iter.begin(), iter.end(), 0);\n            long long f;\n            while ((f = dfs(s, t, 1e18)) > 0) {\n                flow += f;\n            }\n        }\n        return flow;\n    }\n\n    vector<bool> get_source_set(int s) {\n        vector<bool> vis(N, false);\n        queue<int> q;\n        q.push(s);\n        vis[s] = true;\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (auto &e : g[v]) {\n                if (e.cap > 0 && !vis[e.to]) {\n                    vis[e.to] = true;\n                    q.push(e.to);\n                }\n            }\n        }\n        return vis;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    cin >> N;\n    vector<int> x(2*N), y(2*N);\n    for (int i = 0; i < 2*N; i++) cin >> x[i] >> y[i];\n    \n    // assign each point to a cell and compute cell weight (mackerels - sardines)\n    vector<vector<int>> weight(H, vector<int>(W, 0));\n    for (int i = 0; i < N; i++) {\n        int cx = min(x[i] / S, W - 1);\n        int cy = min(y[i] / S, H - 1);\n        weight[cy][cx]++;\n    }\n    for (int i = N; i < 2*N; i++) {\n        int cx = min(x[i] / S, W - 1);\n        int cy = min(y[i] / S, H - 1);\n        weight[cy][cx]--;\n    }\n    \n    // different trade-off parameters (lambda)\n    vector<int> lambdas = {0, 1, 3, 7, 15, 30, 60, 120, 250, 500};\n    \n    int best_score = -1;\n    vector<vector<bool>> best_inside(H, vector<bool>(W, false));\n    \n    const int dx[4] = {1, -1, 0, 0};\n    const int dy[4] = {0, 0, 1, -1};\n    \n    for (int lambda : lambdas) {\n        Dinic dinic(W * H + 2);\n        int source = W * H, sink = source + 1;\n        \n        // unary terms\n        for (int j = 0; j < H; j++) {\n            for (int i = 0; i < W; i++) {\n                int id = i + j * W;\n                int w = weight[j][i];\n                if (w > 0) dinic.add_edge(source, id, w);\n                else if (w < 0) dinic.add_edge(id, sink, -w);\n            }\n        }\n        \n        // pairwise terms (perimeter penalty)\n        for (int j = 0; j < H; j++) {\n            for (int i = 0; i < W; i++) {\n                int id = i + j * W;\n                if (i + 1 < W) dinic.add_undirected(id, id + 1, lambda);\n                if (j + 1 < H) dinic.add_undirected(id, id + W, lambda);\n            }\n        }\n        \n        dinic.max_flow(source, sink);\n        auto vis = dinic.get_source_set(source);\n        vector<vector<bool>> inside(H, vector<bool>(W, false));\n        for (int j = 0; j < H; j++)\n            for (int i = 0; i < W; i++)\n                inside[j][i] = vis[i + j * W];\n        \n        // find connected components of the inside set\n        vector<vector<int>> comp_id(H, vector<int>(W, -1));\n        int comp_cnt = 0;\n        for (int j = 0; j < H; j++) {\n            for (int i = 0; i < W; i++) {\n                if (inside[j][i] && comp_id[j][i] == -1) {\n                    queue<pair<int,int>> q;\n                    q.push({i, j});\n                    comp_id[j][i] = comp_cnt;\n                    while (!q.empty()) {\n                        auto [cx, cy] = q.front(); q.pop();\n                        for (int d = 0; d < 4; d++) {\n                            int nx = cx + dx[d], ny = cy + dy[d];\n                            if (nx >= 0 && nx < W && ny >= 0 && ny < H && inside[ny][nx] && comp_id[ny][nx] == -1) {\n                                comp_id[ny][nx] = comp_cnt;\n                                q.push({nx, ny});\n                            }\n                        }\n                    }\n                    comp_cnt++;\n                }\n            }\n        }\n        \n        // evaluate each component after filling holes\n        for (int c = 0; c < comp_cnt; c++) {\n            int min_i = W, max_i = -1, min_j = H, max_j = -1;\n            for (int j = 0; j < H; j++) {\n                for (int i = 0; i < W; i++) {\n                    if (comp_id[j][i] == c) {\n                        min_i = min(min_i, i); max_i = max(max_i, i);\n                        min_j = min(min_j, j); max_j = max(max_j, j);\n                    }\n                }\n            }\n            int lw = max_i - min_i + 3;\n            int lh = max_j - min_j + 3;\n            vector<vector<bool>> local(lh, vector<bool>(lw, false));\n            for (int j = min_j; j <= max_j; j++)\n                for (int i = min_i; i <= max_i; i++)\n                    if (comp_id[j][i] == c)\n                        local[j - min_j + 1][i - min_i + 1] = true;\n            \n            // flood fill the outside from the borders of the local grid\n            vector<vector<bool>> vis_local(lh, vector<bool>(lw, false));\n            queue<pair<int,int>> q;\n            for (int y = 0; y < lh; y++) {\n                if (!local[y][0]) { q.push({0, y}); vis_local[y][0] = true; }\n                if (!local[y][lw-1]) { q.push({lw-1, y}); vis_local[y][lw-1] = true; }\n            }\n            for (int x = 0; x < lw; x++) {\n                if (!local[0][x]) { q.push({x, 0}); vis_local[0][x] = true; }\n                if (!local[lh-1][x]) { q.push({x, lh-1}); vis_local[lh-1][x] = true; }\n            }\n            while (!q.empty()) {\n                auto [cx, cy] = q.front(); q.pop();\n                for (int d = 0; d < 4; d++) {\n                    int nx = cx + dx[d], ny = cy + dy[d];\n                    if (nx >= 0 && nx < lw && ny >= 0 && ny < lh && !vis_local[ny][nx] && !local[ny][nx]) {\n                        vis_local[ny][nx] = true;\n                        q.push({nx, ny});\n                    }\n                }\n            }\n            // fill holes (any outside cell not reached by the flood fill)\n            for (int y = 0; y < lh; y++)\n                for (int x = 0; x < lw; x++)\n                    if (!vis_local[y][x] && !local[y][x])\n                        local[y][x] = true;\n            \n            // test if a global cell belongs to the filled component\n            auto is_inside_local = [&](int i, int j) -> bool {\n                if (i < min_i || i > max_i || j < min_j || j > max_j) return false;\n                return local[j - min_j + 1][i - min_i + 1];\n            };\n            \n            long long cur_w = 0;\n            int cur_perim = 0;\n            for (int j = min_j; j <= max_j; j++) {\n                for (int i = min_i; i <= max_i; i++) {\n                    if (is_inside_local(i, j)) {\n                        cur_w += weight[j][i];\n                        if (!is_inside_local(i+1, j)) cur_perim++;\n                        if (!is_inside_local(i-1, j)) cur_perim++;\n                        if (!is_inside_local(i, j+1)) cur_perim++;\n                        if (!is_inside_local(i, j-1)) cur_perim++;\n                    }\n                }\n            }\n            \n            // check perimeter constraint\n            if ((long long)cur_perim * S <= MAX_PERIMETER) {\n                int score = max(0LL, cur_w + 1);\n                if (score > best_score) {\n                    best_score = score;\n                    best_inside.assign(H, vector<bool>(W, false));\n                    for (int j = min_j; j <= max_j; j++)\n                        for (int i = min_i; i <= max_i; i++)\n                            if (is_inside_local(i, j))\n                                best_inside[j][i] = true;\n                }\n            }\n        }\n    }\n    \n    // if no valid component found, fall back to a tiny polygon around a single mackerel\n    if (best_score <= 0) {\n        int best_px = x[0], best_py = y[0];\n        // try to find a mackerel whose 1x1 cell contains no sardine\n        for (int i = 0; i < N; i++) {\n            int px = x[i], py = y[i];\n            bool ok = true;\n            for (int j = N; j < 2*N; j++) {\n                if (x[j] >= px && x[j] <= px+1 && y[j] >= py && y[j] <= py+1) {\n                    ok = false;\n                    break;\n                }\n            }\n            if (ok) {\n                best_px = px; best_py = py;\n                break;\n            }\n        }\n        if (best_px == 100000) best_px = 99999;\n        if (best_py == 100000) best_py = 99999;\n        cout << \"4\\n\";\n        cout << best_px << \" \" << best_py << \"\\n\";\n        cout << best_px+1 << \" \" << best_py << \"\\n\";\n        cout << best_px+1 << \" \" << best_py+1 << \"\\n\";\n        cout << best_px << \" \" << best_py+1 << \"\\n\";\n        return 0;\n    }\n    \n    // trace the outer boundary of best_inside\n    struct Seg {\n        int x1, y1, x2, y2;\n    };\n    vector<Seg> segs;\n    for (int j = 0; j < H; j++) {\n        for (int i = 0; i < W; i++) {\n            if (!best_inside[j][i]) continue;\n            int x = i * S, y = j * S;\n            // top edge\n            if (j == 0 || !best_inside[j-1][i])\n                segs.push_back({x, y, x + S, y});\n            // bottom edge\n            if (j == H-1 || !best_inside[j+1][i])\n                segs.push_back({x, y + S, x + S, y + S});\n            // left edge\n            if (i == 0 || !best_inside[j][i-1])\n                segs.push_back({x, y, x, y + S});\n            // right edge\n            if (i == W-1 || !best_inside[j][i+1])\n                segs.push_back({x + S, y, x + S, y + S});\n        }\n    }\n    \n    // link segments via their endpoints\n    unordered_map<long long, vector<int>> vmap;\n    for (int idx = 0; idx < (int)segs.size(); idx++) {\n        long long k1 = (long long)segs[idx].x1 << 32 | segs[idx].y1;\n        long long k2 = (long long)segs[idx].x2 << 32 | segs[idx].y2;\n        vmap[k1].push_back(idx);\n        vmap[k2].push_back(idx);\n    }\n    \n    // trace the boundary loop\n    vector<pair<int,int>> poly;\n    int start_x = segs[0].x1, start_y = segs[0].y1;\n    poly.push_back({start_x, start_y});\n    int cur_x = segs[0].x2, cur_y = segs[0].y2;\n    poly.push_back({cur_x, cur_y});\n    int prev_seg = 0;\n    while (true) {\n        long long key = (long long)cur_x << 32 | cur_y;\n        int next_seg = -1;\n        for (int sid : vmap[key]) {\n            if (sid != prev_seg) {\n                next_seg = sid;\n                break;\n            }\n        }\n        if (next_seg == -1) break;  // should not happen\n        int nx, ny;\n        if (segs[next_seg].x1 == cur_x && segs[next_seg].y1 == cur_y) {\n            nx = segs[next_seg].x2;\n            ny = segs[next_seg].y2;\n        } else {\n            nx = segs[next_seg].x1;\n            ny = segs[next_seg].y1;\n        }\n        if (nx == start_x && ny == start_y) break;\n        poly.push_back({nx, ny});\n        cur_x = nx; cur_y = ny;\n        prev_seg = next_seg;\n    }\n    \n    // remove collinear vertices\n    vector<pair<int,int>> simple = poly;\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        for (size_t i = 0; i < simple.size(); i++) {\n            size_t prv = (i == 0) ? simple.size() - 1 : i - 1;\n            size_t nxt = (i + 1) % simple.size();\n            if (simple[prv].first == simple[i].first && simple[i].first == simple[nxt].first) {\n                simple.erase(simple.begin() + i);\n                changed = true;\n                break;\n            }\n            if (simple[prv].second == simple[i].second && simple[i].second == simple[nxt].second) {\n                simple.erase(simple.begin() + i);\n                changed = true;\n                break;\n            }\n        }\n    }\n    \n    // output\n    cout << simple.size() << \"\\n\";\n    for (auto [xx, yy] : simple)\n        cout << xx << \" \" << yy << \"\\n\";\n    \n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <string>\n#include <utility>\nusing namespace std;\n\nstruct PlacedRect {\n    int index;          // original index (0..N-1)\n    long long x, y;     // position\n    long long w, h;     // size after rotation\n    int rot;            // 0 or 1\n    char dir;           // 'U' or 'L'\n    int base;           // -1 or original index of reference\n};\n\nstruct State {\n    vector<PlacedRect> rects;\n    long long W, H;\n    long long sum_skipped;   // sum of (w+h) for skipped indices\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int N, T, sigma;\n    cin >> N >> T >> sigma;\n    vector<int> w_obs(N), h_obs(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> w_obs[i] >> h_obs[i];\n    }\n\n    // current estimates for true sizes (double for averaging)\n    vector<double> sum_w(N), sum_h(N);\n    vector<int> cnt(N);\n    for (int i = 0; i < N; ++i) {\n        sum_w[i] = w_obs[i];\n        sum_h[i] = h_obs[i];\n        cnt[i] = 1;\n    }\n\n    int turns_done = 0;\n\n    auto update_est = [&](int i, long long w_meas, long long h_meas) {\n        sum_w[i] += w_meas;\n        sum_h[i] += h_meas;\n        cnt[i]++;\n    };\n\n    // If enough turns, spend 2N turns to measure each rectangle twice.\n    if (T >= 2 * N + 10) {\n        for (int i = 0; i < N; ++i) {\n            // r = 0\n            cout << 1 << \"\\n\";\n            cout << i << \" 0 U -1\\n\" << flush;\n            long long Wp, Hp;\n            cin >> Wp >> Hp;\n            update_est(i, Wp, Hp);\n            ++turns_done;\n\n            // r = 1\n            cout << 1 << \"\\n\";\n            cout << i << \" 1 U -1\\n\" << flush;\n            cin >> Wp >> Hp;\n            update_est(i, Hp, Wp);  // swapped\n            ++turns_done;\n        }\n    }\n\n    // final integer estimates\n    vector<long long> ew(N), eh(N);\n    for (int i = 0; i < N; ++i) {\n        ew[i] = (long long)round(sum_w[i] / cnt[i]);\n        eh[i] = (long long)round(sum_h[i] / cnt[i]);\n    }\n\n    // suffix sums for the beam search heuristic\n    vector<long long> suffix_sum(N + 1, 0);\n    for (int i = N - 1; i >= 0; --i) suffix_sum[i] = suffix_sum[i + 1] + ew[i] + eh[i];\n\n    // Beam search for a good placement sequence\n    const int BEAM = 30;\n    vector<State> beam;\n    beam.push_back(State{ {}, 0LL, 0LL, 0LL });\n\n    for (int i = 0; i < N; ++i) {\n        vector<State> next_beams;\n        next_beams.reserve(BEAM * (5 + 4 * N)); // rough upper bound\n\n        for (const auto& s : beam) {\n            // option: skip rectangle i\n            {\n                State skip_s = s;\n                skip_s.sum_skipped += ew[i] + eh[i];\n                next_beams.push_back(move(skip_s));\n            }\n\n            long long w = ew[i];\n            long long h = eh[i];\n\n            for (int rot = 0; rot <= 1; ++rot) {\n                long long cur_w = rot ? h : w;\n                long long cur_h = rot ? w : h;\n\n                // U with base = -1\n                {\n                    long long x = 0, y = 0;\n                    for (const auto& pr : s.rects) {\n                        if (x + cur_w > pr.x && pr.x + pr.w > x)\n                            y = max(y, pr.y + pr.h);\n                    }\n                    State ns = s;\n                    ns.rects.push_back({i, x, y, cur_w, cur_h, rot, 'U', -1});\n                    ns.W = max(ns.W, x + cur_w);\n                    ns.H = max(ns.H, y + cur_h);\n                    next_beams.push_back(move(ns));\n                }\n\n                // L with base = -1\n                {\n                    long long y = 0, x = 0;\n                    for (const auto& pr : s.rects) {\n                        if (y + cur_h > pr.y && pr.y + pr.h > y)\n                            x = max(x, pr.x + pr.w);\n                    }\n                    State ns = s;\n                    ns.rects.push_back({i, x, y, cur_w, cur_h, rot, 'L', -1});\n                    ns.W = max(ns.W, x + cur_w);\n                    ns.H = max(ns.H, y + cur_h);\n                    next_beams.push_back(move(ns));\n                }\n\n                // attach to each already placed rectangle\n                for (const auto& pr : s.rects) {\n                    int base = pr.index;\n\n                    // U\n                    {\n                        long long x = pr.x + pr.w;\n                        long long y = 0;\n                        for (const auto& pr2 : s.rects) {\n                            if (x + cur_w > pr2.x && pr2.x + pr2.w > x)\n                                y = max(y, pr2.y + pr2.h);\n                        }\n                        State ns = s;\n                        ns.rects.push_back({i, x, y, cur_w, cur_h, rot, 'U', base});\n                        ns.W = max(ns.W, x + cur_w);\n                        ns.H = max(ns.H, y + cur_h);\n                        next_beams.push_back(move(ns));\n                    }\n\n                    // L\n                    {\n                        long long y = pr.y + pr.h;\n                        long long x = 0;\n                        for (const auto& pr2 : s.rects) {\n                            if (y + cur_h > pr2.y && pr2.y + pr2.h > y)\n                                x = max(x, pr2.x + pr2.w);\n                        }\n                        State ns = s;\n                        ns.rects.push_back({i, x, y, cur_w, cur_h, rot, 'L', base});\n                        ns.W = max(ns.W, x + cur_w);\n                        ns.H = max(ns.H, y + cur_h);\n                        next_beams.push_back(move(ns));\n                    }\n                }\n            }\n        }\n\n        // keep top BEAM states according to the heuristic\n        vector<pair<long long, int>> costs;\n        costs.reserve(next_beams.size());\n        for (int idx = 0; idx < (int)next_beams.size(); ++idx) {\n            const auto& ns = next_beams[idx];\n            long long cost = ns.W + ns.H + ns.sum_skipped + suffix_sum[i + 1];\n            costs.emplace_back(cost, idx);\n        }\n        sort(costs.begin(), costs.end());\n        beam.clear();\n        for (int j = 0; j < min(BEAM, (int)costs.size()); ++j)\n            beam.push_back(move(next_beams[costs[j].second]));\n    }\n\n    // select the absolute best state (final score = W+H+sum_skipped)\n    const State* best = &beam[0];\n    long long best_cost = best->W + best->H + best->sum_skipped;\n    for (const auto& s : beam) {\n        long long c = s.W + s.H + s.sum_skipped;\n        if (c < best_cost) {\n            best_cost = c;\n            best = &s;\n        }\n    }\n\n    int n = best->rects.size();\n    int rem = T - turns_done;\n    for (int t = 0; t < rem; ++t) {\n        cout << n << \"\\n\";\n        for (const auto& pr : best->rects)\n            cout << pr.index << \" \" << pr.rot << \" \" << pr.dir << \" \" << pr.base << \"\\n\";\n        cout << flush;\n        long long Wp, Hp;\n        cin >> Wp >> Hp;   // read and ignore the measurements\n    }\n\n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <stack>\n#include <ctime>\n#include <cmath>\n#include <cstdint>\n#include <random>\n\nusing namespace std;\n\n// fast random number generator\nuint32_t xor_state;\nvoid init_random() {\n    random_device rd;\n    xor_state = rd();\n    if(xor_state == 0) xor_state = 123456789;\n}\nuint32_t xorshift32() {\n    uint32_t x = xor_state;\n    x ^= x << 13;\n    x ^= x >> 17;\n    x ^= x << 5;\n    return xor_state = x;\n}\ninline double random_double() {\n    return (xorshift32() >> 8) / double(1 << 24);\n}\ninline int random_int(int n) {\n    return xorshift32() % n;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    init_random();\n\n    int N, M, H;\n    cin >> N >> M >> H;\n    vector<int> A(N);\n    for(int i=0; i<N; i++) cin >> A[i];\n    vector<vector<int>> adj(N);\n    for(int i=0; i<M; i++){\n        int u, v; cin >> u >> v;\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n    // skip coordinates\n    for(int i=0; i<N; i++){\n        int x, y; cin >> x >> y;\n    }\n\n    // state\n    vector<int> parent(N, -1);\n    vector<int> depth(N, 0);\n    vector<vector<int>> children(N);\n    vector<int> subtree_sum_A = A;\n    vector<int> subtree_max_depth(N, 0);\n    vector<int> root_of(N);\n    iota(root_of.begin(), root_of.end(), 0);\n\n    // greedy initialization (process vertices in descending A)\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int i, int j){ return A[i] > A[j]; });\n\n    for(int v : order){\n        if(parent[v] != -1) continue;\n        int best_u = -1;\n        int best_udepth = -1;\n        for(int u : adj[v]){\n            if(root_of[u] == v) continue;\n            int new_d = depth[u] + 1;\n            if(new_d + subtree_max_depth[v] <= H){\n                if(depth[u] > best_udepth){\n                    best_udepth = depth[u];\n                    best_u = u;\n                }\n            }\n        }\n        if(best_u != -1){\n            int delta = depth[best_u] + 1;\n            int new_root = root_of[best_u];\n            parent[v] = best_u;\n            children[best_u].push_back(v);\n            stack<int> st;\n            st.push(v);\n            while(!st.empty()){\n                int node = st.top(); st.pop();\n                depth[node] += delta;\n                root_of[node] = new_root;\n                for(int child : children[node]){\n                    st.push(child);\n                }\n            }\n            // update ancestors\n            vector<int> to_update;\n            int cur = best_u;\n            while(cur != -1){\n                to_update.push_back(cur);\n                cur = parent[cur];\n            }\n            sort(to_update.begin(), to_update.end(), [&](int a, int b){ return depth[a] > depth[b]; });\n            for(int node : to_update){\n                int sum = A[node];\n                int max_d = 0;\n                for(int child : children[node]){\n                    sum += subtree_sum_A[child];\n                    max_d = max(max_d, subtree_max_depth[child] + 1);\n                }\n                subtree_sum_A[node] = sum;\n                subtree_max_depth[node] = max_d;\n            }\n        }\n    }\n\n    // initial score\n    long long score = 0;\n    for(int i=0; i<N; i++){\n        score += (depth[i] + 1LL) * A[i];\n    }\n    long long best_score = score;\n    vector<int> best_parent = parent;\n\n    // helper functions for SA\n    auto is_descendant = [&](int anc, int desc) -> bool {\n        if(depth[desc] < depth[anc]) return false;\n        int cur = desc;\n        while(cur != -1 && depth[cur] > depth[anc]){\n            cur = parent[cur];\n        }\n        return cur == anc;\n    };\n\n    auto apply_move = [&](int v, int new_p, int delta) {\n        int old_p = parent[v];\n        int old_d = depth[v];\n        int new_d = (new_p == -1) ? 0 : depth[new_p] + 1;\n        int depth_delta = new_d - old_d;\n        // remove from old parent\n        if(old_p != -1){\n            auto it = find(children[old_p].begin(), children[old_p].end(), v);\n            if(it != children[old_p].end()) children[old_p].erase(it);\n        }\n        // add to new parent\n        if(new_p != -1){\n            children[new_p].push_back(v);\n        }\n        parent[v] = new_p;\n        // update depths in subtree of v\n        if(depth_delta != 0){\n            stack<int> st;\n            st.push(v);\n            while(!st.empty()){\n                int node = st.top(); st.pop();\n                depth[node] += depth_delta;\n                for(int child : children[node]){\n                    st.push(child);\n                }\n            }\n        }\n        // update subtree properties for affected ancestors\n        vector<int> to_update;\n        if(old_p != -1){\n            int cur = old_p;\n            while(cur != -1){\n                to_update.push_back(cur);\n                cur = parent[cur];\n            }\n        }\n        if(new_p != -1){\n            int cur = new_p;\n            while(cur != -1){\n                to_update.push_back(cur);\n                cur = parent[cur];\n            }\n        }\n        sort(to_update.begin(), to_update.end(), [&](int a, int b){ return depth[a] > depth[b]; });\n        to_update.erase(unique(to_update.begin(), to_update.end()), to_update.end());\n        for(int node : to_update){\n            int sum = A[node];\n            int max_d = 0;\n            for(int child : children[node]){\n                sum += subtree_sum_A[child];\n                max_d = max(max_d, subtree_max_depth[child] + 1);\n            }\n            subtree_sum_A[node] = sum;\n            subtree_max_depth[node] = max_d;\n        }\n    };\n\n    // simulated annealing\n    clock_t start_clock = clock();\n    double time_limit_sec = 1.95;\n    double T_start = 20000.0;\n    double T_end = 0.1;\n    double T = T_start;\n    int iter_count = 0;\n\n    while(true){\n        if(iter_count % 1000 == 0){\n            double elapsed = double(clock() - start_clock) / CLOCKS_PER_SEC;\n            if(elapsed >= time_limit_sec) break;\n            T = T_start * pow(T_end / T_start, elapsed / time_limit_sec);\n        }\n        iter_count++;\n        bool moved = false;\n        for(int attempt = 0; attempt < 5; attempt++){\n            int v = random_int(N);\n            int old_p = parent[v];\n            int u;\n            if(old_p != -1 && random_double() < 0.1){\n                u = -1;  // make root\n            } else {\n                if(adj[v].empty()) continue;\n                u = adj[v][random_int(adj[v].size())];\n            }\n            if(u == old_p) continue;\n            int new_d;\n            if(u == -1){\n                new_d = 0;\n            } else {\n                if(is_descendant(v, u) || is_descendant(u, v)) continue;\n                new_d = depth[u] + 1;\n                if(new_d + subtree_max_depth[v] > H) continue;\n            }\n            int delta = (new_d - depth[v]) * subtree_sum_A[v];\n            if(delta >= 0 || random_double() < exp(delta / T)){\n                apply_move(v, u, delta);\n                score += delta;\n                moved = true;\n                if(score > best_score){\n                    best_score = score;\n                    best_parent = parent;\n                }\n                break;\n            }\n        }\n    }\n\n    for(int i=0; i<N; i++){\n        cout << best_parent[i] << (i==N-1 ? \"\\n\" : \" \");\n    }\n\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <utility>\nusing namespace std;\n\nconst int N = 20;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n;\n    cin >> n; // N=20\n    vector<string> C(n);\n    for (int i = 0; i < n; ++i) cin >> C[i];\n    \n    // Locate Oni and Fuku\n    vector<pair<int,int>> oni;\n    bool fuku[N][N] = {false};\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (C[i][j] == 'x') oni.push_back({i,j});\n            else if (C[i][j] == 'o') fuku[i][j] = true;\n        }\n    }\n    int K = oni.size(); // 40\n    \n    // Compute safe intervals for each row/column\n    int L_max[N], R_min[N], U_max[N], D_min[N];\n    for (int i = 0; i < N; ++i) {\n        L_max[i] = N-1;\n        for (int j = 0; j < N; ++j) if (fuku[i][j]) { L_max[i] = j-1; break; }\n        R_min[i] = 0;\n        for (int j = N-1; j >= 0; --j) if (fuku[i][j]) { R_min[i] = j+1; break; }\n    }\n    for (int j = 0; j < N; ++j) {\n        U_max[j] = N-1;\n        for (int i = 0; i < N; ++i) if (fuku[i][j]) { U_max[j] = i-1; break; }\n        D_min[j] = 0;\n        for (int i = N-1; i >= 0; --i) if (fuku[i][j]) { D_min[j] = i+1; break; }\n    }\n    \n    // Allowed lines for each Oni\n    bool allowed_row[K], allowed_col[K];\n    vector<int> both_allowed;\n    for (int k = 0; k < K; ++k) {\n        int i = oni[k].first, j = oni[k].second;\n        allowed_row[k] = (j <= L_max[i]) || (j >= R_min[i]);\n        allowed_col[k] = (i <= U_max[j]) || (i >= D_min[j]);\n        if (allowed_row[k] && allowed_col[k]) both_allowed.push_back(k);\n    }\n    \n    // Initial greedy assignment\n    vector<int> row_cols[N], col_rows[N];\n    bool assign_row[K];\n    for (int k = 0; k < K; ++k) {\n        int i = oni[k].first, j = oni[k].second;\n        if (allowed_row[k] && allowed_col[k]) {\n            int c_row = 1e9, c_col = 1e9;\n            if (j <= L_max[i]) c_row = min(c_row, 2*(j+1));\n            if (j >= R_min[i]) c_row = min(c_row, 2*(N-j));\n            if (i <= U_max[j]) c_col = min(c_col, 2*(i+1));\n            if (i >= D_min[j]) c_col = min(c_col, 2*(N-i));\n            assign_row[k] = (c_row <= c_col);\n        } else if (allowed_row[k]) {\n            assign_row[k] = true;\n        } else {\n            assign_row[k] = false;\n        }\n    }\n    for (int k = 0; k < K; ++k) {\n        int i = oni[k].first, j = oni[k].second;\n        if (assign_row[k]) row_cols[i].push_back(j);\n        else col_rows[j].push_back(i);\n    }\n    for (int i = 0; i < N; ++i) sort(row_cols[i].begin(), row_cols[i].end());\n    for (int j = 0; j < N; ++j) sort(col_rows[j].begin(), col_rows[j].end());\n    \n    // Cost functions for a single row / column\n    auto cost_row = [&](int i) {\n        const auto& cols = row_cols[i];\n        if (cols.empty()) return 0;\n        int L_safe = L_max[i] + 1;\n        int R_safe = N - R_min[i];\n        int m = cols.size();\n        int suf[N+1] = {0};\n        for (int idx = m-1; idx >= 0; --idx)\n            suf[idx] = max(suf[idx+1], N - cols[idx]);\n        int best = 1e9;\n        for (int L_len = 0; L_len <= L_safe; ++L_len) {\n            int idx = lower_bound(cols.begin(), cols.end(), L_len) - cols.begin();\n            int R_len = suf[idx];\n            if (R_len <= R_safe) {\n                int cost = 2 * (L_len + R_len);\n                if (cost < best) best = cost;\n            }\n        }\n        return best;\n    };\n    \n    auto cost_col = [&](int j) {\n        const auto& rows = col_rows[j];\n        if (rows.empty()) return 0;\n        int U_safe = U_max[j] + 1;\n        int D_safe = N - D_min[j];\n        int m = rows.size();\n        int suf[N+1] = {0};\n        for (int idx = m-1; idx >= 0; --idx)\n            suf[idx] = max(suf[idx+1], N - rows[idx]);\n        int best = 1e9;\n        for (int U_len = 0; U_len <= U_safe; ++U_len) {\n            int idx = lower_bound(rows.begin(), rows.end(), U_len) - rows.begin();\n            int D_len = suf[idx];\n            if (D_len <= D_safe) {\n                int cost = 2 * (U_len + D_len);\n                if (cost < best) best = cost;\n            }\n        }\n        return best;\n    };\n    \n    int total_cost = 0;\n    for (int i = 0; i < N; ++i) total_cost += cost_row(i);\n    for (int j = 0; j < N; ++j) total_cost += cost_col(j);\n    \n    int best_cost = total_cost;\n    bool best_assign[K];\n    for (int k = 0; k < K; ++k) best_assign[k] = assign_row[k];\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> dist01(0.0, 1.0);\n    double temp = 10.0;\n    double cool = 0.999;\n    const int MAX_ITER = 10000;\n    \n    auto apply_flip = [&](int k) {\n        int i = oni[k].first, j = oni[k].second;\n        int old_row = cost_row(i);\n        int old_col = cost_col(j);\n        if (assign_row[k]) {\n            auto& rv = row_cols[i];\n            rv.erase(lower_bound(rv.begin(), rv.end(), j));\n            auto& cv = col_rows[j];\n            cv.insert(lower_bound(cv.begin(), cv.end(), i), i);\n            assign_row[k] = false;\n        } else {\n            auto& cv = col_rows[j];\n            cv.erase(lower_bound(cv.begin(), cv.end(), i));\n            auto& rv = row_cols[i];\n            rv.insert(lower_bound(rv.begin(), rv.end(), j), j);\n            assign_row[k] = true;\n        }\n        int new_row = cost_row(i);\n        int new_col = cost_col(j);\n        int delta = (new_row - old_row) + (new_col - old_col);\n        total_cost += delta;\n        return delta;\n    };\n    \n    // Simulated Annealing on the partition\n    if (!both_allowed.empty()) {\n        for (int iter = 0; iter < MAX_ITER; ++iter) {\n            int k = both_allowed[rng() % both_allowed.size()];\n            double delta = apply_flip(k);\n            if (delta <= 0 || dist01(rng) < exp(-delta / temp)) {\n                if (total_cost < best_cost) {\n                    best_cost = total_cost;\n                    for (int kk = 0; kk < K; ++kk) best_assign[kk] = assign_row[kk];\n                }\n            } else {\n                apply_flip(k); // revert\n            }\n            temp *= cool;\n        }\n    }\n    \n    // Restore best assignment\n    for (int i = 0; i < N; ++i) row_cols[i].clear();\n    for (int j = 0; j < N; ++j) col_rows[j].clear();\n    for (int k = 0; k < K; ++k) {\n        int i = oni[k].first, j = oni[k].second;\n        if (best_assign[k]) row_cols[i].push_back(j);\n        else col_rows[j].push_back(i);\n    }\n    for (int i = 0; i < N; ++i) sort(row_cols[i].begin(), row_cols[i].end());\n    for (int j = 0; j < N; ++j) sort(col_rows[j].begin(), col_rows[j].end());\n    total_cost = best_cost;\n    for (int k = 0; k < K; ++k) assign_row[k] = best_assign[k];\n    \n    // Hill-climb from best state to ensure local minimum\n    if (!both_allowed.empty()) {\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            vector<int> shuf = both_allowed;\n            shuffle(shuf.begin(), shuf.end(), rng);\n            for (int k : shuf) {\n                int old = total_cost;\n                apply_flip(k);\n                if (total_cost < old) {\n                    improved = true;\n                    if (total_cost < best_cost) {\n                        best_cost = total_cost;\n                        for (int kk = 0; kk < K; ++kk) best_assign[kk] = assign_row[kk];\n                    }\n                } else {\n                    apply_flip(k); // revert\n                }\n            }\n        }\n    }\n    \n    // Rebuild final state from best assignment\n    for (int i = 0; i < N; ++i) row_cols[i].clear();\n    for (int j = 0; j < N; ++j) col_rows[j].clear();\n    for (int k = 0; k < K; ++k) {\n        int i = oni[k].first, j = oni[k].second;\n        if (best_assign[k]) row_cols[i].push_back(j);\n        else col_rows[j].push_back(i);\n    }\n    for (int i = 0; i < N; ++i) sort(row_cols[i].begin(), row_cols[i].end());\n    for (int j = 0; j < N; ++j) sort(col_rows[j].begin(), col_rows[j].end());\n    \n    // Extract optimal push lengths\n    auto get_row_ops = [&](int i) -> pair<int,int> {\n        const auto& cols = row_cols[i];\n        if (cols.empty()) return {0,0};\n        int L_safe = L_max[i] + 1;\n        int R_safe = N - R_min[i];\n        int m = cols.size();\n        int suf[N+1] = {0};\n        for (int idx = m-1; idx >= 0; --idx) suf[idx] = max(suf[idx+1], N - cols[idx]);\n        int best_c = 1e9;\n        int best_L = 0, best_R = 0;\n        for (int L_len = 0; L_len <= L_safe; ++L_len) {\n            int idx = lower_bound(cols.begin(), cols.end(), L_len) - cols.begin();\n            int R_len = suf[idx];\n            if (R_len <= R_safe) {\n                int cst = 2*(L_len + R_len);\n                if (cst < best_c) { best_c = cst; best_L = L_len; best_R = R_len; }\n            }\n        }\n        return {best_L, best_R};\n    };\n    auto get_col_ops = [&](int j) -> pair<int,int> {\n        const auto& rows = col_rows[j];\n        if (rows.empty()) return {0,0};\n        int U_safe = U_max[j] + 1;\n        int D_safe = N - D_min[j];\n        int m = rows.size();\n        int suf[N+1] = {0};\n        for (int idx = m-1; idx >= 0; --idx) suf[idx] = max(suf[idx+1], N - rows[idx]);\n        int best_c = 1e9;\n        int best_U = 0, best_D = 0;\n        for (int U_len = 0; U_len <= U_safe; ++U_len) {\n            int idx = lower_bound(rows.begin(), rows.end(), U_len) - rows.begin();\n            int D_len = suf[idx];\n            if (D_len <= D_safe) {\n                int cst = 2*(U_len + D_len);\n                if (cst < best_c) { best_c = cst; best_U = U_len; best_D = D_len; }\n            }\n        }\n        return {best_U, best_D};\n    };\n    \n    vector<pair<char,int>> ops;\n    for (int i = 0; i < N; ++i) {\n        auto [L_len, R_len] = get_row_ops(i);\n        for (int t = 0; t < L_len; ++t) ops.push_back({'L', i});\n        for (int t = 0; t < L_len; ++t) ops.push_back({'R', i});\n        for (int t = 0; t < R_len; ++t) ops.push_back({'R', i});\n        for (int t = 0; t < R_len; ++t) ops.push_back({'L', i});\n    }\n    for (int j = 0; j < N; ++j) {\n        auto [U_len, D_len] = get_col_ops(j);\n        for (int t = 0; t < U_len; ++t) ops.push_back({'U', j});\n        for (int t = 0; t < U_len; ++t) ops.push_back({'D', j});\n        for (int t = 0; t < D_len; ++t) ops.push_back({'D', j});\n        for (int t = 0; t < D_len; ++t) ops.push_back({'U', j});\n    }\n    \n    // Output the sequence\n    for (const auto& [d, p] : ops) {\n        cout << d << \" \" << p << \"\\n\";\n    }\n    \n    return 0;\n}","ahc044":"#include <iostream>\n#include <cstdlib>\n#include <cmath>\n#include <chrono>\n#include <cstring>\n#include <algorithm>\n#include <climits>\n\nusing namespace std;\n\nconst int N = 100;\nconst int L = 500000;\n\nint T[N];\n\ninline int compute_error(const int a[N], const int b[N]) {\n    int t[N] = {0};\n    t[0] = 1;\n    int cur = 0;\n    int edge[N][2];\n    for (int i = 0; i < N; ++i) {\n        edge[i][0] = b[i];\n        edge[i][1] = a[i];\n    }\n    for (int step = 1; step < L; ++step) {\n        cur = edge[cur][t[cur] & 1];\n        t[cur]++;\n    }\n    int err = 0;\n    for (int i = 0; i < N; ++i) {\n        int diff = t[i] - T[i];\n        err += (diff > 0) ? diff : -diff;\n    }\n    return err;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    int N_in, L_in;\n    cin >> N_in >> L_in;\n    for (int i = 0; i < N; ++i) cin >> T[i];\n    \n    srand(time(0));\n    \n    int best_a[N], best_b[N];\n    int best_err = INT_MAX;\n    \n    // Cumulative distribution for proportional edge selection\n    int cum[N+1];\n    cum[0] = 0;\n    for (int i = 0; i < N; ++i) cum[i+1] = cum[i] + T[i];\n    \n    // 100 initial solutions: cycle on a, frequency-guided b\n    for (int k = 0; k < 100; ++k) {\n        int a[N], b[N];\n        for (int i = 0; i < N; ++i) {\n            a[i] = (i+1) % N;\n            int r = rand() % L;\n            int j = upper_bound(cum, cum+N+1, r) - cum - 1;\n            if (j < 0) j = 0;\n            b[i] = j;\n        }\n        int err = compute_error(a, b);\n        if (err < best_err) {\n            best_err = err;\n            memcpy(best_a, a, sizeof(a));\n            memcpy(best_b, b, sizeof(b));\n        }\n    }\n    \n    // 20 completely random initial solutions\n    for (int k = 0; k < 20; ++k) {\n        int a[N], b[N];\n        for (int i = 0; i < N; ++i) {\n            a[i] = rand() % N;\n            b[i] = rand() % N;\n        }\n        int err = compute_error(a, b);\n        if (err < best_err) {\n            best_err = err;\n            memcpy(best_a, a, sizeof(a));\n            memcpy(best_b, b, sizeof(b));\n        }\n    }\n    \n    int cur_a[N], cur_b[N];\n    memcpy(cur_a, best_a, sizeof(cur_a));\n    memcpy(cur_b, best_b, sizeof(cur_b));\n    int cur_err = best_err;\n    \n    auto start = chrono::steady_clock::now();\n    double time_limit = 1.95;\n    double T_start = 5000.0;\n    double T_end = 0.1;\n    double temp = T_start;\n    int iter = 0;\n    \n    while (true) {\n        if (iter % 100 == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start).count();\n            if (elapsed > time_limit) break;\n            double progress = elapsed / time_limit;\n            temp = T_start * pow(T_end / T_start, progress);\n        }\n        \n        int move_type = rand() % 10;\n        int old_err = cur_err;\n        bool reverted = false;\n        \n        if (move_type < 8) {   // 80%: change one outgoing edge\n            int i = rand() % N;\n            int new_val = rand() % N;\n            bool change_a = rand() & 1;\n            int old_val = change_a ? cur_a[i] : cur_b[i];\n            if (change_a) cur_a[i] = new_val;\n            else cur_b[i] = new_val;\n            \n            int new_err = compute_error(cur_a, cur_b);\n            int delta = new_err - cur_err;\n            if (delta <= 0) {\n                cur_err = new_err;\n            } else {\n                double prob = exp(-delta / temp);\n                if ((double)rand() / RAND_MAX < prob) {\n                    cur_err = new_err;\n                } else {\n                    if (change_a) cur_a[i] = old_val;\n                    else cur_b[i] = old_val;\n                    reverted = true;\n                }\n            }\n        } else if (move_type == 8) { // 10%: swap a_i and b_i\n            int i = rand() % N;\n            swap(cur_a[i], cur_b[i]);\n            int new_err = compute_error(cur_a, cur_b);\n            int delta = new_err - cur_err;\n            if (delta <= 0) {\n                cur_err = new_err;\n            } else {\n                double prob = exp(-delta / temp);\n                if ((double)rand() / RAND_MAX < prob) {\n                    cur_err = new_err;\n                } else {\n                    swap(cur_a[i], cur_b[i]); // revert\n                    reverted = true;\n                }\n            }\n        } else { // 10%: change both a_i and b_i\n            int i = rand() % N;\n            int old_a = cur_a[i], old_b = cur_b[i];\n            cur_a[i] = rand() % N;\n            cur_b[i] = rand() % N;\n            int new_err = compute_error(cur_a, cur_b);\n            int delta = new_err - cur_err;\n            if (delta <= 0) {\n                cur_err = new_err;\n            } else {\n                double prob = exp(-delta / temp);\n                if ((double)rand() / RAND_MAX < prob) {\n                    cur_err = new_err;\n                } else {\n                    cur_a[i] = old_a;\n                    cur_b[i] = old_b;\n                    reverted = true;\n                }\n            }\n        }\n        \n        if (cur_err < best_err) {\n            best_err = cur_err;\n            memcpy(best_a, cur_a, sizeof(cur_a));\n            memcpy(best_b, cur_b, sizeof(cur_b));\n        }\n        \n        ++iter;\n        if (best_err == 0) break;\n    }\n    \n    for (int i = 0; i < N; ++i) {\n        cout << best_a[i] << \" \" << best_b[i] << \"\\n\";\n    }\n    \n    return 0;\n}","ahc045":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n#include <cstdint>\n\nusing namespace std;\n\nint N, M, Q, L;\nint q_used = 0;                      // number of queries performed\nvector<int> cx, cy;                  // estimated centers\n\n// query a subset, return MST edges (u, v) with u<v\nvector<pair<int, int>> query_subset(const vector<int>& C) {\n    if (q_used >= Q) return {};      // no more queries allowed\n    ++q_used;\n    int l = (int)C.size();\n    cout << \"? \" << l;\n    for (int c : C) cout << \" \" << c;\n    cout << endl;\n    vector<pair<int, int>> res(l - 1);\n    for (int i = 0; i < l - 1; ++i) {\n        cin >> res[i].first >> res[i].second;\n    }\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int W;\n    cin >> N >> M >> Q >> L >> W;\n    vector<int> G(M);\n    for (int i = 0; i < M; ++i) cin >> G[i];\n\n    vector<int> lx(N), rx(N), ly(N), ry(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n    }\n\n    // estimated centre of each city\n    cx.resize(N);\n    cy.resize(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    // Morton code for spatial ordering (15 bits per coordinate, enough for 0..10000)\n    auto morton = [&](int x, int y) -> uint64_t {\n        uint64_t z = 0;\n        for (int i = 14; i >= 0; --i) {\n            z = (z << 2) | ((((x >> i) & 1) << 1) | ((y >> i) & 1));\n        }\n        return z;\n    };\n    vector<uint64_t> mort(N);\n    for (int i = 0; i < N; ++i) {\n        mort[i] = morton(cx[i], cy[i]);\n    }\n\n    // global order of cities\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int i, int j) { return mort[i] < mort[j]; });\n\n    // split the ordered cities into groups\n    vector<vector<int>> groups(M);\n    int cur = 0;\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < G[i]; ++j) {\n            groups[i].push_back(order[cur++]);\n        }\n    }\n\n    // for each group we build a spanning tree\n    vector<vector<int>> group_cities(M);\n    vector<vector<pair<int, int>>> group_edges(M);\n\n    for (int k = 0; k < M; ++k) {\n        const auto& nodes = groups[k];\n        int sz = (int)nodes.size();\n        if (sz == 0) continue;\n        if (sz == 1) {\n            group_cities[k] = nodes;\n            continue;\n        }\n\n        vector<pair<int, int>> edges;\n        int pos = 0;\n        while (pos < sz) {\n            if (q_used >= Q) {\n                // budget exhausted \u2013 connect remaining cities linearly\n                for (int i = pos; i < sz; ++i) {\n                    edges.emplace_back(nodes[i - 1], nodes[i]);\n                }\n                break;\n            }\n            if (pos == 0) {\n                int l = min(L, sz - pos);\n                vector<int> C(nodes.begin(), nodes.begin() + l);\n                auto res = query_subset(C);\n                edges.insert(edges.end(), res.begin(), res.end());\n                pos += l;\n            } else {\n                int anchor = nodes[pos - 1];\n                int take = min(L - 1, sz - pos);\n                vector<int> C = {anchor};\n                C.insert(C.end(), nodes.begin() + pos, nodes.begin() + pos + take);\n                auto res = query_subset(C);\n                edges.insert(edges.end(), res.begin(), res.end());\n                pos += take;\n            }\n        }\n        group_cities[k] = nodes;\n        group_edges[k] = move(edges);\n    }\n\n    // output final answer\n    cout << \"!\" << endl;\n    for (int k = 0; k < M; ++k) {\n        const auto& cities = group_cities[k];\n        for (int i = 0; i < (int)cities.size(); ++i) {\n            if (i) cout << \" \";\n            cout << cities[i];\n        }\n        cout << endl;\n        for (const auto& e : group_edges[k]) {\n            cout << e.first << \" \" << e.second << endl;\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <string>\n\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int N, M;\n    cin >> N >> M;\n    vector<int> R(M), C(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> R[i] >> C[i];\n    }\n\n    int total = N * N;\n    int S = total;          // represents \"no block\"\n    int state_size = total + 1;\n    int MAX_STATE = total * state_size;\n\n    // precompute row and column for each cell\n    vector<int> pr(total), pc(total);\n    for (int i = 0; i < total; ++i) {\n        pr[i] = i / N;\n        pc[i] = i % N;\n    }\n\n    vector<int> vis(MAX_STATE, 0);\n    vector<int> ps(MAX_STATE);\n    vector<int> pa(MAX_STATE);\n    vector<int> q(MAX_STATE);\n    int tok = 0;\n\n    vector<int> total_actions;\n\n    // process each segment: start -> target1, target1 -> target2, ...\n    for (int seg = 0; seg < M - 1; ++seg) {\n        int start_pos = R[seg] * N + C[seg];\n        int target_pos = R[seg+1] * N + C[seg+1];\n\n        ++tok;\n        int head = 0, tail = 0;\n        int start_state = start_pos * state_size + S;\n        vis[start_state] = tok;\n        ps[start_state] = -1;\n        q[tail++] = start_state;\n        int goal_state = -1;\n\n        while (head < tail) {\n            int s = q[head++];\n            int pos = s / state_size;\n            int block = s % state_size;\n            if (pos == target_pos && block == S) {\n                goal_state = s;\n                break;\n            }\n            int r = pr[pos], c = pc[pos];\n\n            for (int d = 0; d < 4; ++d) {\n                // --- Move ---\n                int nr = r, nc = c;\n                if (d == 0) nr--;\n                else if (d == 1) nr++;\n                else if (d == 2) nc--;\n                else nc++;\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                    int npos = nr * N + nc;\n                    if (npos != block) {\n                        int nstate = npos * state_size + block;\n                        if (vis[nstate] != tok) {\n                            vis[nstate] = tok;\n                            ps[nstate] = s;\n                            pa[nstate] = 0 * 4 + d;  // Move\n                            q[tail++] = nstate;\n                        }\n                    }\n                }\n\n                // --- Slide ---\n                int slide_pos;\n                if (block == S) {\n                    if (d == 0) slide_pos = c;                     // (0, c)\n                    else if (d == 1) slide_pos = (N-1)*N + c;      // (N-1, c)\n                    else if (d == 2) slide_pos = r * N;            // (r, 0)\n                    else slide_pos = r * N + (N-1);                // (r, N-1)\n                } else {\n                    int br = block / N, bc = block % N;\n                    if (d == 0) {  // up\n                        if (bc == c && br < r) slide_pos = (br + 1) * N + c;\n                        else slide_pos = c;\n                    } else if (d == 1) {  // down\n                        if (bc == c && br > r) slide_pos = (br - 1) * N + c;\n                        else slide_pos = (N-1)*N + c;\n                    } else if (d == 2) {  // left\n                        if (br == r && bc < c) slide_pos = r * N + (bc + 1);\n                        else slide_pos = r * N;\n                    } else {  // right\n                        if (br == r && bc > c) slide_pos = r * N + (bc - 1);\n                        else slide_pos = r * N + (N-1);\n                    }\n                }\n                int nstate_s = slide_pos * state_size + block;\n                if (vis[nstate_s] != tok) {\n                    vis[nstate_s] = tok;\n                    ps[nstate_s] = s;\n                    pa[nstate_s] = 1 * 4 + d;  // Slide\n                    q[tail++] = nstate_s;\n                }\n\n                // --- Alter ---\n                int adj_r = r, adj_c = c;\n                if (d == 0) adj_r--;\n                else if (d == 1) adj_r++;\n                else if (d == 2) adj_c--;\n                else adj_c++;\n                if (adj_r >= 0 && adj_r < N && adj_c >= 0 && adj_c < N) {\n                    int adj_id = adj_r * N + adj_c;\n                    if (block == S) {\n                        // place block\n                        int nstate = pos * state_size + adj_id;\n                        if (vis[nstate] != tok) {\n                            vis[nstate] = tok;\n                            ps[nstate] = s;\n                            pa[nstate] = 2 * 4 + d;  // Alter (place)\n                            q[tail++] = nstate;\n                        }\n                    } else {\n                        if (adj_id == block) {\n                            // remove block\n                            int nstate = pos * state_size + S;\n                            if (vis[nstate] != tok) {\n                                vis[nstate] = tok;\n                                ps[nstate] = s;\n                                pa[nstate] = 2 * 4 + d;  // Alter (remove)\n                                q[tail++] = nstate;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        // reconstruct action sequence for this segment\n        vector<int> seg_actions;\n        for (int s = goal_state; s != start_state; s = ps[s]) {\n            seg_actions.push_back(pa[s]);\n        }\n        reverse(seg_actions.begin(), seg_actions.end());\n        total_actions.insert(total_actions.end(), seg_actions.begin(), seg_actions.end());\n    }\n\n    // cancel consecutive identical Alter actions (place/remove pairs that do nothing)\n    vector<int> opt_actions;\n    for (int aid : total_actions) {\n        if (!opt_actions.empty() && opt_actions.back() == aid && (aid / 4) == 2) {\n            opt_actions.pop_back();\n        } else {\n            opt_actions.push_back(aid);\n        }\n    }\n    total_actions = move(opt_actions);\n\n    const char act_chars[3] = {'M', 'S', 'A'};\n    const char dir_chars[4] = {'U', 'D', 'L', 'R'};\n    for (int aid : total_actions) {\n        cout << act_chars[aid / 4] << ' ' << dir_chars[aid % 4] << '\\n';\n    }\n\n    return 0;\n}"},"2":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\nusing namespace chrono;\n\n// Fast random number generator\nstruct XorShift {\n    uint32_t x, y, z, w;\n    XorShift(uint32_t seed = 123456789) : x(seed), y(362436069), z(521288629), w(88675123) {\n        for (int i = 0; i < 10; i++) next();\n    }\n    uint32_t next() {\n        uint32_t t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = w ^ (w >> 19) ^ t ^ (t >> 8);\n    }\n    int nextInt(int max) {\n        if (max < 0) return 0;\n        return next() % (max + 1);\n    }\n    double nextDouble() {\n        return (double)(next() & 0xFFFFFF) / 0x1000000;\n    }\n};\n\nstruct Node {\n    int type;   // 0: leaf, 1: vertical cut, 2: horizontal cut\n    int leaf_id; // used when type == 0\n    int k;       // cut coordinate\n    int left, right;\n    int parent;\n    int min_k, max_k;   // allowed range for k\n    int x1, y1, x2, y2; // bounding box\n    vector<int> ids;    // leaf indices in this subtree (used only during construction)\n};\n\nint n;\nvector<int> x, y, r;\nvector<Node> nodes;\nint root;\nXorShift rng(system_clock::now().time_since_epoch().count());\n\n// Satisfaction for a single leaf\ndouble leaf_score(long long area, int r) {\n    double ratio = (area <= r) ? (double)area / r : (double)r / area;\n    return 2.0 * ratio - ratio * ratio;\n}\n\n// Recursively evaluate the slicing tree and update bounding boxes\ndouble evaluate(int idx, int x1, int y1, int x2, int y2) {\n    Node& node = nodes[idx];\n    node.x1 = x1; node.y1 = y1; node.x2 = x2; node.y2 = y2;\n    if (node.type == 0) {\n        long long area = (long long)(x2 - x1) * (y2 - y1);\n        return leaf_score(area, r[node.leaf_id]);\n    } else if (node.type == 1) { // vertical\n        int k = node.k;\n        return evaluate(node.left, x1, y1, k, y2) + evaluate(node.right, k, y1, x2, y2);\n    } else { // horizontal\n        int k = node.k;\n        return evaluate(node.left, x1, y1, x2, k) + evaluate(node.right, x1, k, x2, y2);\n    }\n}\n\n// Build greedy initial tree (recursive partitioning based on area matching)\nint buildGreedyTree(const vector<int>& pts, int x1, int y1, int x2, int y2, int parent) {\n    if (pts.size() == 1) {\n        int id = pts[0];\n        nodes.push_back({0, id, 0, -1, -1, parent, 0, 0, 0, 0, 0, 0, {id}});\n        return nodes.size() - 1;\n    }\n\n    long long sumR = 0;\n    for (int id : pts) sumR += r[id];\n\n    struct Candidate { int orient; int k; vector<int> left, right; double err; };\n    vector<Candidate> cands;\n\n    // Vertical cuts\n    vector<int> sorted = pts;\n    sort(sorted.begin(), sorted.end(), [&](int a, int b) { return x[a] < x[b]; });\n    long long left_sum = 0;\n    for (int i = 0; i < (int)sorted.size() - 1; i++) {\n        left_sum += r[sorted[i]];\n        double ideal_frac = (double)left_sum / sumR;\n        int min_k = x[sorted[i]] + 1;\n        int max_k = x[sorted[i + 1]];\n        if (min_k > max_k) continue;\n        int k = clamp((int)round(x1 + ideal_frac * (x2 - x1)), min_k, max_k);\n        double actual_frac = (double)(k - x1) / (x2 - x1);\n        double err = fabs(actual_frac - ideal_frac);\n        cands.push_back({1, k, vector<int>(sorted.begin(), sorted.begin() + i + 1),\n                         vector<int>(sorted.begin() + i + 1, sorted.end()), err});\n    }\n\n    // Horizontal cuts\n    sort(sorted.begin(), sorted.end(), [&](int a, int b) { return y[a] < y[b]; });\n    left_sum = 0;\n    for (int i = 0; i < (int)sorted.size() - 1; i++) {\n        left_sum += r[sorted[i]];\n        double ideal_frac = (double)left_sum / sumR;\n        int min_k = y[sorted[i]] + 1;\n        int max_k = y[sorted[i + 1]];\n        if (min_k > max_k) continue;\n        int k = clamp((int)round(y1 + ideal_frac * (y2 - y1)), min_k, max_k);\n        double actual_frac = (double)(k - y1) / (y2 - y1);\n        double err = fabs(actual_frac - ideal_frac);\n        cands.push_back({2, k, vector<int>(sorted.begin(), sorted.begin() + i + 1),\n                         vector<int>(sorted.begin() + i + 1, sorted.end()), err});\n    }\n\n    // Choose a candidate probabilistically (favor smaller error)\n    double min_err = 1e9;\n    for (auto& c : cands) if (c.err < min_err) min_err = c.err;\n    vector<double> weights(cands.size());\n    double sum_w = 0;\n    for (size_t i = 0; i < cands.size(); i++) {\n        weights[i] = exp(-(cands[i].err - min_err) * 100.0);\n        sum_w += weights[i];\n    }\n    double rv = rng.nextDouble() * sum_w;\n    int chosen_idx = 0;\n    double cum = 0;\n    for (size_t i = 0; i < cands.size(); i++) {\n        cum += weights[i];\n        if (cum >= rv) { chosen_idx = i; break; }\n    }\n    Candidate best = cands[chosen_idx];\n\n    nodes.push_back({best.orient, -1, best.k, -1, -1, parent, 0, 0, 0, 0, 0, 0, pts});\n    int idx = nodes.size() - 1;\n\n    int left_child, right_child;\n    if (best.orient == 1) {\n        left_child = buildGreedyTree(best.left, x1, y1, best.k, y2, idx);\n        right_child = buildGreedyTree(best.right, best.k, y1, x2, y2, idx);\n        int max_x_left = 0, min_x_right = 10000;\n        for (int id : best.left) max_x_left = max(max_x_left, x[id]);\n        for (int id : best.right) min_x_right = min(min_x_right, x[id]);\n        nodes[idx].min_k = max_x_left + 1;\n        nodes[idx].max_k = min_x_right;\n    } else {\n        left_child = buildGreedyTree(best.left, x1, y1, x2, best.k, idx);\n        right_child = buildGreedyTree(best.right, x1, best.k, x2, y2, idx);\n        int max_y_bottom = 0, min_y_top = 10000;\n        for (int id : best.left) max_y_bottom = max(max_y_bottom, y[id]);\n        for (int id : best.right) min_y_top = min(min_y_top, y[id]);\n        nodes[idx].min_k = max_y_bottom + 1;\n        nodes[idx].max_k = min_y_top;\n    }\n    nodes[idx].left = left_child;\n    nodes[idx].right = right_child;\n    return idx;\n}\n\n// Attempt to reorient an internal node (vertical <-> horizontal)\nbool tryReorient(int idx) {\n    Node& node = nodes[idx];\n    if (node.type == 0) return false;\n    vector<int> left_ids = nodes[node.left].ids;\n    vector<int> right_ids = nodes[node.right].ids;\n\n    if (node.type == 1) { // vertical -> horizontal\n        int max_y_left = -1, min_y_left = 10001;\n        int max_y_right = -1, min_y_right = 10001;\n        for (int id : left_ids) {\n            max_y_left = max(max_y_left, y[id]);\n            min_y_left = min(min_y_left, y[id]);\n        }\n        for (int id : right_ids) {\n            max_y_right = max(max_y_right, y[id]);\n            min_y_right = min(min_y_right, y[id]);\n        }\n        if (max_y_left < min_y_right) {\n            node.type = 2;\n            node.min_k = max_y_left + 1;\n            node.max_k = min_y_right;\n            node.k = node.min_k + rng.nextInt(node.max_k - node.min_k);\n            return true;\n        } else if (max_y_right < min_y_left) {\n            swap(node.left, node.right);\n            node.type = 2;\n            node.min_k = max_y_right + 1;\n            node.max_k = min_y_left;\n            node.k = node.min_k + rng.nextInt(node.max_k - node.min_k);\n            return true;\n        }\n    } else { // horizontal -> vertical\n        int max_x_left = -1, min_x_left = 10001;\n        int max_x_right = -1, min_x_right = 10001;\n        for (int id : left_ids) {\n            max_x_left = max(max_x_left, x[id]);\n            min_x_left = min(min_x_left, x[id]);\n        }\n        for (int id : right_ids) {\n            max_x_right = max(max_x_right, x[id]);\n            min_x_right = min(min_x_right, x[id]);\n        }\n        if (max_x_left < min_x_right) {\n            node.type = 1;\n            node.min_k = max_x_left + 1;\n            node.max_k = min_x_right;\n            node.k = node.min_k + rng.nextInt(node.max_k - node.min_k);\n            return true;\n        } else if (max_x_right < min_x_left) {\n            swap(node.left, node.right);\n            node.type = 1;\n            node.min_k = max_x_right + 1;\n            node.max_k = min_x_left;\n            node.k = node.min_k + rng.nextInt(node.max_k - node.min_k);\n            return true;\n        }\n    }\n    return false;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n;\n    x.resize(n); y.resize(n); r.resize(n);\n    for (int i = 0; i < n; i++) cin >> x[i] >> y[i] >> r[i];\n\n    double global_best_score = -1;\n    vector<Node> global_best_nodes;\n    int global_best_root = -1;\n    auto start_time = steady_clock::now();\n    auto time_left = [&]() -> bool {\n        return duration<double>(steady_clock::now() - start_time).count() > 4.8;\n    };\n\n    vector<int> active_nodes;\n    auto refresh_active = [&]() {\n        active_nodes.clear();\n        function<void(int)> dfs = [&](int idx) {\n            if (nodes[idx].type != 0) {\n                active_nodes.push_back(idx);\n                dfs(nodes[idx].left);\n                dfs(nodes[idx].right);\n            }\n        };\n        dfs(root);\n    };\n\n    const int iter_per_restart = 300000;\n    const double T_start = 1.0;\n    const double T_end = 1e-6;\n\n    while (!time_left()) {\n        // Build a fresh greedy tree\n        nodes.clear();\n        vector<int> all(n);\n        iota(all.begin(), all.end(), 0);\n        root = buildGreedyTree(all, 0, 0, 10000, 10000, -1);\n        refresh_active();\n        double current_score = evaluate(root, 0, 0, 10000, 10000);\n\n        double best_restart_score = current_score;\n        vector<Node> best_restart_nodes = nodes;\n        int best_restart_root = root;\n\n        for (int iter = 0; iter < iter_per_restart; iter++) {\n            if (iter % 100 == 0 && time_left()) break;\n            double progress = (double)iter / iter_per_restart;\n            double T = T_start * pow(T_end / T_start, progress);\n\n            if (active_nodes.empty()) break;\n\n            int move_type = rng.nextInt(99);\n            if (move_type < 20) { // reorient (20%)\n                int attempts = 10;\n                bool success = false;\n                Node saved_node;\n                int saved_left, saved_right;\n                int idx = -1;\n                for (int a = 0; a < attempts; a++) {\n                    idx = active_nodes[rng.nextInt(active_nodes.size() - 1)];\n                    saved_node = nodes[idx];\n                    saved_left = nodes[idx].left;\n                    saved_right = nodes[idx].right;\n                    if (tryReorient(idx)) { success = true; break; }\n                }\n                if (!success) continue;\n\n                double new_score = evaluate(root, 0, 0, 10000, 10000);\n                if (new_score > current_score || rng.nextDouble() < exp((new_score - current_score) / T)) {\n                    current_score = new_score;\n                    if (new_score > best_restart_score) {\n                        best_restart_score = new_score;\n                        best_restart_nodes = nodes;\n                        best_restart_root = root;\n                    }\n                } else {\n                    nodes[idx] = saved_node;\n                    nodes[idx].left = saved_left;\n                    nodes[idx].right = saved_right;\n                    evaluate(root, 0, 0, 10000, 10000);\n                }\n            } else { // change cut coordinate\n                int idx = active_nodes[rng.nextInt(active_nodes.size() - 1)];\n                int old_k = nodes[idx].k;\n                int min_k = nodes[idx].min_k;\n                int max_k = nodes[idx].max_k;\n                if (min_k == max_k) continue;\n                int new_k = min_k + rng.nextInt(max_k - min_k);\n                if (new_k == old_k) continue;\n\n                nodes[idx].k = new_k;\n                double new_score = evaluate(root, 0, 0, 10000, 10000);\n                if (new_score > current_score || rng.nextDouble() < exp((new_score - current_score) / T)) {\n                    current_score = new_score;\n                    if (new_score > best_restart_score) {\n                        best_restart_score = new_score;\n                        best_restart_nodes = nodes;\n                        best_restart_root = root;\n                    }\n                } else {\n                    nodes[idx].k = old_k;\n                    evaluate(root, 0, 0, 10000, 10000);\n                }\n            }\n        }\n\n        if (best_restart_score > global_best_score) {\n            global_best_score = best_restart_score;\n            global_best_nodes = best_restart_nodes;\n            global_best_root = best_restart_root;\n        }\n    }\n\n    // Final polishing: exhaustive enumeration for every cut coordinate\n    nodes = global_best_nodes;\n    root = global_best_root;\n    refresh_active();\n    double current_score = evaluate(root, 0, 0, 10000, 10000);\n    vector<int> internals = active_nodes;\n    for (int idx : internals) {\n        if (nodes[idx].min_k >= nodes[idx].max_k) continue;\n        int old_k = nodes[idx].k;\n        double best_local = current_score;\n        int best_k = old_k;\n        for (int k = nodes[idx].min_k; k <= nodes[idx].max_k; k++) {\n            if (k == old_k) continue;\n            nodes[idx].k = k;\n            double score = evaluate(root, 0, 0, 10000, 10000);\n            if (score > best_local) {\n                best_local = score;\n                best_k = k;\n            }\n        }\n        if (best_k != old_k) {\n            nodes[idx].k = best_k;\n            current_score = best_local;\n        } else {\n            nodes[idx].k = old_k;\n            evaluate(root, 0, 0, 10000, 10000);\n        }\n    }\n\n    // Store the best solution\n    global_best_score = current_score;\n    global_best_nodes = nodes;\n    global_best_root = root;\n\n    // Output\n    nodes = global_best_nodes;\n    root = global_best_root;\n    evaluate(root, 0, 0, 10000, 10000);\n    vector<tuple<int, int, int, int>> ans(n);\n    function<void(int)> collect = [&](int idx) {\n        Node& node = nodes[idx];\n        if (node.type == 0) {\n            ans[node.leaf_id] = {node.x1, node.y1, node.x2, node.y2};\n        } else {\n            collect(node.left);\n            collect(node.right);\n        }\n    };\n    collect(root);\n    for (auto [a, b, c, d] : ans) cout << a << \" \" << b << \" \" << c << \" \" << d << \"\\n\";\n\n    return 0;\n}","ahc002":"#include <iostream>\n#include <vector>\n#include <bitset>\n#include <queue>\n#include <algorithm>\n#include <chrono>\n#include <numeric>\n#include <unordered_map>\n#include <string>\nusing namespace std;\n\nconstexpr int N = 50;\nconstexpr int MAX_TILES = 2500;\n\nstruct State {\n    int parent_id;\n    unsigned short current_tile;\n    int score;\n    bitset<MAX_TILES> visited;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj;\n    cin >> si >> sj;\n\n    vector t(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> t[i][j];\n\n    vector p(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> p[i][j];\n\n    // --- Compute tiles ---\n    int M = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (t[i][j] > M) M = t[i][j];\n    M += 1;\n\n    vector<vector<pair<int,int>>> tile_sq(M);\n    vector<int> tile_weight(M, 0);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int id = t[i][j];\n            tile_sq[id].push_back({i, j});\n            tile_weight[id] += p[i][j];\n        }\n    }\n\n    // --- Adjacency and exit squares ---\n    const int dirs[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};\n    vector<vector<int>> adj(M);\n    vector<unordered_map<int, pair<int,int>>> exit_sq(M);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = t[i][j];\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + dirs[d][0], nj = j + dirs[d][1];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                int v = t[ni][nj];\n                if (u != v) {\n                    adj[u].push_back(v);\n                    if (exit_sq[u].find(v) == exit_sq[u].end()) {\n                        exit_sq[u][v] = {i, j};\n                    }\n                }\n            }\n        }\n    }\n    for (int i = 0; i < M; ++i) {\n        sort(adj[i].begin(), adj[i].end());\n        adj[i].erase(unique(adj[i].begin(), adj[i].end()), adj[i].end());\n    }\n\n    // --- Beam search ---\n    int start_tile = t[si][sj];\n    vector<State> states;\n    states.reserve(2000000);\n    State init;\n    init.parent_id = -1;\n    init.current_tile = start_tile;\n    init.visited.reset();\n    init.visited.set(start_tile);\n    init.score = tile_weight[start_tile];\n    states.push_back(init);\n    vector<int> cur = {0};\n    int best_id = 0;\n\n    const int BEAM_WIDTH = 700;\n    auto start_time = chrono::steady_clock::now();\n\n    while (!cur.empty()) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - start_time).count() > 1950) break;\n        if (states.size() > 2000000) break;\n\n        vector<int> nxt_cand;\n        nxt_cand.reserve(cur.size() * 4);\n        for (int id : cur) {\n            const State& st = states[id];\n            unsigned short u = st.current_tile;\n            for (unsigned short v : adj[u]) {\n                if (!st.visited[v]) {\n                    State ns = st;\n                    ns.visited.set(v);\n                    ns.score += tile_weight[v];\n                    ns.current_tile = v;\n                    ns.parent_id = id;\n                    nxt_cand.push_back(states.size());\n                    states.push_back(move(ns));\n                    if (states.back().score > states[best_id].score) {\n                        best_id = states.size() - 1;\n                    }\n                }\n            }\n        }\n        if (nxt_cand.empty()) break;\n\n        if ((int)nxt_cand.size() > BEAM_WIDTH) {\n            // Heuristic: current score + sum of weights of tiles within 2 steps\n            vector<long long> vals(nxt_cand.size());\n            for (size_t i = 0; i < nxt_cand.size(); ++i) {\n                int sid = nxt_cand[i];\n                const State& s = states[sid];\n                long long h = s.score;\n                vector<bool> vis_local(M, false);\n                queue<int> q;\n                q.push(s.current_tile);\n                vis_local[s.current_tile] = true;\n                for (int d = 0; d < 2; ++d) {\n                    int qsz = q.size();\n                    if (qsz == 0) break;\n                    for (int k = 0; k < qsz; ++k) {\n                        int uu = q.front(); q.pop();\n                        for (int vv : adj[uu]) {\n                            if (!s.visited[vv] && !vis_local[vv]) {\n                                vis_local[vv] = true;\n                                h += tile_weight[vv];\n                                q.push(vv);\n                            }\n                        }\n                    }\n                }\n                vals[i] = h;\n            }\n            vector<int> idx(nxt_cand.size());\n            iota(idx.begin(), idx.end(), 0);\n            sort(idx.begin(), idx.end(), [&](int i, int j) { return vals[i] > vals[j]; });\n            cur.clear();\n            cur.reserve(BEAM_WIDTH);\n            for (int i = 0; i < BEAM_WIDTH; ++i) {\n                cur.push_back(nxt_cand[idx[i]]);\n            }\n        } else {\n            cur = move(nxt_cand);\n        }\n    }\n\n    // --- Reconstruct tile sequence ---\n    vector<unsigned short> tile_seq;\n    for (int id = best_id; id != -1; id = states[id].parent_id) {\n        tile_seq.push_back(states[id].current_tile);\n    }\n    reverse(tile_seq.begin(), tile_seq.end());\n\n    // --- Generate path string ---\n    string ans;\n    int x = si, y = sj;\n    vector vis(N, vector<bool>(N, false));\n    vis[x][y] = true;\n\n    auto get_move = [&](int x1, int y1, int x2, int y2) -> string {\n        if (x2 == x1 - 1) return \"U\";\n        if (x2 == x1 + 1) return \"D\";\n        if (y2 == y1 - 1) return \"L\";\n        if (y2 == y1 + 1) return \"R\";\n        return \"\";\n    };\n\n    for (size_t idx = 0; idx < tile_seq.size(); ++idx) {\n        unsigned short t = tile_seq[idx];\n        auto& sqs = tile_sq[t];\n        // Visit all squares inside the current tile\n        if (sqs.size() == 2) {\n            auto [r0, c0] = sqs[0];\n            auto [r1, c1] = sqs[1];\n            bool v0 = vis[r0][c0], v1 = vis[r1][c1];\n            if (!v0 || !v1) {\n                auto [ur, uc] = v0 ? sqs[1] : sqs[0];\n                ans += get_move(x, y, ur, uc);\n                x = ur; y = uc;\n                vis[x][y] = true;\n            }\n        }\n        // If not the last tile, move to exit square and then to the next tile\n        if (idx != tile_seq.size() - 1) {\n            unsigned short nxt = tile_seq[idx + 1];\n            auto [ex, ey] = exit_sq[t][nxt];\n            if (x != ex || y != ey) {\n                ans += get_move(x, y, ex, ey);\n                x = ex; y = ey;\n                vis[x][y] = true;\n            }\n            int nx = -1, ny = -1;\n            for (int d = 0; d < 4; ++d) {\n                int ni = x + dirs[d][0], nj = y + dirs[d][1];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N && t[ni][nj] == nxt) {\n                    nx = ni; ny = nj;\n                    break;\n                }\n            }\n            if (nx != -1) {\n                ans += get_move(x, y, nx, ny);\n                x = nx; y = ny;\n                vis[x][y] = true;\n            } else {\n                break; // should not happen\n            }\n        }\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int N = 30;\nconstexpr int H_EDGES = N * (N - 1);   // 870\nconstexpr int V_EDGES = (N - 1) * N;   // 870\nconstexpr int E = H_EDGES + V_EDGES;   // 1740\n\n// edge index for horizontal edge between (i,j) and (i,j+1)\nint edge_idx_horiz(int i, int j) { return i * (N - 1) + j; }\n// edge index for vertical edge between (i,j) and (i+1,j)\nint edge_idx_vert(int i, int j) { return H_EDGES + i * N + j; }\n\n// Dijkstra returning move string and edges traversed\nstring dijkstra(int si, int sj, int ti, int tj,\n                const vector<double>& w_plan,\n                const vector<int>& cnt,\n                double alpha,\n                mt19937& rng,\n                vector<int>& path_edges) {\n    int start = si * N + sj;\n    int goal = ti * N + tj;\n\n    vector<double> dist(N * N, 1e18);\n    vector<int> parent(N * N, -1);\n    vector<int> parent_edge(N * N, -1);\n    dist[start] = 0;\n\n    using P = pair<double, int>;\n    priority_queue<P, vector<P>, greater<P>> pq;\n    pq.push({0, start});\n\n    uniform_real_distribution<double> noise(-0.5, 0.5);\n\n    // adjacency\n    static vector<vector<pair<int, int>>> adj;\n    if (adj.empty()) {\n        adj.resize(N * N);\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (j < N - 1) {\n                    int u = i * N + j, v = i * N + j + 1;\n                    int e = edge_idx_horiz(i, j);\n                    adj[u].push_back({v, e});\n                    adj[v].push_back({u, e});\n                }\n                if (i < N - 1) {\n                    int u = i * N + j, v = (i + 1) * N + j;\n                    int e = edge_idx_vert(i, j);\n                    adj[u].push_back({v, e});\n                    adj[v].push_back({u, e});\n                }\n            }\n        }\n    }\n\n    while (!pq.empty()) {\n        auto [d, u] = pq.top(); pq.pop();\n        if (d != dist[u]) continue;\n        if (u == goal) break;\n        for (auto [v, e] : adj[u]) {\n            double w_mod = w_plan[e] - alpha / sqrt(cnt[e] + 1.0);\n            if (w_mod < 1.0) w_mod = 1.0;\n            double nd = d + w_mod + noise(rng) * 0.1;\n            if (nd < dist[v]) {\n                dist[v] = nd;\n                parent[v] = u;\n                parent_edge[v] = e;\n                pq.push({nd, v});\n            }\n        }\n    }\n\n    // reconstruct\n    path_edges.clear();\n    vector<int> nodes;\n    for (int cur = goal; cur != start; cur = parent[cur]) {\n        nodes.push_back(cur);\n        path_edges.push_back(parent_edge[cur]);\n    }\n    nodes.push_back(start);\n    reverse(nodes.begin(), nodes.end());\n    reverse(path_edges.begin(), path_edges.end());\n\n    string moves;\n    for (size_t i = 0; i + 1 < nodes.size(); ++i) {\n        int u = nodes[i], v = nodes[i + 1];\n        int ui = u / N, uj = u % N;\n        int vi = v / N, vj = v % N;\n        if (vi == ui - 1) moves += 'U';\n        else if (vi == ui + 1) moves += 'D';\n        else if (vj == uj - 1) moves += 'L';\n        else moves += 'R';\n    }\n    return moves;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    vector<double> w(E, 5000.0);\n    vector<double> w_plan = w;\n    vector<int> cnt(E, 0);\n    vector<double> row_h_mean(N, 5000.0);\n    vector<double> col_v_mean(N, 5000.0);\n\n    mt19937 rng(12345);\n    double alpha_explore = 2000.0;\n    double base_lr = 800.0;\n    double reg_coeff = 0.0005;\n\n    auto clamp = [](double v, double lo, double hi) {\n        return max(lo, min(hi, v));\n    };\n\n    auto recompute_means = [&]() {\n        for (int i = 0; i < N; ++i) {\n            double s = 0;\n            for (int j = 0; j < N - 1; ++j) s += w[edge_idx_horiz(i, j)];\n            row_h_mean[i] = s / (N - 1);\n        }\n        for (int j = 0; j < N; ++j) {\n            double s = 0;\n            for (int i = 0; i < N - 1; ++i) s += w[edge_idx_vert(i, j)];\n            col_v_mean[j] = s / (N - 1);\n        }\n    };\n\n    auto segment_rows = [&]() {\n        for (int i = 0; i < N; ++i) {\n            vector<double> a(N - 1);\n            for (int j = 0; j < N - 1; ++j) a[j] = w[edge_idx_horiz(i, j)];\n            double sum_total = accumulate(a.begin(), a.end(), 0.0);\n            double mean_all = sum_total / (N - 1);\n            double sse0 = 0;\n            for (double x : a) sse0 += (x - mean_all) * (x - mean_all);\n            double best_sse = sse0;\n            int best_x = -1;\n            double best_meanL = mean_all, best_meanR = mean_all;\n            double sum_left = 0;\n            for (int x = 1; x < N - 1; ++x) {\n                sum_left += a[x - 1];\n                double meanL = sum_left / x;\n                double sum_right = sum_total - sum_left;\n                double meanR = sum_right / (N - 1 - x);\n                double sse = 0;\n                for (int j = 0; j < x; ++j) sse += (a[j] - meanL) * (a[j] - meanL);\n                for (int j = x; j < N - 1; ++j) sse += (a[j] - meanR) * (a[j] - meanR);\n                if (sse < best_sse) {\n                    best_sse = sse;\n                    best_x = x;\n                    best_meanL = meanL;\n                    best_meanR = meanR;\n                }\n            }\n            if (best_sse < sse0 * 0.95) {\n                for (int j = 0; j < best_x; ++j) w[edge_idx_horiz(i, j)] = best_meanL;\n                for (int j = best_x; j < N - 1; ++j) w[edge_idx_horiz(i, j)] = best_meanR;\n            } else {\n                for (int j = 0; j < N - 1; ++j) w[edge_idx_horiz(i, j)] = mean_all;\n            }\n        }\n    };\n\n    auto segment_cols = [&]() {\n        for (int j = 0; j < N; ++j) {\n            vector<double> a(N - 1);\n            for (int i = 0; i < N - 1; ++i) a[i] = w[edge_idx_vert(i, j)];\n            double sum_total = accumulate(a.begin(), a.end(), 0.0);\n            double mean_all = sum_total / (N - 1);\n            double sse0 = 0;\n            for (double x : a) sse0 += (x - mean_all) * (x - mean_all);\n            double best_sse = sse0;\n            int best_x = -1;\n            double best_meanL = mean_all, best_meanR = mean_all;\n            double sum_left = 0;\n            for (int x = 1; x < N - 1; ++x) {\n                sum_left += a[x - 1];\n                double meanL = sum_left / x;\n                double sum_right = sum_total - sum_left;\n                double meanR = sum_right / (N - 1 - x);\n                double sse = 0;\n                for (int i = 0; i < x; ++i) sse += (a[i] - meanL) * (a[i] - meanL);\n                for (int i = x; i < N - 1; ++i) sse += (a[i] - meanR) * (a[i] - meanR);\n                if (sse < best_sse) {\n                    best_sse = sse;\n                    best_x = x;\n                    best_meanL = meanL;\n                    best_meanR = meanR;\n                }\n            }\n            if (best_sse < sse0 * 0.95) {\n                for (int i = 0; i < best_x; ++i) w[edge_idx_vert(i, j)] = best_meanL;\n                for (int i = best_x; i < N - 1; ++i) w[edge_idx_vert(i, j)] = best_meanR;\n            } else {\n                for (int i = 0; i < N - 1; ++i) w[edge_idx_vert(i, j)] = mean_all;\n            }\n        }\n    };\n\n    for (int k = 0; k < 1000; ++k) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n\n        vector<int> path_edges;\n        string moves = dijkstra(si, sj, ti, tj, w_plan, cnt, alpha_explore, rng, path_edges);\n        cout << moves << endl; // flushes\n\n        int obs;\n        cin >> obs;\n\n        double pred = 0;\n        for (int e : path_edges) pred += w[e];\n\n        double lr_decay = 1.0 / (1.0 + k * 0.005);\n        double lr_abs = base_lr / (pred + 1.0) * lr_decay;\n\n        for (int e : path_edges) {\n            double mean;\n            if (e < H_EDGES) {\n                int i = e / (N - 1);\n                mean = row_h_mean[i];\n            } else {\n                int idx = e - H_EDGES;\n                int j = idx % N;\n                mean = col_v_mean[j];\n            }\n            double grad = pred - obs;\n            double reg = w[e] - mean;\n            w[e] -= lr_abs * grad + reg_coeff * reg;\n            w[e] = clamp(w[e], 1000.0, 9000.0);\n            cnt[e]++;\n        }\n\n        recompute_means();\n\n        double rho = 0.05;\n        for (int e = 0; e < E; ++e)\n            w_plan[e] = (1 - rho) * w_plan[e] + rho * w[e];\n\n        alpha_explore = max(0.0, alpha_explore - 2.0);\n\n        if ((k + 1) % 100 == 0 && k >= 99) {\n            segment_rows();\n            segment_cols();\n            recompute_means();\n            for (int e = 0; e < E; ++e) w_plan[e] = w[e];\n        }\n    }\n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <numeric>\n#include <chrono>\n#include <cmath>\n#include <cstring>\n#include <cstdint>\n\nusing namespace std;\n\nconstexpr int N = 20;\n\nstruct XorShift {\n    uint32_t x;\n    XorShift(uint32_t seed) : x(seed) {}\n    uint32_t next() {\n        x ^= x << 13;\n        x ^= x >> 17;\n        x ^= x << 5;\n        return x;\n    }\n    int nextInt(int max) {\n        return next() % max;\n    }\n    double nextDouble() {\n        return (next() >> 8) * 0x1p-24;\n    }\n};\n\nint M;\nvector<string> strs;\nvector<int> len;\nvector<uint8_t> h_match_count, v_match_count, h_count, v_count;\nvector<int16_t> s_count;\nint c_total;\nchar grid[N][N];\n\nvoid init_match_arrays() {\n    h_match_count.assign(M * N * N, 0);\n    v_match_count.assign(M * N * N, 0);\n    h_count.assign(M * N, 0);\n    v_count.assign(M * N, 0);\n    s_count.assign(M, 0);\n    c_total = 0;\n}\n\nvoid compute_all_matches() {\n    fill(h_match_count.begin(), h_match_count.end(), 0);\n    fill(v_match_count.begin(), v_match_count.end(), 0);\n    fill(h_count.begin(), h_count.end(), 0);\n    fill(v_count.begin(), v_count.end(), 0);\n    fill(s_count.begin(), s_count.end(), 0);\n    c_total = 0;\n\n    for (int i = 0; i < M; ++i) {\n        int L = len[i];\n        const string& s = strs[i];\n        int total = 0;\n        // horizontal\n        for (int r = 0; r < N; ++r) {\n            int h_cnt = 0;\n            for (int start = 0; start < N; ++start) {\n                int cnt = 0;\n                for (int pos = 0; pos < L; ++pos) {\n                    if (grid[r][(start+pos)%N] == s[pos]) cnt++;\n                }\n                h_match_count[i * N * N + r * N + start] = cnt;\n                if (cnt == L) h_cnt++;\n            }\n            h_count[i * N + r] = h_cnt;\n            total += h_cnt;\n        }\n        // vertical\n        for (int c = 0; c < N; ++c) {\n            int v_cnt = 0;\n            for (int start = 0; start < N; ++start) {\n                int cnt = 0;\n                for (int pos = 0; pos < L; ++pos) {\n                    if (grid[(start+pos)%N][c] == s[pos]) cnt++;\n                }\n                v_match_count[i * N * N + c * N + start] = cnt;\n                if (cnt == L) v_cnt++;\n            }\n            v_count[i * N + c] = v_cnt;\n            total += v_cnt;\n        }\n        s_count[i] = total;\n        if (total > 0) c_total++;\n    }\n}\n\nint count_matched(const char g[N][N]) {\n    int cnt = 0;\n    for (int i = 0; i < M; ++i) {\n        const string& s = strs[i];\n        int L = len[i];\n        bool found = false;\n        for (int r = 0; r < N && !found; ++r) {\n            for (int start = 0; start < N && !found; ++start) {\n                bool ok = true;\n                for (int pos = 0; pos < L; ++pos) {\n                    if (g[r][(start+pos)%N] != s[pos]) { ok=false; break; }\n                }\n                if (ok) found = true;\n            }\n        }\n        for (int c = 0; c < N && !found; ++c) {\n            for (int start = 0; start < N && !found; ++start) {\n                bool ok = true;\n                for (int pos = 0; pos < L; ++pos) {\n                    if (g[(start+pos)%N][c] != s[pos]) { ok=false; break; }\n                }\n                if (ok) found = true;\n            }\n        }\n        if (found) cnt++;\n    }\n    return cnt;\n}\n\nint count_dots(const char g[N][N]) {\n    int d = 0;\n    for (int i=0; i<N; ++i) for (int j=0; j<N; ++j) if (g[i][j] == '.') d++;\n    return d;\n}\n\nvoid flip(int r, int c, char new_char) {\n    char old_char = grid[r][c];\n    if (old_char == new_char) return;\n    for (int i = 0; i < M; ++i) {\n        int L = len[i];\n        const string& s = strs[i];\n        // horizontal\n        int h_base = i * N * N + r * N;\n        int h_count_base = i * N + r;\n        for (int offset = 0; offset < L; ++offset) {\n            int start = (c - offset + N) % N;\n            bool old_contrib = (old_char == s[offset]);\n            bool new_contrib = (new_char == s[offset]);\n            int diff = (new_contrib ? 1 : 0) - (old_contrib ? 1 : 0);\n            if (diff != 0) {\n                int idx = h_base + start;\n                int old_cnt = h_match_count[idx];\n                int new_cnt = old_cnt + diff;\n                h_match_count[idx] = new_cnt;\n                bool was = (old_cnt == L);\n                bool is = (new_cnt == L);\n                if (was != is) {\n                    if (is) {\n                        h_count[h_count_base]++;\n                        s_count[i]++;\n                        if (s_count[i] == 1) c_total++;\n                    } else {\n                        h_count[h_count_base]--;\n                        s_count[i]--;\n                        if (s_count[i] == 0) c_total--;\n                    }\n                }\n            }\n        }\n        // vertical\n        int v_base = i * N * N + c * N;\n        int v_count_base = i * N + c;\n        for (int offset = 0; offset < L; ++offset) {\n            int start = (r - offset + N) % N;\n            bool old_contrib = (old_char == s[offset]);\n            bool new_contrib = (new_char == s[offset]);\n            int diff = (new_contrib ? 1 : 0) - (old_contrib ? 1 : 0);\n            if (diff != 0) {\n                int idx = v_base + start;\n                int old_cnt = v_match_count[idx];\n                int new_cnt = old_cnt + diff;\n                v_match_count[idx] = new_cnt;\n                bool was = (old_cnt == L);\n                bool is = (new_cnt == L);\n                if (was != is) {\n                    if (is) {\n                        v_count[v_count_base]++;\n                        s_count[i]++;\n                        if (s_count[i] == 1) c_total++;\n                    } else {\n                        v_count[v_count_base]--;\n                        s_count[i]--;\n                        if (s_count[i] == 0) c_total--;\n                    }\n                }\n            }\n        }\n    }\n    grid[r][c] = new_char;\n}\n\nint main() {\n    ios::sync_with_stdio(false); cin.tie(0);\n    auto start_time = chrono::steady_clock::now();\n    auto get_time = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n\n    cin >> N >> M; // N is fixed to 20\n    N = 20;\n    strs.resize(M);\n    len.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> strs[i];\n        len[i] = strs[i].size();\n    }\n\n    XorShift rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    // --- greedy construction ---\n    double greedy_time_limit = 0.5;\n    char best_grid[N][N];\n    int best_c = -1;\n    int best_d = 0;\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    char cur_grid[N][N];\n\n    struct Placement {\n        int ori; // 0 horizontal, 1 vertical\n        int rc;  // row or column index\n        int start;\n        int overlap;\n    };\n    vector<Placement> valid;\n    valid.reserve(800);\n\n    while (get_time() < greedy_time_limit) {\n        memset(cur_grid, '.', sizeof(cur_grid));\n        for (int i = M-1; i > 0; --i) swap(order[i], order[rng.nextInt(i+1)]);\n        for (int idx : order) {\n            const string& s = strs[idx];\n            int L = len[idx];\n            valid.clear();\n            // horizontal\n            for (int r = 0; r < N; ++r) {\n                for (int start = 0; start < N; ++start) {\n                    int overlap = 0;\n                    bool ok = true;\n                    for (int pos = 0; pos < L; ++pos) {\n                        int c = (start+pos)%N;\n                        if (cur_grid[r][c] != '.' && cur_grid[r][c] != s[pos]) {\n                            ok = false; break;\n                        }\n                        if (cur_grid[r][c] != '.') overlap++;\n                    }\n                    if (ok) valid.push_back({0, r, start, overlap});\n                }\n            }\n            // vertical\n            for (int c = 0; c < N; ++c) {\n                for (int start = 0; start < N; ++start) {\n                    int overlap = 0;\n                    bool ok = true;\n                    for (int pos = 0; pos < L; ++pos) {\n                        int r = (start+pos)%N;\n                        if (cur_grid[r][c] != '.' && cur_grid[r][c] != s[pos]) {\n                            ok = false; break;\n                        }\n                        if (cur_grid[r][c] != '.') overlap++;\n                    }\n                    if (ok) valid.push_back({1, c, start, overlap});\n                }\n            }\n            if (valid.empty()) continue;\n            int max_overlap = -1;\n            for (auto& p : valid) if (p.overlap > max_overlap) max_overlap = p.overlap;\n            vector<Placement*> candidates;\n            for (auto& p : valid) if (p.overlap == max_overlap) candidates.push_back(&p);\n            Placement& chosen = *candidates[rng.nextInt(candidates.size())];\n            if (chosen.ori == 0) {\n                int r = chosen.rc;\n                int start = chosen.start;\n                for (int pos = 0; pos < L; ++pos) cur_grid[r][(start+pos)%N] = s[pos];\n            } else {\n                int c = chosen.rc;\n                int start = chosen.start;\n                for (int pos = 0; pos < L; ++pos) cur_grid[(start+pos)%N][c] = s[pos];\n            }\n        }\n        int actual_c = count_matched(cur_grid);\n        int d = count_dots(cur_grid);\n        if (actual_c > best_c || (actual_c == best_c && d > best_d)) {\n            best_c = actual_c;\n            best_d = d;\n            memcpy(best_grid, cur_grid, sizeof(best_grid));\n        }\n        if (best_c == M) break;\n    }\n\n    char overall_best_grid[N][N];\n    int overall_best_c = best_c;\n    int overall_best_d = best_d;\n    memcpy(overall_best_grid, best_grid, sizeof(best_grid));\n\n    // --- SA phase when c < M ---\n    if (overall_best_c < M) {\n        memcpy(grid, best_grid, sizeof(grid));\n        for (int i=0; i<N; ++i)\n            for (int j=0; j<N; ++j)\n                if (grid[i][j] == '.')\n                    grid[i][j] = \"ABCDEFGH\"[rng.nextInt(8)];\n\n        init_match_arrays();\n        compute_all_matches();\n        int best_c_sa = c_total;\n        char best_grid_sa[N][N];\n        memcpy(best_grid_sa, grid, sizeof(grid));\n\n        double T_start = 1.0;\n        double T_end = 0.001;\n        int max_steps = 200000;\n        double cool_rate = pow(T_end / T_start, 1.0 / max_steps);\n        double T = T_start;\n        double sa_time_limit = 2.9;\n        int step = 0;\n\n        while (get_time() < sa_time_limit && step < max_steps && c_total < M) {\n            int r = rng.nextInt(N);\n            int c = rng.nextInt(N);\n            char old_char = grid[r][c];\n            char new_char = \"ABCDEFGH\"[rng.nextInt(8)];\n            if (new_char == old_char) continue;\n            int old_c = c_total;\n            flip(r, c, new_char);\n            int new_c = c_total;\n            int delta = new_c - old_c;\n            if (delta >= 0) {\n                if (new_c > best_c_sa) {\n                    best_c_sa = new_c;\n                    memcpy(best_grid_sa, grid, sizeof(grid));\n                }\n            } else {\n                double prob = exp(delta / T);\n                if (rng.nextDouble() < prob) {\n                    // accept\n                } else {\n                    flip(r, c, old_char); // revert\n                }\n            }\n            T *= cool_rate;\n            ++step;\n            if (c_total == M) {\n                best_c_sa = M;\n                memcpy(best_grid_sa, grid, sizeof(grid));\n                break;\n            }\n        }\n        if (best_c_sa > overall_best_c) {\n            overall_best_c = best_c_sa;\n            overall_best_d = 0;\n            memcpy(overall_best_grid, best_grid_sa, sizeof(best_grid_sa));\n        }\n    }\n\n    // --- dot optimization if all strings are matched ---\n    if (overall_best_c == M) {\n        memcpy(grid, overall_best_grid, sizeof(grid));\n        init_match_arrays();\n        compute_all_matches();\n        vector<pair<int,int>> cells;\n        cells.reserve(N*N);\n        for (int i=0; i<N; ++i) for (int j=0; j<N; ++j) if (grid[i][j] != '.') cells.emplace_back(i,j);\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            for (int i = cells.size()-1; i>0; --i) swap(cells[i], cells[rng.nextInt(i+1)]);\n            for (auto& p : cells) {\n                int r = p.first, c = p.second;\n                if (grid[r][c] == '.') continue;\n                char old = grid[r][c];\n                flip(r, c, '.');\n                if (c_total == M) {\n                    changed = true;\n                } else {\n                    flip(r, c, old);\n                }\n            }\n        }\n        memcpy(overall_best_grid, grid, sizeof(grid));\n    }\n\n    // output\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) cout << overall_best_grid[i][j];\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int N, si, sj;\n    cin >> N >> si >> sj;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n\n    // Assign IDs to road cells\n    vector<vector<int>> id(N, vector<int>(N, -1));\n    vector<pair<int, int>> cells;\n    vector<int> cell_cost;\n    int r = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != '#') {\n                id[i][j] = r;\n                cells.emplace_back(i, j);\n                cell_cost.push_back(grid[i][j] - '0');\n                r++;\n            }\n        }\n    }\n\n    // Adjacency list: each edge (v, w) where w is cost of entering v\n    vector<vector<pair<int, int>>> adj(r);\n    const int di[4] = {-1, 1, 0, 0};\n    const int dj[4] = {0, 0, -1, 1};\n    for (int u = 0; u < r; ++u) {\n        int i = cells[u].first, j = cells[u].second;\n        for (int d = 0; d < 4; ++d) {\n            int ni = i + di[d], nj = j + dj[d];\n            if (ni >= 0 && ni < N && nj >= 0 && nj < N && id[ni][nj] != -1) {\n                int v = id[ni][nj];\n                int w = cell_cost[v];\n                adj[u].emplace_back(v, w);\n            }\n        }\n    }\n\n    // Horizontal segments (rows)\n    vector<int> h_id(r, -1);\n    int H_count = 0;\n    vector<int> h_ep1, h_ep2; // endpoints\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ) {\n            if (id[i][j] != -1) {\n                int start_j = j;\n                while (j < N && id[i][j] != -1) {\n                    h_id[id[i][j]] = H_count;\n                    j++;\n                }\n                int end_j = j - 1;\n                h_ep1.push_back(id[i][start_j]);\n                h_ep2.push_back(id[i][end_j]);\n                H_count++;\n            } else {\n                j++;\n            }\n        }\n    }\n\n    // Vertical segments (columns)\n    vector<int> v_id(r, -1);\n    int V_count = 0;\n    vector<int> v_ep1, v_ep2;\n    for (int j = 0; j < N; ++j) {\n        for (int i = 0; i < N; ) {\n            if (id[i][j] != -1) {\n                int start_i = i;\n                while (i < N && id[i][j] != -1) {\n                    v_id[id[i][j]] = V_count;\n                    i++;\n                }\n                int end_i = i - 1;\n                v_ep1.push_back(id[start_i][j]);\n                v_ep2.push_back(id[end_i][j]);\n                V_count++;\n            } else i++;\n        }\n    }\n\n    int total_seg = H_count + V_count;\n\n    // Candidate set: start + all segment endpoints\n    set<int> cand_set;\n    cand_set.insert(id[si][sj]);\n    for (int x : h_ep1) cand_set.insert(x);\n    for (int x : h_ep2) cand_set.insert(x);\n    for (int x : v_ep1) cand_set.insert(x);\n    for (int x : v_ep2) cand_set.insert(x);\n    vector<int> P(cand_set.begin(), cand_set.end());\n    int P_sz = P.size();\n\n    // For each candidate, list of segments it covers (h_id and v_id with offset)\n    vector<vector<int>> seg_cover(P_sz);\n    for (int i = 0; i < P_sz; ++i) {\n        int cid = P[i];\n        seg_cover[i].push_back(h_id[cid]);\n        seg_cover[i].push_back(H_count + v_id[cid]);\n    }\n\n    // Greedy set cover, starting with start cell\n    int start_cid = id[si][sj];\n    int start_idx = -1;\n    for (int i = 0; i < P_sz; ++i) if (P[i] == start_cid) { start_idx = i; break; }\n\n    vector<bool> covered(total_seg, false);\n    vector<int> selected;\n    if (start_idx != -1) {\n        selected.push_back(start_idx);\n        for (int seg : seg_cover[start_idx]) covered[seg] = true;\n    }\n    int uncovered = 0;\n    for (bool b : covered) if (!b) uncovered++;\n\n    while (uncovered > 0) {\n        int best_idx = -1, best_gain = 0;\n        for (int i = 0; i < P_sz; ++i) {\n            if (find(selected.begin(), selected.end(), i) != selected.end()) continue;\n            int gain = 0;\n            for (int seg : seg_cover[i]) if (!covered[seg]) gain++;\n            if (gain > best_gain) {\n                best_gain = gain;\n                best_idx = i;\n            }\n        }\n        if (best_gain == 0) break; // safety\n        selected.push_back(best_idx);\n        for (int seg : seg_cover[best_idx]) {\n            if (!covered[seg]) { covered[seg] = true; uncovered--; }\n        }\n    }\n\n    // Prune redundant waypoints\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        for (size_t i = 0; i < selected.size(); ++i) {\n            if (P[selected[i]] == start_cid) continue;\n            vector<bool> cov_without(total_seg, false);\n            for (size_t j = 0; j < selected.size(); ++j) {\n                if (i == j) continue;\n                for (int seg : seg_cover[selected[j]]) cov_without[seg] = true;\n            }\n            bool needed = false;\n            for (int seg : seg_cover[selected[i]]) if (!cov_without[seg]) { needed = true; break; }\n            if (!needed) {\n                selected.erase(selected.begin() + i);\n                changed = true;\n                break;\n            }\n        }\n    }\n\n    // Ensure start is first\n    if (selected.empty() || P[selected[0]] != start_cid) {\n        auto it = find(selected.begin(), selected.end(), start_idx);\n        if (it != selected.end()) {\n            int pos = it - selected.begin();\n            swap(selected[0], selected[pos]);\n        } else {\n            selected.insert(selected.begin(), start_idx);\n        }\n    }\n\n    // C: cell ids of chosen waypoints\n    vector<int> C;\n    for (int idx : selected) C.push_back(P[idx]);\n    int K = C.size();\n\n    if (K == 1) {\n        cout << \"\" << \"\\n\";\n        return 0;\n    }\n\n    // Distance matrix D (directed costs)\n    const int INF = 1e9;\n    vector<vector<int>> D(K, vector<int>(K, 0));\n\n    // Dijkstra (Dial's algorithm) for directed shortest paths\n    auto dijkstra = [&](int src, vector<int>& dist, vector<int>& prev) {\n        dist.assign(r, INF);\n        prev.assign(r, -1);\n        vector<queue<int>> buckets(10);\n        dist[src] = 0;\n        buckets[0].push(src);\n        int max_d = 0, cur_d = 0;\n        while (cur_d <= max_d) {\n            int idx = cur_d % 10;\n            if (!buckets[idx].empty()) {\n                int u = buckets[idx].front(); buckets[idx].pop();\n                if (dist[u] < cur_d) continue;\n                for (auto& p : adj[u]) {\n                    int v = p.first, w = p.second;\n                    int nd = dist[u] + w;\n                    if (nd < dist[v]) {\n                        dist[v] = nd;\n                        prev[v] = u;\n                        buckets[nd % 10].push(v);\n                        if (nd > max_d) max_d = nd;\n                    }\n                }\n            } else {\n                cur_d++;\n            }\n        }\n    };\n\n    // Build D\n    for (int i = 0; i < K; ++i) {\n        vector<int> dist, prev;\n        dijkstra(C[i], dist, prev);\n        for (int j = 0; j < K; ++j) D[i][j] = dist[C[j]];\n    }\n\n    // Build initial ATSP tour using nearest neighbour\n    vector<int> tour(K);\n    vector<bool> used(K, false);\n    tour[0] = 0; used[0] = true;\n    for (int pos = 1; pos < K; ++pos) {\n        int last = tour[pos - 1];\n        int best = -1, best_d = INF;\n        for (int nxt = 0; nxt < K; ++nxt) {\n            if (!used[nxt] && D[last][nxt] < best_d) {\n                best_d = D[last][nxt];\n                best = nxt;\n            }\n        }\n        tour[pos] = best;\n        used[best] = true;\n    }\n\n    // 2-opt improvement for asymmetric TSP (segment reversal)\n    auto eval_tour = [&](const vector<int>& t) {\n        int sum = 0;\n        for (int i = 0; i < K; ++i) sum += D[t[i]][t[(i+1)%K]];\n        return sum;\n    };\n\n    int best_cost = eval_tour(tour);\n    if (K <= 400) { // only run 2-opt for moderate K\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            for (int i = 0; i < K; ++i) {\n                for (int j = i + 2; j < K; ++j) {\n                    if (i == 0 && j == K - 1) continue; // not reversing the whole tour\n                    int a = tour[i], b = tour[(i+1)%K], c = tour[j], d = tour[(j+1)%K];\n                    // Simple delta calculation with prefix sums to avoid O(K) per move\n                    // For simplicity and given K is small, we just do O(K) evaluator:\n                    vector<int> nt = tour;\n                    reverse(nt.begin() + i + 1, nt.begin() + j + 1);\n                    int new_cost = eval_tour(nt);\n                    if (new_cost < best_cost) {\n                        tour = nt;\n                        best_cost = new_cost;\n                        improved = true;\n                        // restart loops\n                        goto next_2opt;\n                    }\n                }\n            }\n            next_2opt:;\n        }\n    }\n\n    // Generate output route\n    string ans;\n    ans.reserve(1000000);\n\n    for (int step = 0; step < K; ++step) {\n        int u = C[tour[step]];\n        int v = C[tour[(step + 1) % K]];\n        vector<int> dist, prev;\n        dijkstra(u, dist, prev);\n        vector<int> path;\n        for (int cur = v; cur != u; cur = prev[cur]) path.push_back(cur);\n        path.push_back(u);\n        reverse(path.begin(), path.end());\n\n        for (size_t k = 0; k + 1 < path.size(); ++k) {\n            int from = path[k], to = path[k + 1];\n            int fi = cells[from].first, fj = cells[from].second;\n            int ti = cells[to].first, tj = cells[to].second;\n            if (ti < fi) ans += 'U';\n            else if (ti > fi) ans += 'D';\n            else if (tj < fj) ans += 'L';\n            else ans += 'R';\n        }\n    }\n\n    cout << ans << \"\\n\";\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <set>\n#include <climits>\n#include <cmath>\nusing namespace std;\n\nstruct Obs {\n    int task;\n    int L;\n    int U;\n};\n\nint N, M, K, R;\nvector<vector<int>> d;           // task difficulties\nvector<vector<int>> out_edges;   // dependents of each task\nvector<int> indegree;            // original indegree\nvector<int> height;              // longest path to sink (including itself)\nint max_height;\n\nvector<int> task_status;         // 0: not started, 1: in progress, 2: completed\nvector<int> req_remaining;       // number of unfinished prerequisites\nvector<int> worker_task;         // which task worker is doing (-1 = free)\nvector<int> worker_start;        // day the worker started current task\nvector<vector<Obs>> obs;         // observations per worker\nvector<vector<int>> LB, UB;      // skill bounds per worker\n\n// update skill bounds for worker j using all observations\nvoid update_bounds(int j) {\n    vector<int> &lb = LB[j];\n    vector<int> &ub = UB[j];\n    fill(lb.begin(), lb.end(), 0);\n    fill(ub.begin(), ub.end(), 200);\n\n    bool changed = true;\n    int iter = 0;\n    while (changed && iter < 10) {\n        changed = false;\n        iter++;\n        for (const auto &ob : obs[j]) {\n            int ti = ob.task;\n            int L = ob.L;\n            int U = ob.U;\n            // Update lower bounds using upper bound U\n            for (int k = 0; k < K; k++) {\n                int new_lb = max(lb[k], d[ti][k] - U);\n                if (new_lb > ub[k]) new_lb = ub[k]; // keep consistent\n                if (new_lb > lb[k]) {\n                    lb[k] = new_lb;\n                    changed = true;\n                }\n            }\n            // Precompute S_others_max (max possible deficit from other skills)\n            vector<int> S_others_max(K, 0);\n            for (int k = 0; k < K; k++) {\n                int sum = 0;\n                for (int k2 = 0; k2 < K; k2++) {\n                    if (k2 == k) continue;\n                    sum += max(0, d[ti][k2] - lb[k2]);\n                }\n                S_others_max[k] = sum;\n            }\n            // Update upper bounds using lower bound L\n            for (int k = 0; k < K; k++) {\n                if (L > S_others_max[k]) {\n                    int new_ub = d[ti][k] - (L - S_others_max[k]);\n                    if (new_ub < lb[k]) new_ub = lb[k]; // keep consistent\n                    if (new_ub < ub[k]) {\n                        ub[k] = new_ub;\n                        changed = true;\n                    }\n                }\n            }\n        }\n    }\n}\n\n// estimate days needed for worker w to finish task idx\nint estimate_t(int worker, int task) {\n    double r = 0.0;\n    if (max_height > 1) {\n        r = (double)(height[task] - 1) / (max_height - 1);\n    }\n    int w_val = 0;\n    for (int k = 0; k < K; k++) {\n        double s_blend = LB[worker][k] + (UB[worker][k] - LB[worker][k]) * (1.0 - r);\n        int s_int = (int)round(s_blend);\n        int def = d[task][k] - s_int;\n        if (def > 0) w_val += def;\n    }\n    return (w_val == 0) ? 1 : w_val;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> M >> K >> R;\n    d.resize(N, vector<int>(K));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < K; j++) {\n            cin >> d[i][j];\n        }\n    }\n    out_edges.resize(N);\n    indegree.assign(N, 0);\n    for (int i = 0; i < R; i++) {\n        int u, v;\n        cin >> u >> v;\n        u--; v--;\n        out_edges[u].push_back(v);\n        indegree[v]++;\n    }\n    \n    // Compute height = length of longest path to a sink (inclusive)\n    height.resize(N);\n    max_height = 0;\n    for (int i = N - 1; i >= 0; i--) {\n        int best = 0;\n        for (int v : out_edges[i]) {\n            best = max(best, height[v]);\n        }\n        height[i] = best + 1;\n        max_height = max(max_height, height[i]);\n    }\n    \n    // Initialize state\n    task_status.assign(N, 0);\n    req_remaining = indegree;\n    worker_task.assign(M, -1);\n    worker_start.assign(M, -1);\n    obs.resize(M);\n    LB.assign(M, vector<int>(K, 0));\n    UB.assign(M, vector<int>(K, 200));\n    \n    int day = 1;\n    int completed = 0;\n    \n    while (true) {\n        vector<int> free_workers;\n        for (int j = 0; j < M; j++) {\n            if (worker_task[j] == -1) free_workers.push_back(j);\n        }\n        vector<int> ready_tasks;\n        for (int i = 0; i < N; i++) {\n            if (task_status[i] == 0 && req_remaining[i] == 0) {\n                ready_tasks.push_back(i);\n            }\n        }\n        \n        // Sort by height descending (critical first)\n        sort(ready_tasks.begin(), ready_tasks.end(), [&](int a, int b) {\n            return height[a] > height[b];\n        });\n        \n        // Only consider a limited number of highest priority tasks\n        int max_consider = max((int)free_workers.size() * 3, 40);\n        if ((int)ready_tasks.size() > max_consider) {\n            ready_tasks.resize(max_consider);\n        }\n        \n        vector<pair<int,int>> assignments;\n        set<int> used;\n        for (int task : ready_tasks) {\n            int best_w = -1;\n            int best_t = INT_MAX;\n            for (int w : free_workers) {\n                if (used.count(w)) continue;\n                int t_est = estimate_t(w, task);\n                if (t_est < best_t) {\n                    best_t = t_est;\n                    best_w = w;\n                }\n            }\n            if (best_w != -1) {\n                assignments.push_back({best_w, task});\n                used.insert(best_w);\n                if (used.size() == free_workers.size()) break;\n            }\n        }\n        \n        // Output assignments\n        cout << assignments.size();\n        for (auto &p : assignments) {\n            cout << \" \" << p.first + 1 << \" \" << p.second + 1;\n        }\n        cout << \"\\n\";\n        cout.flush();\n        \n        // Update state for newly started tasks\n        for (auto &p : assignments) {\n            int w = p.first;\n            int task = p.second;\n            worker_task[w] = task;\n            worker_start[w] = day;\n            task_status[task] = 1;\n        }\n        \n        // Read completions\n        int n;\n        cin >> n;\n        if (n == -1) {\n            break;\n        }\n        vector<int> finished_workers(n);\n        for (int i = 0; i < n; i++) {\n            cin >> finished_workers[i];\n            finished_workers[i]--;\n        }\n        \n        // Process each completion\n        for (int w : finished_workers) {\n            int task = worker_task[w];\n            int start = worker_start[w];\n            int t_actual = day - start + 1;\n            int L, U;\n            if (t_actual == 1) {\n                L = 0;\n                U = 4;\n            } else {\n                L = max(1, t_actual - 3);\n                U = t_actual + 3;\n            }\n            obs[w].push_back({task, L, U});\n            \n            task_status[task] = 2;\n            completed++;\n            for (int v : out_edges[task]) {\n                req_remaining[v]--;\n            }\n            worker_task[w] = -1;\n            worker_start[w] = -1;\n        }\n        \n        // Update skill bounds for workers who finished a task\n        for (int w : finished_workers) {\n            update_bounds(w);\n        }\n        \n        day++;\n        if (day > 2000) {\n            break;\n        }\n    }\n    \n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct InsertResult {\n    int cost, i, j;\n};\n\nint main() {\n    auto start_time = chrono::steady_clock::now();\n    auto elapsed_ms = [&]() {\n        return chrono::duration_cast<chrono::milliseconds>(\n                   chrono::steady_clock::now() - start_time)\n            .count();\n    };\n\n    // ---------- input ----------\n    vector<int> ax(1000), ay(1000), cx(1000), cy(1000);\n    for (int i = 0; i < 1000; i++)\n        cin >> ax[i] >> ay[i] >> cx[i] >> cy[i];\n\n    // ---------- precompute coordinates ----------\n    vector<pair<int, int>> coords(2001);\n    coords[0] = {400, 400};\n    for (int i = 0; i < 1000; i++) {\n        coords[2 * i + 1] = {ax[i], ay[i]};\n        coords[2 * i + 2] = {cx[i], cy[i]};\n    }\n    auto dist = [&](int u, int v) -> int {\n        return abs(coords[u].first - coords[v].first) +\n               abs(coords[u].second - coords[v].second);\n    };\n\n    // ---------- state ----------\n    vector<int> seq;            // sequence of node IDs (without depot)\n    int T = 0;                  // total travel time\n    vector<bool> sel_flag(1000, false);\n    vector<int> sel_orders;     // selected order indices (0..999)\n\n    // ---------- helpers ----------\n    auto calc_total = [&](const vector<int>& s) -> int {\n        if (s.empty()) return 0;\n        int tot = dist(0, s[0]);\n        for (size_t i = 0; i + 1 < s.size(); i++)\n            tot += dist(s[i], s[i + 1]);\n        tot += dist(s.back(), 0);\n        return tot;\n    };\n\n    auto eval_ins = [&](const vector<int>& s, int o) -> InsertResult {\n        int L = s.size();\n        int P = 2 * o + 1, D = 2 * o + 2;\n        int best_cost = INT_MAX, best_i = -1, best_j = -1;\n        for (int i = 0; i <= L; i++) {\n            int prev_i = (i == 0 ? 0 : s[i - 1]);\n            int next_i = (i == L ? 0 : s[i]);\n            int base_i = dist(prev_i, next_i);\n            // consecutive P and D at gap i\n            int cost_pd = dist(prev_i, P) + dist(P, D) + dist(D, next_i) - base_i;\n            if (cost_pd < best_cost) {\n                best_cost = cost_pd;\n                best_i = best_j = i;\n            }\n            int inc_P = dist(prev_i, P) + dist(P, next_i) - base_i;\n            for (int j = i + 1; j <= L; j++) {\n                int prev_j = s[j - 1];  // j>=1\n                int next_j = (j == L ? 0 : s[j]);\n                int inc_D = dist(prev_j, D) + dist(D, next_j) - dist(prev_j, next_j);\n                int cost = inc_P + inc_D;\n                if (cost < best_cost) {\n                    best_cost = cost;\n                    best_i = i;\n                    best_j = j;\n                }\n            }\n        }\n        return {best_cost, best_i, best_j};\n    };\n\n    auto apply_ins = [&](vector<int>& s, int o, int i, int j) {\n        int P = 2 * o + 1, D = 2 * o + 2;\n        int L = s.size();\n        vector<int> ns;\n        ns.reserve(L + 2);\n        for (int pos = 0; pos <= L; pos++) {\n            if (pos == i) ns.push_back(P);\n            if (pos == j) ns.push_back(D);\n            if (pos < L) ns.push_back(s[pos]);\n        }\n        s = move(ns);\n    };\n\n    auto remove_order = [&](vector<int>& s, int o) {\n        int P = 2 * o + 1, D = 2 * o + 2;\n        s.erase(remove(s.begin(), s.end(), P), s.end());\n        s.erase(remove(s.begin(), s.end(), D), s.end());\n    };\n\n    // ---------- greedy construction of initial 50 orders ----------\n    for (int sel = 0; sel < 50; sel++) {\n        int best_o = -1, best_cost = INT_MAX, best_i = -1, best_j = -1;\n        for (int o = 0; o < 1000; o++) {\n            if (sel_flag[o]) continue;\n            auto res = eval_ins(seq, o);\n            if (res.cost < best_cost) {\n                best_cost = res.cost;\n                best_o = o;\n                best_i = res.i;\n                best_j = res.j;\n            }\n        }\n        apply_ins(seq, best_o, best_i, best_j);\n        T += best_cost;\n        sel_flag[best_o] = true;\n        sel_orders.push_back(best_o);\n    }\n    T = calc_total(seq);  // avoid any accumulation error\n\n    // ---------- route improvement (deterministic local search) ----------\n    auto improve_route = [&]() {\n        const int MAX_PASSES = 20;\n        for (int pass = 0; pass < MAX_PASSES; pass++) {\n            bool improved = false;\n            // --- re\u2011insert whole order ---\n            for (int i = 0; i < (int)sel_orders.size(); i++) {\n                int o = sel_orders[i];\n                vector<int> temp_s = seq;\n                remove_order(temp_s, o);\n                int T_wo = calc_total(temp_s);\n                auto res = eval_ins(temp_s, o);\n                int T_new = T_wo + res.cost;\n                if (T_new < T) {\n                    seq = move(temp_s);\n                    apply_ins(seq, o, res.i, res.j);\n                    T = T_new;\n                    improved = true;\n                    break;\n                }\n            }\n            if (improved) continue;\n\n            // --- relocate one stop (pickup or delivery) ---\n            int L = seq.size();\n            for (int idx = 0; idx < L; idx++) {\n                int node = seq[idx];\n                int o = (node - 1) / 2;\n                bool is_pickup = (node % 2 == 1);\n                int other_node = is_pickup ? node + 1 : node - 1;\n                int other_idx = -1;\n                for (int k = 0; k < L; k++)\n                    if (seq[k] == other_node) { other_idx = k; break; }\n                vector<int> temp_s = seq;\n                temp_s.erase(temp_s.begin() + idx);\n                int other_idx_temp = -1;\n                for (int k = 0; k < L - 1; k++)\n                    if (temp_s[k] == other_node) { other_idx_temp = k; break; }\n                int best_delta = 0, best_pos = -1;\n                for (int pos = 0; pos <= L - 1; pos++) {\n                    if (is_pickup && pos > other_idx_temp) continue;\n                    if (!is_pickup && pos < other_idx_temp) continue;\n                    int prev = (pos == 0 ? 0 : temp_s[pos - 1]);\n                    int next = (pos == L - 1 ? 0 : temp_s[pos]);\n                    int base = dist(prev, next);\n                    int delta = dist(prev, node) + dist(node, next) - base;\n                    if (delta < best_delta) {\n                        best_delta = delta;\n                        best_pos = pos;\n                    }\n                }\n                if (best_delta < 0) {\n                    temp_s.insert(temp_s.begin() + best_pos, node);\n                    seq = move(temp_s);\n                    T += best_delta;\n                    improved = true;\n                    break;\n                }\n            }\n            if (improved) continue;\n\n            // --- reverse a segment (if feasible) ---\n            L = seq.size();\n            int best_delta = 0, best_i = -1, best_j = -1;\n            for (int i = 0; i < L; i++) {\n                for (int j = i + 1; j < L; j++) {\n                    bool feasible = true;\n                    for (int o : sel_orders) {\n                        int P = 2 * o + 1, D = 2 * o + 2;\n                        bool p_in = false, d_in = false;\n                        for (int k = i; k <= j; k++) {\n                            if (seq[k] == P) p_in = true;\n                            if (seq[k] == D) d_in = true;\n                        }\n                        if (p_in && d_in) { feasible = false; break; }\n                    }\n                    if (!feasible) continue;\n                    int prev_i = (i == 0 ? 0 : seq[i - 1]);\n                    int next_j = (j == L - 1 ? 0 : seq[j + 1]);\n                    int delta = dist(prev_i, seq[j]) + dist(seq[i], next_j) -\n                                dist(prev_i, seq[i]) - dist(seq[j], next_j);\n                    if (delta < best_delta) {\n                        best_delta = delta;\n                        best_i = i;\n                        best_j = j;\n                    }\n                }\n            }\n            if (best_delta < 0) {\n                reverse(seq.begin() + best_i, seq.begin() + best_j + 1);\n                T += best_delta;\n                improved = true;\n            }\n            if (!improved) break;\n        }\n    };\n\n    improve_route();\n\n    // ---------- SA + subset optimisation ----------\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> rnd_order(0, 999);\n    uniform_int_distribution<int> rnd_idx(0, 49);\n    uniform_real_distribution<double> rnd_prob(0.0, 1.0);\n\n    auto last_improve_time = chrono::steady_clock::now();\n\n    while (elapsed_ms() < 1900) {\n        double temp = 500.0 * (1.0 - elapsed_ms() / 2000.0);\n        if (temp < 1.0) temp = 1.0;\n        for (int a = 0; a < 100; a++) {\n            int idx_sel = rnd_idx(rng);\n            int o_sel = sel_orders[idx_sel];\n            int o_unsel;\n            do { o_unsel = rnd_order(rng); } while (sel_flag[o_unsel]);\n\n            int P_sel = 2 * o_sel + 1, D_sel = 2 * o_sel + 2;\n            vector<int> temp_s;\n            temp_s.reserve(seq.size() - 2);\n            for (int node : seq)\n                if (node != P_sel && node != D_sel) temp_s.push_back(node);\n            int T_wo = calc_total(temp_s);\n            auto res = eval_ins(temp_s, o_unsel);\n            int T_new = T_wo + res.cost;\n            double delta = T_new - T;\n            if (delta < 0 || exp(-delta / temp) > rnd_prob(rng)) {\n                apply_ins(temp_s, o_unsel, res.i, res.j);\n                seq = move(temp_s);\n                T = T_new;\n                sel_flag[o_sel] = false;\n                sel_flag[o_unsel] = true;\n                sel_orders[idx_sel] = o_unsel;\n            }\n        }\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - last_improve_time)\n                .count() > 200) {\n            improve_route();\n            last_improve_time = chrono::steady_clock::now();\n        }\n    }\n\n    // final polish\n    improve_route();\n\n    // ---------- output ----------\n    sort(sel_orders.begin(), sel_orders.end());\n    cout << 50;\n    for (int o : sel_orders) cout << \" \" << o + 1;\n    cout << \"\\n\";\n    cout << (seq.size() + 2);\n    cout << \" 400 400\";\n    for (int node : seq)\n        cout << \" \" << coords[node].first << \" \" << coords[node].second;\n    cout << \" 400 400\" << endl;\n\n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n#include <tuple>\n#include <climits>\n#include <cstdint>\n\nusing namespace std;\n\nstruct DSU {\n    vector<int> parent, sz;\n    int comps;\n    DSU(int n) : parent(n), sz(n, 1), comps(n) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    DSU(const DSU& other) : parent(other.parent), sz(other.sz), comps(other.comps) {}\n    int find(int x) {\n        while (parent[x] != x) {\n            parent[x] = parent[parent[x]];\n            x = parent[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        parent[b] = a;\n        sz[a] += sz[b];\n        --comps;\n        return true;\n    }\n    bool same(int a, int b) { return find(a) == find(b); }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    const int N = 400;\n    const int M = 1995;\n    \n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; ++i) cin >> x[i] >> y[i];\n    \n    vector<int> U(M), V(M);\n    for (int i = 0; i < M; ++i) cin >> U[i] >> V[i];\n    \n    vector<int> d(M);\n    for (int i = 0; i < M; ++i) {\n        double dx = x[U[i]] - x[V[i]];\n        double dy = y[U[i]] - y[V[i]];\n        d[i] = (int)round(sqrt(dx*dx + dy*dy));\n    }\n    \n    // XorShift for fast random numbers\n    uint32_t xs[4] = {123456789, 362436069, 521288629, 88675123};\n    auto xorshift = [&]() -> uint32_t {\n        uint32_t t = xs[0] ^ (xs[0] << 11);\n        xs[0] = xs[1];\n        xs[1] = xs[2];\n        xs[2] = xs[3];\n        xs[3] = xs[3] ^ (xs[3] >> 19) ^ t ^ (t >> 8);\n        return xs[3];\n    };\n    \n    const int num_sim = 3000;\n    vector<int> mst_count(M, 0);\n    \n    for (int sim = 0; sim < num_sim; ++sim) {\n        vector<tuple<int,int,int,int>> sim_edges; // (l, u, v, idx)\n        sim_edges.reserve(M);\n        for (int i = 0; i < M; ++i) {\n            int range = 2 * d[i] + 1;\n            int l = d[i] + int(xorshift() % range);\n            sim_edges.emplace_back(l, U[i], V[i], i);\n        }\n        sort(sim_edges.begin(), sim_edges.end());\n        DSU dsu_sim(N);\n        for (auto [l, u, v, idx] : sim_edges) {\n            if (dsu_sim.unite(u, v)) {\n                mst_count[idx]++;\n            }\n        }\n    }\n    \n    vector<double> prob(M);\n    for (int i = 0; i < M; ++i) {\n        prob[i] = (double)mst_count[i] / num_sim;\n    }\n    \n    DSU dsu(N);\n    vector<pair<int,int>> accepted; // to rebuild conn quickly\n    accepted.reserve(N);\n    \n    for (int i = 0; i < M; ++i) {\n        int l_i;\n        cin >> l_i;\n        int u = U[i], v = V[i];\n        \n        if (dsu.same(u, v)) {\n            cout << 0 << endl;\n            continue;\n        }\n        \n        // Very cheap edge -> accept immediately\n        if (l_i <= d[i] * 1.2) {\n            dsu.unite(u, v);\n            accepted.emplace_back(u, v);\n            cout << 1 << endl;\n            continue;\n        }\n        \n        int ru = dsu.find(u), rv = dsu.find(v);\n        \n        // Build a DSU with all future edges to check global connectivity\n        DSU conn(N);\n        for (auto [a, b] : accepted) conn.unite(a, b);\n        \n        int min_d_cut = INT_MAX;\n        for (int j = i + 1; j < M; ++j) {\n            conn.unite(U[j], V[j]);\n            int r1 = dsu.find(U[j]), r2 = dsu.find(V[j]);\n            if ((r1 == ru && r2 == rv) || (r1 == rv && r2 == ru)) {\n                min_d_cut = min(min_d_cut, d[j]);\n            }\n        }\n        \n        // Safety: if even accepting all future edges cannot connect the graph\n        if (conn.comps > 1) {\n            dsu.unite(u, v);\n            accepted.emplace_back(u, v);\n            cout << 1 << endl;\n            continue;\n        }\n        \n        // If there is a direct future edge and we are cheaper than its minimum possible value\n        if (min_d_cut != INT_MAX && l_i <= min_d_cut) {\n            dsu.unite(u, v);\n            accepted.emplace_back(u, v);\n            cout << 1 << endl;\n            continue;\n        }\n        \n        // No direct future edge exists, but graph can be connected via other paths\n        if (min_d_cut == INT_MAX) {\n            cout << 0 << endl;\n            continue;\n        }\n        \n        // Dynamic threshold based on local alternative, global importance, progress and urgency\n        double progress = (double)i / M;\n        int comps = dsu.comps;\n        int R = M - i - 1;\n        double urgency = (R > 0) ? (double)(comps - 1) / R : 1.0;\n        double factor = 1.0 + 2.0 * prob[i] + 0.5 * progress + 0.5 * urgency;\n        double threshold = min_d_cut * factor;\n        \n        if (l_i <= threshold) {\n            dsu.unite(u, v);\n            accepted.emplace_back(u, v);\n            cout << 1 << endl;\n        } else {\n            cout << 0 << endl;\n        }\n    }\n    \n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst long long INF_CAP = 1e9;\n\nstruct Dinic {\n    struct Edge {\n        int to, rev;\n        long long cap;\n    };\n    vector<vector<Edge>> g;\n    vector<int> level, iter;\n    Dinic(int n) : g(n), level(n), iter(n) {}\n    void add_edge(int from, int to, long long cap) {\n        g[from].push_back({to, (int)g[to].size(), cap});\n        g[to].push_back({from, (int)g[from].size() - 1, 0});\n    }\n    void bfs(int s) {\n        fill(level.begin(), level.end(), -1);\n        queue<int> q;\n        level[s] = 0; q.push(s);\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (auto &e : g[v]) {\n                if (e.cap > 0 && level[e.to] < 0) {\n                    level[e.to] = level[v] + 1;\n                    q.push(e.to);\n                }\n            }\n        }\n    }\n    long long dfs(int v, int t, long long f) {\n        if (v == t) return f;\n        for (int &i = iter[v]; i < (int)g[v].size(); i++) {\n            Edge &e = g[v][i];\n            if (e.cap > 0 && level[v] < level[e.to]) {\n                long long d = dfs(e.to, t, min(f, e.cap));\n                if (d > 0) {\n                    e.cap -= d;\n                    g[e.to][e.rev].cap += d;\n                    return d;\n                }\n            }\n        }\n        return 0;\n    }\n    long long max_flow(int s, int t) {\n        long long flow = 0;\n        while (true) {\n            bfs(s);\n            if (level[t] < 0) return flow;\n            fill(iter.begin(), iter.end(), 0);\n            long long f;\n            while ((f = dfs(s, t, 1LL<<60)) > 0) flow += f;\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N; cin >> N;\n    vector<int> px(N), py(N), pt(N);\n    for (int i = 0; i < N; i++) cin >> px[i] >> py[i] >> pt[i];\n    int M; cin >> M;\n    vector<int> hx(M), hy(M);\n    for (int i = 0; i < M; i++) cin >> hx[i] >> hy[i];\n\n    int grid[32][32];\n    memset(grid, 0, sizeof(grid));\n\n    const int dx[4] = {-1, 1, 0, 0};\n    const int dy[4] = {0, 0, -1, 1};\n\n    for (int turn = 0; turn < 300; turn++) {\n        int dist_human[32][32];\n        memset(dist_human, -1, sizeof(dist_human));\n        queue<pair<int,int>> qh;\n        for (int i = 0; i < M; i++) {\n            dist_human[hx[i]][hy[i]] = 0;\n            qh.push({hx[i], hy[i]});\n        }\n        while (!qh.empty()) {\n            auto [x, y] = qh.front(); qh.pop();\n            for (int d = 0; d < 4; d++) {\n                int nx = x + dx[d], ny = y + dy[d];\n                if (nx >= 1 && nx <= 30 && ny >= 1 && ny <= 30 && grid[nx][ny] == 0 && dist_human[nx][ny] == -1) {\n                    dist_human[nx][ny] = dist_human[x][y] + 1;\n                    qh.push({nx, ny});\n                }\n            }\n        }\n\n        int dist_pet[32][32];\n        memset(dist_pet, -1, sizeof(dist_pet));\n        queue<pair<int,int>> qp;\n        for (int i = 0; i < N; i++) {\n            dist_pet[px[i]][py[i]] = 0;\n            qp.push({px[i], py[i]});\n        }\n        while (!qp.empty()) {\n            auto [x, y] = qp.front(); qp.pop();\n            for (int d = 0; d < 4; d++) {\n                int nx = x + dx[d], ny = y + dy[d];\n                if (nx >= 1 && nx <= 30 && ny >= 1 && ny <= 30 && grid[nx][ny] == 0 && dist_pet[nx][ny] == -1) {\n                    dist_pet[nx][ny] = dist_pet[x][y] + 1;\n                    qp.push({nx, ny});\n                }\n            }\n        }\n\n        int pid[32][32];\n        memset(pid, -1, sizeof(pid));\n        vector<pair<int,int>> passable;\n        for (int i = 1; i <= 30; i++)\n            for (int j = 1; j <= 30; j++)\n                if (grid[i][j] == 0) {\n                    pid[i][j] = passable.size();\n                    passable.push_back({i, j});\n                }\n\n        int V = passable.size();\n        int src = 2 * V, sink = 2 * V + 1;\n        Dinic dinic(2 * V + 2);\n\n        for (int u = 0; u < V; u++) {\n            auto [x, y] = passable[u];\n            bool has_human = false, has_pet = false, adj_pet = false;\n            for (int i = 0; i < M; i++) if (hx[i] == x && hy[i] == y) has_human = true;\n            for (int i = 0; i < N; i++) if (px[i] == x && py[i] == y) has_pet = true;\n            if (!has_pet) {\n                for (int d = 0; d < 4; d++) {\n                    int nx = x + dx[d], ny = y + dy[d];\n                    if (nx >= 1 && nx <= 30 && ny >= 1 && ny <= 30) {\n                        for (int i = 0; i < N; i++)\n                            if (px[i] == nx && py[i] == ny) adj_pet = true;\n                    }\n                }\n            }\n            bool can_build = !has_human && !has_pet && !adj_pet;\n            long long cap;\n            if (can_build) {\n                int d = dist_human[x][y];\n                cap = 1 + 10000 / (d + 1);\n            } else {\n                cap = INF_CAP;\n            }\n            dinic.add_edge(2 * u, 2 * u + 1, cap);\n        }\n\n        for (int u = 0; u < V; u++) {\n            auto [x, y] = passable[u];\n            for (int d = 0; d < 4; d++) {\n                int nx = x + dx[d], ny = y + dy[d];\n                if (nx >= 1 && nx <= 30 && ny >= 1 && ny <= 30 && pid[nx][ny] != -1) {\n                    int v = pid[nx][ny];\n                    dinic.add_edge(2 * u + 1, 2 * v, INF_CAP);\n                    dinic.add_edge(2 * v + 1, 2 * u, INF_CAP);\n                }\n            }\n        }\n\n        for (int i = 0; i < M; i++) {\n            int u = pid[hx[i]][hy[i]];\n            if (u != -1) dinic.add_edge(src, 2 * u, INF_CAP);\n        }\n        for (int i = 0; i < N; i++) {\n            int u = pid[px[i]][py[i]];\n            if (u != -1) dinic.add_edge(2 * u + 1, sink, INF_CAP);\n        }\n\n        long long flow = dinic.max_flow(src, sink);\n        vector<pair<int,int>> target_walls;\n        if (flow < INF_CAP / 2) {\n            vector<bool> visited(2 * V + 2, false);\n            queue<int> q;\n            visited[sink] = true; q.push(sink);\n            while (!q.empty()) {\n                int v = q.front(); q.pop();\n                for (auto &e : dinic.g[v])\n                    if (e.cap > 0 && !visited[e.to]) {\n                        visited[e.to] = true;\n                        q.push(e.to);\n                    }\n            }\n            for (int u = 0; u < V; u++) {\n                int in = 2 * u, out = 2 * u + 1;\n                if (!visited[in] && visited[out])\n                    target_walls.push_back(passable[u]);\n            }\n        }\n\n        string actions(M, '.');\n\n        if (!target_walls.empty()) {\n            struct HumanBFS {\n                vector<vector<int>> dist;\n                vector<vector<pair<int,int>>> parent;\n            };\n            vector<HumanBFS> bfs_data(M);\n            for (int i = 0; i < M; i++) {\n                HumanBFS hb;\n                hb.dist.assign(31, vector<int>(31, -1));\n                hb.parent.assign(31, vector<pair<int,int>>(31, {-1, -1}));\n                queue<pair<int,int>> q;\n                hb.dist[hx[i]][hy[i]] = 0;\n                q.push({hx[i], hy[i]});\n                while (!q.empty()) {\n                    auto [x, y] = q.front(); q.pop();\n                    for (int d = 0; d < 4; d++) {\n                        int nx = x + dx[d], ny = y + dy[d];\n                        if (nx >= 1 && nx <= 30 && ny >= 1 && ny <= 30 && grid[nx][ny] == 0 && hb.dist[nx][ny] == -1) {\n                            hb.dist[nx][ny] = hb.dist[x][y] + 1;\n                            hb.parent[nx][ny] = {x, y};\n                            q.push({nx, ny});\n                        }\n                    }\n                }\n                bfs_data[i] = hb;\n            }\n\n            int Wcnt = target_walls.size();\n            vector<bool> wall_assigned(Wcnt, false);\n            vector<int> assigned_wall(M, -1), target_nx(M, -1), target_ny(M, -1);\n\n            for (int i = 0; i < M; i++) {\n                int best_w = -1, best_dist = INF_CAP, best_nx = -1, best_ny = -1;\n                for (int w = 0; w < Wcnt; w++) {\n                    if (wall_assigned[w]) continue;\n                    auto [wx, wy] = target_walls[w];\n                    int mind = INF_CAP, mnx = -1, mny = -1;\n                    for (int d = 0; d < 4; d++) {\n                        int nx = wx + dx[d], ny = wy + dy[d];\n                        if (nx >= 1 && nx <= 30 && ny >= 1 && ny <= 30 && grid[nx][ny] == 0) {\n                            int dist = bfs_data[i].dist[nx][ny];\n                            if (dist != -1 && dist < mind) {\n                                mind = dist;\n                                mnx = nx; mny = ny;\n                            }\n                        }\n                    }\n                    if (mind < best_dist) {\n                        best_dist = mind;\n                        best_w = w;\n                        best_nx = mnx; best_ny = mny;\n                    }\n                }\n                if (best_w != -1) {\n                    assigned_wall[i] = best_w;\n                    wall_assigned[best_w] = true;\n                    target_nx[i] = best_nx;\n                    target_ny[i] = best_ny;\n                }\n            }\n\n            for (int i = 0; i < M; i++) {\n                if (assigned_wall[i] == -1) continue;\n                int nx = target_nx[i], ny = target_ny[i];\n                if (nx == -1) continue;\n                int d = bfs_data[i].dist[nx][ny];\n                if (d == 0) {\n                    auto [wx, wy] = target_walls[assigned_wall[i]];\n                    if (wx < hx[i]) actions[i] = 'u';\n                    else if (wx > hx[i]) actions[i] = 'd';\n                    else if (wy < hy[i]) actions[i] = 'l';\n                    else if (wy > hy[i]) actions[i] = 'r';\n                } else {\n                    int cx = nx, cy = ny;\n                    while (true) {\n                        auto [px, py] = bfs_data[i].parent[cx][cy];\n                        if (px == hx[i] && py == hy[i]) break;\n                        cx = px; cy = py;\n                    }\n                    if (cx < hx[i]) actions[i] = 'U';\n                    else if (cx > hx[i]) actions[i] = 'D';\n                    else if (cy < hy[i]) actions[i] = 'L';\n                    else if (cy > hy[i]) actions[i] = 'R';\n                }\n            }\n\n            set<pair<int,int>> build_set;\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 wx = hx[i], wy = hy[i];\n                    if (c == 'u') wx--;\n                    else if (c == 'd') wx++;\n                    else if (c == 'l') wy--;\n                    else if (c == 'r') wy++;\n                    build_set.insert({wx, wy});\n                }\n            }\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 nx = hx[i], ny = hy[i];\n                    if (c == 'U') nx--;\n                    else if (c == 'D') nx++;\n                    else if (c == 'L') ny--;\n                    else if (c == 'R') ny++;\n                    if (build_set.count({nx, ny})) actions[i] = '.';\n                }\n            }\n        }\n\n        for (int i = 0; i < M; i++) {\n            if (actions[i] == '.') {\n                int best_dist = dist_pet[hx[i]][hy[i]];\n                char best_c = '.';\n                char moves[4] = {'U', 'D', 'L', 'R'};\n                for (int d = 0; d < 4; d++) {\n                    int nx = hx[i] + dx[d], ny = hy[i] + dy[d];\n                    if (nx >= 1 && nx <= 30 && ny >= 1 && ny <= 30 && grid[nx][ny] == 0) {\n                        if (dist_pet[nx][ny] > best_dist) {\n                            best_dist = dist_pet[nx][ny];\n                            best_c = moves[d];\n                        }\n                    }\n                }\n                actions[i] = best_c;\n            }\n        }\n\n        cout << actions << endl;\n\n        for (int i = 0; i < M; i++) {\n            char c = actions[i];\n            if (c == 'u') grid[hx[i] - 1][hy[i]] = 1;\n            else if (c == 'd') grid[hx[i] + 1][hy[i]] = 1;\n            else if (c == 'l') grid[hx[i]][hy[i] - 1] = 1;\n            else if (c == 'r') grid[hx[i]][hy[i] + 1] = 1;\n            else if (c == 'U') hx[i]--;\n            else if (c == 'D') hx[i]++;\n            else if (c == 'L') hy[i]--;\n            else if (c == 'R') hy[i]++;\n        }\n\n        for (int i = 0; i < N; i++) {\n            string s; cin >> s;\n            if (s == \".\") continue;\n            for (char c : s) {\n                if (c == 'U') px[i]--;\n                else if (c == 'D') px[i]++;\n                else if (c == 'L') py[i]--;\n                else if (c == 'R') py[i]++;\n            }\n        }\n    }\n    return 0;\n}","ahc009":"#include <iostream>\n#include <string>\n#include <vector>\n#include <array>\n#include <algorithm>\n#include <random>\n#include <cmath>\n\nusing namespace std;\n\nconst int L = 200;\nconst int H = 20, W = 20;\nconst int N = H * W;\n\nint start_id, target_id;\ndouble p;\nint next_cell[4][N];\ndouble p_stay[4][N];\ndouble p_move[4][N];\nchar dir_chars[4] = {'U', 'D', 'L', 'R'};\ndouble V[201][N]; // V[remaining steps][cell]\n\n// Evaluate exact expected S of a fixed string of length L\ndouble evaluate(const string& s) {\n    array<double, N> prob;\n    prob.fill(0.0);\n    prob[start_id] = 1.0;\n    double er = 0.0;\n    for (int step = 0; step < L; ++step) {\n        array<double, N> next_prob;\n        next_prob.fill(0.0);\n        int d;\n        char c = s[step];\n        if (c == 'U') d = 0;\n        else if (c == 'D') d = 1;\n        else if (c == 'L') d = 2;\n        else d = 3;\n        for (int i = 0; i < N; ++i) {\n            double pr = prob[i];\n            if (pr == 0.0) continue;\n            double stay = p_stay[d][i];\n            double move = p_move[d][i];\n            next_prob[i] += pr * stay;\n            if (move > 0.0) {\n                int nxt = next_cell[d][i];\n                if (nxt == target_id) {\n                    er += pr * move * (401 - (step + 1));\n                } else {\n                    next_prob[nxt] += pr * move;\n                }\n            }\n        }\n        prob = move(next_prob);\n    }\n    return er;\n}\n\nstruct BeamState {\n    string moves;\n    array<double, N> prob;\n    double er;\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    cin >> si >> sj >> ti >> tj >> p;\n    start_id = si * W + sj;\n    target_id = ti * W + tj;\n    \n    vector<string> h(20), v(20);\n    for (int i = 0; i < 20; ++i) cin >> h[i];\n    for (int i = 0; i < 19; ++i) cin >> v[i]; // 19 rows of 20 chars\n    \n    // Precompute walls, next cells, and move/stay probabilities\n    bool wall[4][N];\n    int di[4] = {-1, 1, 0, 0};\n    int dj[4] = {0, 0, -1, 1};\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = i * W + j;\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + di[d];\n                int nj = j + dj[d];\n                bool w = true;\n                if (ni >= 0 && ni < H && nj >= 0 && nj < W) {\n                    if (d == 0) {        // U\n                        if (v[i-1][j] == '0') w = false;\n                    } else if (d == 1) { // D\n                        if (v[i][j] == '0') w = false;\n                    } else if (d == 2) { // L\n                        if (h[i][j-1] == '0') w = false;\n                    } else {             // R\n                        if (h[i][j] == '0') w = false;\n                    }\n                }\n                wall[d][id] = w;\n                if (!w) {\n                    next_cell[d][id] = ni * W + nj;\n                } else {\n                    next_cell[d][id] = id;\n                }\n                if (w) {\n                    p_stay[d][id] = 1.0;\n                    p_move[d][id] = 0.0;\n                } else {\n                    p_stay[d][id] = p;\n                    p_move[d][id] = 1.0 - p;\n                }\n            }\n        }\n    }\n    \n    // Dynamic programming for adaptive upper bound V\n    for (int k = 0; k <= L; ++k) fill(V[k], V[k] + N, 0.0);\n    for (int k = 1; k <= L; ++k) {\n        double target_reward = 200.0 + k; // 401 - turn, turn = 201 - k\n        for (int i = 0; i < N; ++i) {\n            if (i == target_id) continue;\n            double best = 0.0;\n            for (int d = 0; d < 4; ++d) {\n                double stay = p_stay[d][i];\n                double move = p_move[d][i];\n                double val;\n                if (move == 0.0) {\n                    val = V[k-1][i];\n                } else {\n                    int nxt = next_cell[d][i];\n                    double move_val = (nxt == target_id) ? target_reward : V[k-1][nxt];\n                    val = stay * V[k-1][i] + move * move_val;\n                }\n                if (val > best) best = val;\n            }\n            V[k][i] = best;\n        }\n    }\n    \n    // Beam search\n    const int K = 150;\n    vector<BeamState> beam;\n    {\n        BeamState init;\n        init.moves = \"\";\n        init.prob.fill(0.0);\n        init.prob[start_id] = 1.0;\n        init.er = 0.0;\n        init.score = V[L][start_id];\n        beam.push_back(init);\n    }\n    \n    for (int step = 0; step < L; ++step) {\n        vector<BeamState> next_beam;\n        next_beam.reserve(beam.size() * 4);\n        for (const auto& st : beam) {\n            for (int d = 0; d < 4; ++d) {\n                BeamState ns;\n                ns.moves = st.moves + dir_chars[d];\n                ns.prob.fill(0.0);\n                ns.er = st.er;\n                for (int i = 0; i < N; ++i) {\n                    double pr = st.prob[i];\n                    if (pr == 0.0) continue;\n                    double stay = p_stay[d][i];\n                    double move = p_move[d][i];\n                    ns.prob[i] += pr * stay;\n                    if (move > 0.0) {\n                        int nxt = next_cell[d][i];\n                        if (nxt == target_id) {\n                            ns.er += pr * move * (401 - (step + 1));\n                        } else {\n                            ns.prob[nxt] += pr * move;\n                        }\n                    }\n                }\n                int R = L - (step + 1);\n                double future = 0.0;\n                for (int i = 0; i < N; ++i) {\n                    future += ns.prob[i] * V[R][i];\n                }\n                ns.score = ns.er + future;\n                next_beam.push_back(ns);\n            }\n        }\n        if (next_beam.size() > K) {\n            nth_element(next_beam.begin(), next_beam.begin() + K, next_beam.end(),\n                [](const BeamState& a, const BeamState& b) { return a.score > b.score; });\n            next_beam.resize(K);\n        } else {\n            sort(next_beam.begin(), next_beam.end(),\n                [](const BeamState& a, const BeamState& b) { return a.score > b.score; });\n        }\n        beam = move(next_beam);\n    }\n    \n    // Pick best from final beam\n    auto best_it = max_element(beam.begin(), beam.end(),\n        [](const BeamState& a, const BeamState& b) { return a.er < b.er; });\n    string best_s = best_it->moves;\n    double best_er = best_it->er;\n    \n    // Local refinement\n    random_device rd;\n    mt19937 rng(rd());\n    uniform_int_distribution<int> pos_dist(0, L-1);\n    uniform_int_distribution<int> dir_dist(0, 3);\n    for (int it = 0; it < 1500; ++it) {\n        int pos = pos_dist(rng);\n        char old_char = best_s[pos];\n        char new_char = dir_chars[dir_dist(rng)];\n        if (new_char == old_char) continue;\n        best_s[pos] = new_char;\n        double new_er = evaluate(best_s);\n        if (new_er > best_er) {\n            best_er = new_er;\n        } else {\n            best_s[pos] = old_char;\n        }\n    }\n    \n    cout << best_s << \"\\n\";\n    return 0;\n}","ahc010":"#include <iostream>\n#include <string>\n#include <vector>\n#include <cmath>\n#include <chrono>\n#include <cstring>\n#include <cstdint>\n\nusing namespace std;\n\n// xorshift random generator\nuint64_t xor64_state = 88172645463325252ULL;\nuint64_t xor64() {\n    xor64_state ^= xor64_state << 13;\n    xor64_state ^= xor64_state >> 7;\n    xor64_state ^= xor64_state << 17;\n    return xor64_state;\n}\nint rand_int(int n) {\n    return xor64() % n;\n}\ndouble rand_double() {\n    return (xor64() >> 11) * (1.0 / (1ULL << 53));\n}\n\nint main() {\n    // seed\n    xor64_state = chrono::steady_clock::now().time_since_epoch().count();\n    \n    int init[900];\n    for (int i = 0; i < 30; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < 30; ++j) {\n            init[i * 30 + j] = s[j] - '0';\n        }\n    }\n    \n    // rotation mapping: rotate[t][r] = type after r CCW rotations (r=0..3)\n    int rot1[8] = {1, 2, 3, 0, 5, 4, 7, 6};\n    int rotate[8][4];\n    for (int t = 0; t < 8; ++t) {\n        rotate[t][0] = t;\n        for (int r = 1; r < 4; ++r) {\n            rotate[t][r] = rot1[rotate[t][r-1]];\n        }\n    }\n    \n    // neighbor index for each direction (0=left,1=up,2=right,3=down), -1 if boundary\n    int neig[900][4];\n    for (int i = 0; i < 30; ++i) {\n        for (int j = 0; j < 30; ++j) {\n            int idx = i * 30 + j;\n            neig[idx][0] = (j > 0) ? idx - 1 : -1;\n            neig[idx][1] = (i > 0) ? idx - 30 : -1;\n            neig[idx][2] = (j < 29) ? idx + 1 : -1;\n            neig[idx][3] = (i < 29) ? idx + 30 : -1;\n        }\n    }\n    \n    // visited array for evaluation (directed edges)\n    int vis[900][4] = {0};\n    int mark = 0;\n    \n    // transition table from problem statement\n    const int to[8][4] = {\n        {1, 0, -1, -1},\n        {3, -1, -1, 0},\n        {-1, -1, 3, 2},\n        {-1, 2, 1, -1},\n        {1, 0, 3, 2},\n        {3, 2, 1, 0},\n        {2, -1, 0, -1},\n        {-1, 3, -1, 1}\n    };\n    \n    // evaluation: returns L1 * L2 (or 0 if <2 loops)\n    auto evaluate = [&](const int* cur) -> int {\n        mark++;\n        int max1 = 0, max2 = 0;\n        for (int i = 0; i < 900; ++i) {\n            int t = cur[i];\n            for (int d = 0; d < 4; ++d) {\n                if (vis[i][d] == mark) continue;\n                int d0 = to[t][d];\n                if (d0 < 0) continue;\n                int si = i, sd = d;\n                int ci = i, cd = d;\n                int len = 0;\n                while (1) {\n                    vis[ci][cd] = mark;\n                    int d2 = to[cur[ci]][cd];\n                    if (d2 < 0) { len = -1; break; }\n                    int ni = neig[ci][d2];\n                    if (ni < 0) { len = -1; break; }\n                    int nd = (d2 + 2) & 3;\n                    len++;\n                    ci = ni; cd = nd;\n                    if (ci == si && cd == sd) break;\n                }\n                if (len > 0) {\n                    if (len > max1) { max2 = max1; max1 = len; }\n                    else if (len > max2) { max2 = len; }\n                }\n            }\n        }\n        if (max2 == 0) return 0;\n        return max1 * max2;\n    };\n    \n    int cur[900];\n    int rot[900] = {0};\n    for (int i = 0; i < 900; ++i) cur[i] = init[i];\n    \n    int cur_score = evaluate(cur);\n    int best_score = cur_score;\n    int best_rot[900];\n    memcpy(best_rot, rot, sizeof(rot));\n    \n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.95;\n    double T = 100000.0;\n    double alpha = 0.999947;\n    \n    while (true) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n        if (elapsed >= time_limit) break;\n        \n        int idx = rand_int(900);\n        int delta = (rand_int(3) + 1); // 1, 2, or 3\n        int old_rot = rot[idx];\n        int new_rot = (old_rot + delta) & 3;\n        int old_type = cur[idx];\n        int new_type = rotate[init[idx]][new_rot];\n        if (new_type == old_type) continue;\n        \n        cur[idx] = new_type;\n        rot[idx] = new_rot;\n        int new_score = evaluate(cur);\n        \n        if (new_score >= cur_score || rand_double() < exp((new_score - cur_score) / T)) {\n            cur_score = new_score;\n            if (new_score > best_score) {\n                best_score = new_score;\n                memcpy(best_rot, rot, sizeof(rot));\n            }\n        } else {\n            cur[idx] = old_type;\n            rot[idx] = old_rot;\n        }\n        T *= alpha;\n    }\n    \n    // output 900 digits\n    for (int i = 0; i < 900; ++i) {\n        cout << best_rot[i];\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\nusing uint64 = unsigned long long;\nusing uint16 = unsigned short;\n\nconst int MAXN = 10;\nconst int MAXV = MAXN * MAXN; // 100\n\nint N, T, V;\nint EMPTY_ID;\n\n// Directions: 0:left, 1:up, 2:right, 3:down\nint dir_bit[4] = {1, 2, 4, 8};\nint opp_dir[4] = {2, 3, 0, 1};\nint drow[4] = {0, -1, 0, 1};\nint dcol[4] = {-1, 0, 1, 0};\nchar move_chars[4] = {'L', 'U', 'R', 'D'};\nunordered_map<char, char> opp_char_map = {{'L','R'},{'R','L'},{'U','D'},{'D','U'}};\n\nint tile_has[16][4];\nuint16 mask_has[4], mask_no[4];\n\nvoid precompute_tile_masks() {\n    for (int t=0; t<16; ++t) {\n        for (int d=0; d<4; ++d) {\n            tile_has[t][d] = (t & dir_bit[d]) ? 1 : 0;\n        }\n    }\n    for (int d=0; d<4; ++d) {\n        uint16 m_has = 0;\n        for (int t=0; t<16; ++t) if (tile_has[t][d]) m_has |= (1<<t);\n        mask_has[d] = m_has;\n        mask_no[d] = (~m_has) & 0xFFFF;\n    }\n}\n\n// ---------- CSP (target board reconstruction) ----------\nuint16 dom[MAXN][MAXN];\nint csp_board[MAXN][MAXN];\nbool assigned[MAXN][MAXN];\nint csp_tile_counts[16];\n\nbool dfs_csp(int assigned_cnt) {\n    if (assigned_cnt == V) return true;\n    int best_i=-1, best_j=-1, best_pop=999;\n    for (int i=0; i<N; ++i) {\n        for (int j=0; j<N; ++j) {\n            if (!assigned[i][j]) {\n                int pop = __builtin_popcount(dom[i][j]);\n                if (pop < best_pop) {\n                    best_pop = pop;\n                    best_i = i; best_j = j;\n                }\n            }\n        }\n    }\n    if (best_pop == 0) return false;\n    int i=best_i, j=best_j;\n    uint16 cur_dom = dom[i][j];\n    for (int t=0; t<16; ++t) {\n        if (!(cur_dom & (1<<t))) continue;\n        if (csp_tile_counts[t] == 0) continue;\n        bool ok = true;\n        for (int d=0; d<4; ++d) {\n            int ni = i + drow[d], nj = j + dcol[d];\n            if (ni<0 || ni>=N || nj<0 || nj>=N) continue;\n            if (assigned[ni][nj]) {\n                int nt = csp_board[ni][nj];\n                if (tile_has[t][d] != tile_has[nt][opp_dir[d]]) {\n                    ok = false; break;\n                }\n            }\n        }\n        if (!ok) continue;\n        csp_tile_counts[t]--;\n        assigned[i][j] = true;\n        csp_board[i][j] = t;\n        vector<tuple<int,int,uint16>> saved;\n        for (int d=0; d<4; ++d) {\n            int ni = i + drow[d], nj = j + dcol[d];\n            if (ni<0 || ni>=N || nj<0 || nj>=N) continue;\n            if (!assigned[ni][nj]) {\n                uint16 old = dom[ni][nj];\n                uint16 new_dom;\n                if (tile_has[t][d]) {\n                    new_dom = old & mask_has[opp_dir[d]];\n                } else {\n                    new_dom = old & mask_no[opp_dir[d]];\n                }\n                if (new_dom == 0) { ok = false; break; }\n                if (new_dom != old) {\n                    dom[ni][nj] = new_dom;\n                    saved.push_back({ni,nj,old});\n                }\n            }\n        }\n        if (ok) {\n            if (dfs_csp(assigned_cnt+1)) return true;\n        }\n        for (auto& s : saved) {\n            dom[get<0>(s)][get<1>(s)] = get<2>(s);\n        }\n        assigned[i][j] = false;\n        csp_board[i][j] = -1;\n        csp_tile_counts[t]++;\n    }\n    return false;\n}\n\n// ---------- Hungarian algorithm ----------\nvector<int> hungarian(const vector<vector<int>>& cost) {\n    int n = cost.size();\n    if (n == 0) return {};\n    vector<int> u(n+1, 0), v(n+1, 0), p(n+1, 0), way(n+1, 0);\n    const int INF = 1e9;\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) {\n                if (!used[j]) {\n                    int cur = cost[i0-1][j-1] - u[i0] - v[j];\n                    if (cur < minv[j]) { minv[j] = cur; way[j] = j0; }\n                    if (minv[j] < delta) { delta = minv[j]; 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    vector<int> assignment(n, -1);\n    for (int j=1; j<=n; ++j) {\n        if (p[j] > 0) {\n            assignment[p[j]-1] = j-1;\n        }\n    }\n    return assignment;\n}\n\n// ---------- Node for beam search ----------\nstruct Node {\n    uint8_t board[MAXV];\n    int empty;\n    int h;\n    uint64 hash;\n    int parent;\n    char move;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> T;\n    V = N * N;\n    EMPTY_ID = V - 1; // empty tile gets this ID\n\n    precompute_tile_masks();\n\n    vector<string> grid(N);\n    for (int i=0; i<N; ++i) cin >> grid[i];\n\n    int init_type[MAXN][MAXN];\n    int tile_counts[16] = {0};\n    for (int i=0; i<N; ++i) {\n        for (int j=0; j<N; ++j) {\n            char c = grid[i][j];\n            int t = (c >= '0' && c <= '9') ? (c - '0') : (c - 'a' + 10);\n            init_type[i][j] = t;\n            tile_counts[t]++;\n        }\n    }\n\n    // ---------- target board CSP ----------\n    for (int i=0; i<N; ++i) for (int j=0; j<N; ++j) {\n        uint16 mask = 0xFFFF;\n        if (i == 0) mask &= mask_no[1];      // no up\n        if (i == N-1) mask &= mask_no[3];    // no down\n        if (j == 0) mask &= mask_no[0];      // no left\n        if (j == N-1) mask &= mask_no[2];    // no right\n        if (i == N-2 && j == N-1) mask &= mask_no[3]; // no down to empty\n        if (i == N-1 && j == N-2) mask &= mask_no[2]; // no right to empty\n        if (i == N-1 && j == N-1) mask = (1 << 0);    // only empty tile\n        else mask &= ~(1 << 0);              // empty tile already used\n        dom[i][j] = mask;\n    }\n    memset(assigned, 0, sizeof(assigned));\n    memset(csp_board, -1, sizeof(csp_board));\n    memcpy(csp_tile_counts, tile_counts, sizeof(tile_counts));\n    assigned[N-1][N-1] = true;\n    csp_board[N-1][N-1] = 0;\n    csp_tile_counts[0]--;\n    dom[N-1][N-1] = 0;\n\n    bool csp_ok = dfs_csp(1);\n    assert(csp_ok); // problem guarantees solvable\n\n    // ---------- ID assignment and matching ----------\n    int init_id[MAXN][MAXN];\n    int id_to_type[MAXV];\n    int id_count = 0;\n    for (int i=0; i<N; ++i) for (int j=0; j<N; ++j) {\n        if (init_type[i][j] == 0) {\n            init_id[i][j] = EMPTY_ID;\n            id_to_type[EMPTY_ID] = 0;\n        } else {\n            init_id[i][j] = id_count;\n            id_to_type[id_count] = init_type[i][j];\n            id_count++;\n        }\n    }\n\n    int targetPos[MAXV];\n    targetPos[EMPTY_ID] = (N-1)*N + (N-1);\n\n    vector<int> ids_of_type[16];\n    vector<int> cells_of_type[16];\n    for (int i=0; i<N; ++i) for (int j=0; j<N; ++j) {\n        int t = csp_board[i][j];\n        if (t != 0) {\n            cells_of_type[t].push_back(i*N + j);\n        }\n    }\n    for (int id=0; id<EMPTY_ID; ++id) {\n        int t = id_to_type[id];\n        ids_of_type[t].push_back(id);\n    }\n\n    // initial positions of IDs\n    int initPos[MAXV];\n    for (int i=0; i<N; ++i) for (int j=0; j<N; ++j) {\n        initPos[init_id[i][j]] = i*N + j;\n    }\n\n    for (int t=1; t<16; ++t) {\n        int n = ids_of_type[t].size();\n        if (n == 0) continue;\n        vector<vector<int>> cost(n, vector<int>(n));\n        for (int i=0; i<n; ++i) {\n            int id = ids_of_type[t][i];\n            int r1 = initPos[id] / N, c1 = initPos[id] % N;\n            for (int j=0; j<n; ++j) {\n                int cell = cells_of_type[t][j];\n                int r2 = cell / N, c2 = cell % N;\n                cost[i][j] = abs(r1-r2) + abs(c1-c2);\n            }\n        }\n        vector<int> assignment = hungarian(cost);\n        for (int i=0; i<n; ++i) {\n            int id = ids_of_type[t][i];\n            int j = assignment[i];\n            targetPos[id] = cells_of_type[t][j];\n        }\n    }\n\n    // ---------- Manhattan distance table ----------\n    int manDist[MAXV][MAXV];\n    for (int id=0; id<V; ++id) {\n        int tr = targetPos[id] / N, tc = targetPos[id] % N;\n        for (int cell=0; cell<V; ++cell) {\n            int r = cell / N, c = cell % N;\n            manDist[id][cell] = abs(tr-r) + abs(tc-c);\n        }\n    }\n\n    // ---------- Zobrist hashing ----------\n    mt19937_64 rng(12345);\n    uint64 zob[MAXV][MAXV];\n    for (int id=0; id<V; ++id)\n        for (int cell=0; cell<V; ++cell)\n            zob[id][cell] = rng();\n\n    // ---------- Initial state ----------\n    Node root;\n    for (int i=0; i<N; ++i)\n        for (int j=0; j<N; ++j)\n            root.board[i*N+j] = init_id[i][j];\n\n    int init_h = 0;\n    uint64 init_hash = 0;\n    for (int cell=0; cell<V; ++cell) {\n        int id = root.board[cell];\n        if (id == EMPTY_ID) root.empty = cell;\n        init_h += manDist[id][cell];\n        init_hash ^= zob[id][cell];\n    }\n    root.h = init_h;\n    root.hash = init_hash;\n    root.parent = -1;\n    root.move = 0;\n\n    if (init_h == 0) {\n        cout << \"\" << endl;\n        return 0;\n    }\n\n    // ---------- Beam search ----------\n    vector<Node> nodes;\n    nodes.reserve(400000);\n    unordered_set<uint64_t> global_hash;\n    global_hash.reserve(400000);\n\n    nodes.push_back(root);\n    global_hash.insert(root.hash);\n\n    vector<int> current_beam = {0};\n    int goal_node = -1;\n    int best_h_node = 0;\n    int best_h = init_h;\n    const int beam_width = 150;\n\n    clock_t start_time = clock();\n    const double TIME_LIMIT = 2.8 * CLOCKS_PER_SEC;\n\n    for (int depth = 0; depth < T; ++depth) {\n        if (clock() - start_time > TIME_LIMIT) break;\n        vector<int> next_nodes;\n        for (int idx : current_beam) {\n            Node& cur = nodes[idx];\n            int e = cur.empty;\n            int r = e / N, c = e % N;\n            for (int d=0; d<4; ++d) {\n                int nr = r + drow[d], nc = c + dcol[d];\n                if (nr<0 || nr>=N || nc<0 || nc>=N) continue;\n                if (cur.move != 0) {\n                    if (move_chars[d] == opp_char_map[cur.move]) continue;\n                }\n                int neighbor = nr*N + nc;\n                int tileID = cur.board[neighbor];\n\n                Node next;\n                memcpy(next.board, cur.board, V * sizeof(uint8_t));\n                next.board[e] = tileID;\n                next.board[neighbor] = EMPTY_ID;\n                next.empty = neighbor;\n\n                uint64 new_hash = cur.hash;\n                new_hash ^= zob[tileID][e] ^ zob[tileID][neighbor] ^ zob[EMPTY_ID][neighbor] ^ zob[EMPTY_ID][e];\n                next.hash = new_hash;\n                if (global_hash.count(new_hash)) continue;\n\n                int new_h = cur.h;\n                new_h += manDist[tileID][e] - manDist[tileID][neighbor];\n                new_h += manDist[EMPTY_ID][neighbor] - manDist[EMPTY_ID][e];\n                next.h = new_h;\n                next.parent = idx;\n                next.move = move_chars[d];\n\n                if (new_h == 0) goal_node = nodes.size();\n\n                nodes.push_back(next);\n                global_hash.insert(new_hash);\n                next_nodes.push_back(nodes.size()-1);\n\n                if (new_h < best_h) {\n                    best_h = new_h;\n                    best_h_node = nodes.size()-1;\n                }\n                if (goal_node != -1) break;\n            }\n            if (goal_node != -1) break;\n        }\n        if (goal_node != -1) break;\n        if (next_nodes.empty()) break;\n\n        sort(next_nodes.begin(), next_nodes.end(), [&](int a, int b) {\n            return nodes[a].h < nodes[b].h;\n        });\n        if (next_nodes.size() > beam_width) next_nodes.resize(beam_width);\n        current_beam = move(next_nodes);\n    }\n\n    // ---------- Output ----------\n    int out_node = (goal_node != -1) ? goal_node : best_h_node;\n    string seq;\n    while (nodes[out_node].parent != -1) {\n        seq.push_back(nodes[out_node].move);\n        out_node = nodes[out_node].parent;\n    }\n    reverse(seq.begin(), seq.end());\n    if ((int)seq.length() > T) seq = seq.substr(0, T);\n    cout << seq << endl;\n\n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <numeric>\n#include <cstdlib>\n#include <tuple>\n\nusing namespace std;\n\nstruct Point { int x, y; };\nstruct Line { int p1x, p1y, p2x, p2y; };\n\nvector<int> a(11);\nint total_attendees;\n\nlong long cross(const Line& L, const Point& p) {\n    long long dx = L.p2x - L.p1x;\n    long long dy = L.p2y - L.p1y;\n    long long px = p.x - L.p1x;\n    long long py = p.y - L.p1y;\n    return dx * py - dy * px;\n}\n\n// check if line intersects the cake (circle radius 10000)\nbool line_intersects_circle(const Line& L) {\n    long long dx = L.p2x - L.p1x;\n    long long dy = L.p2y - L.p1y;\n    long long cross_val = std::llabs((long long)L.p1x * L.p2y - (long long)L.p1y * L.p2x);\n    long long lhs = cross_val * cross_val;\n    long long rhs = 100000000LL * (dx * dx + dy * dy);\n    return lhs <= rhs;\n}\n\nint side(const Line& L, const Point& p) {\n    long long c = cross(L, p);\n    if (c > 0) return 1;\n    if (c < 0) return -1;\n    return 0;\n}\n\nstruct State {\n    vector<int> cell_of_point;\n    vector<int> cell_count;\n    vector<vector<int>> cell_points;\n    int score;\n};\n\nint compute_score_from_counts(const vector<int>& cell_count) {\n    int b[11] = {0};\n    for (int cnt : cell_count) if (cnt > 0 && cnt <= 10) b[cnt]++;\n    int res = 0;\n    for (int d = 1; d <= 10; ++d) res += min(a[d], b[d]);\n    return res;\n}\n\nState build_initial_state(const vector<Point>& pts) {\n    State st;\n    int N = pts.size();\n    st.cell_of_point.assign(N, 0);\n    st.cell_count = {N};\n    st.cell_points = { vector<int>(N) };\n    iota(st.cell_points[0].begin(), st.cell_points[0].end(), 0);\n    st.score = compute_score_from_counts(st.cell_count);\n    return st;\n}\n\n// returns new_count, bits, score; if line hits any strawberry, score = -1\ntuple<vector<int>, vector<int>, int> simulate(const State& st, const Line& L, const vector<Point>& pts) {\n    int N = pts.size();\n    int C = st.cell_count.size();\n    vector<int> new_count(2 * C, 0);\n    vector<int> bits(N);\n    long long dx = L.p2x - L.p1x;\n    long long dy = L.p2y - L.p1y;\n    for (int i = 0; i < N; ++i) {\n        int old_c = st.cell_of_point[i];\n        long long px = pts[i].x - L.p1x;\n        long long py = pts[i].y - L.p1y;\n        long long c = dx * py - dy * px;\n        if (c == 0) return { {}, {}, -1 };\n        int bit = (c > 0) ? 1 : 0;\n        bits[i] = bit;\n        int nc = old_c * 2 + bit;\n        new_count[nc]++;\n    }\n    int score = compute_score_from_counts(new_count);\n    return {new_count, bits, score};\n}\n\nvoid apply_line(State& st, const Line& /*L*/, const vector<int>& new_count,\n                const vector<int>& bits, const vector<Point>& pts) {\n    int N = pts.size();\n    int C = st.cell_count.size();\n    vector<int> new_cell_id(2 * C, -1);\n    int new_C = 0;\n    for (int c = 0; c < 2 * C; ++c)\n        if (new_count[c] > 0) new_cell_id[c] = new_C++;\n    st.cell_count.resize(new_C);\n    st.cell_points.assign(new_C, vector<int>());\n    for (int c = 0; c < 2 * C; ++c) {\n        if (new_count[c] > 0) {\n            int nid = new_cell_id[c];\n            st.cell_count[nid] = new_count[c];\n            st.cell_points[nid].reserve(new_count[c]);\n        }\n    }\n    for (int i = 0; i < N; ++i) {\n        int old_c = st.cell_of_point[i];\n        int nid = new_cell_id[old_c * 2 + bits[i]];\n        st.cell_of_point[i] = nid;\n        st.cell_points[nid].push_back(i);\n    }\n    st.score = compute_score_from_counts(st.cell_count);\n}\n\n// ----- candidate generators -----\nLine random_line_through_cake(mt19937& rng) {\n    uniform_int_distribution<int> dist_coord(-10000, 10000);\n    uniform_int_distribution<int> dist_d(-1000, 1000);\n    while (true) {\n        int x = dist_coord(rng);\n        int y = dist_coord(rng);\n        if ((long long)x * x + (long long)y * y < 100000000LL) {\n            int dx = dist_d(rng);\n            int dy = dist_d(rng);\n            if (dx == 0 && dy == 0) dx = 1;\n            return {x, y, x + dx, y + dy};\n        }\n    }\n}\n\nLine random_cell_split_line(const State& st, const vector<Point>& pts, mt19937& rng) {\n    const auto& cell_points = st.cell_points;\n    vector<int> valid_cells;\n    for (int c = 0; c < (int)cell_points.size(); ++c)\n        if (cell_points[c].size() >= 2) valid_cells.push_back(c);\n    if (valid_cells.empty()) return random_line_through_cake(rng);\n    uniform_int_distribution<int> dist_cell(0, valid_cells.size() - 1);\n    int c = valid_cells[dist_cell(rng)];\n    const auto& pvec = cell_points[c];\n    uniform_int_distribution<int> dist_pt(0, pvec.size() - 1);\n    int i1 = pvec[dist_pt(rng)];\n    int i2 = pvec[dist_pt(rng)];\n    while (i2 == i1) i2 = pvec[dist_pt(rng)];\n    Point p1 = pts[i1], p2 = pts[i2];\n    int mx = (p1.x + p2.x) / 2;\n    int my = (p1.y + p2.y) / 2;\n    uniform_int_distribution<int> dist_d(-200, 200);\n    int dx = dist_d(rng);\n    int dy = dist_d(rng);\n    if (dx == 0 && dy == 0) dx = 1;\n    Line L = {mx, my, mx + dx, my + dy};\n    int s1 = side(L, p1), s2 = side(L, p2);\n    if (s1 == s2 || s1 == 0 || s2 == 0) {\n        int ndx = -dy, ndy = dx;\n        dx = ndx; dy = ndy;\n        L = {mx, my, mx + dx, my + dy};\n        s1 = side(L, p1); s2 = side(L, p2);\n        if (s1 == s2 || s1 == 0 || s2 == 0) {\n            return random_line_through_cake(rng);\n        }\n    }\n    return L;\n}\n\nLine random_separating_line(const vector<Point>& pts, int N, mt19937& rng) {\n    uniform_int_distribution<int> dist_pt(0, N - 1);\n    int i1 = dist_pt(rng);\n    int i2 = dist_pt(rng);\n    while (i2 == i1) i2 = dist_pt(rng);\n    Point p1 = pts[i1], p2 = pts[i2];\n    int mx = (p1.x + p2.x) / 2;\n    int my = (p1.y + p2.y) / 2;\n    uniform_int_distribution<int> dist_d(-1000, 1000);\n    int dx = dist_d(rng);\n    int dy = dist_d(rng);\n    if (dx == 0 && dy == 0) dx = 1;\n    Line L = {mx, my, mx + dx, my + dy};\n    if (side(L, p1) == side(L, p2) || side(L, p1) == 0 || side(L, p2) == 0) {\n        swap(dx, dy); dx = -dx;\n        L = {mx, my, mx + dx, my + dy};\n        if (side(L, p1) == side(L, p2) || side(L, p1) == 0 || side(L, p2) == 0)\n            return random_line_through_cake(rng);\n    }\n    return L;\n}\n\nLine perturb_existing_line(const vector<Line>& lines, mt19937& rng) {\n    if (lines.empty()) return random_line_through_cake(rng);\n    uniform_int_distribution<int> dist_idx(0, lines.size() - 1);\n    uniform_int_distribution<int> dist_delta(-200, 200);\n    uniform_int_distribution<int> dist_coord(0, 3);\n    Line L = lines[dist_idx(rng)];\n    int delta = dist_delta(rng);\n    int coord = dist_coord(rng);\n    if (coord == 0) L.p1x += delta;\n    else if (coord == 1) L.p1y += delta;\n    else if (coord == 2) L.p2x += delta;\n    else L.p2y += delta;\n    if (L.p1x == L.p2x && L.p1y == L.p2y) L.p1x += 1;\n    return L;\n}\n\nint main() {\n    ios::sync_with_stdio(false); cin.tie(0);\n    auto start_time = chrono::steady_clock::now();\n\n    int N, K; cin >> N >> K;\n    total_attendees = 0;\n    for (int d = 1; d <= 10; ++d) { cin >> a[d]; total_attendees += a[d]; }\n    vector<Point> pts(N);\n    for (int i = 0; i < N; ++i) cin >> pts[i].x >> pts[i].y;\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    State st = build_initial_state(pts);\n    vector<Line> lines;\n    lines.reserve(K);\n\n    const int NUM_GREEDY_CANDIDATES = 200;\n    const double TIME_LIMIT = 2.9;\n\n    // greedy addition: always add the best line found, up to K cuts\n    while ((int)lines.size() < K) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n        if (elapsed > TIME_LIMIT) break;\n        int best_score = -1;\n        Line best_line;\n        vector<int> best_new_count, best_bits;\n        for (int t = 0; t < NUM_GREEDY_CANDIDATES; ++t) {\n            Line cand;\n            int type = uniform_int_distribution<int>(0, 9)(rng);\n            if (type < 2) cand = random_line_through_cake(rng);\n            else if (type < 6) cand = random_cell_split_line(st, pts, rng);\n            else if (type < 9) cand = random_separating_line(pts, N, rng);\n            else cand = perturb_existing_line(lines, rng);\n            if (!line_intersects_circle(cand)) continue;\n            auto [new_count, bits, score] = simulate(st, cand, pts);\n            if (score < 0) continue; // hits a strawberry center\n            if (score > best_score) {\n                best_score = score;\n                best_line = cand;\n                best_new_count = std::move(new_count);\n                best_bits = std::move(bits);\n            }\n        }\n        // fallback: force a line that does not hit any strawberry\n        if (best_score < 0) {\n            while (true) {\n                Line cand = random_line_through_cake(rng);\n                if (!line_intersects_circle(cand)) continue;\n                auto [new_count, bits, score] = simulate(st, cand, pts);\n                if (score >= 0) {\n                    best_line = cand;\n                    best_new_count = std::move(new_count);\n                    best_bits = std::move(bits);\n                    break;\n                }\n            }\n        }\n        apply_line(st, best_line, best_new_count, best_bits, pts);\n        lines.push_back(best_line);\n    }\n\n    // local search: try to replace each line with a better one\n    bool improved = true;\n    int local_iter = 0;\n    const int NUM_LOCAL_CANDIDATES = 150;\n    while (improved && (int)lines.size() == K && local_iter < 5) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n        if (elapsed > TIME_LIMIT) break;\n        improved = false;\n        local_iter++;\n        vector<int> order(K);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n        for (int idx : order) {\n            elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n            if (elapsed > TIME_LIMIT) break;\n            Line old_line = lines[idx];\n            // build state without this line\n            State curr = build_initial_state(pts);\n            for (int j = 0; j < K; ++j) {\n                if (j == idx) continue;\n                auto [new_count, bits, score] = simulate(curr, lines[j], pts);\n                apply_line(curr, lines[j], new_count, bits, pts);\n            }\n            int best_score = curr.score;\n            Line best_line;\n            vector<int> best_new_count, best_bits;\n            for (int t = 0; t < NUM_LOCAL_CANDIDATES; ++t) {\n                Line cand;\n                int type = uniform_int_distribution<int>(0, 9)(rng);\n                if (type < 2) cand = random_line_through_cake(rng);\n                else if (type < 6) cand = random_cell_split_line(curr, pts, rng);\n                else if (type < 9) cand = random_separating_line(pts, N, rng);\n                else cand = perturb_existing_line(lines, rng);\n                if (!line_intersects_circle(cand)) continue;\n                auto [new_count, bits, score] = simulate(curr, cand, pts);\n                if (score < 0) continue;\n                if (score > best_score) {\n                    best_score = score;\n                    best_line = cand;\n                    best_new_count = std::move(new_count);\n                    best_bits = std::move(bits);\n                }\n            }\n            if (best_score > curr.score) {\n                lines[idx] = best_line;\n                improved = true;\n            } else {\n                lines[idx] = old_line;\n            }\n        }\n        // rebuild global state after each pass\n        if (improved) {\n            st = build_initial_state(pts);\n            for (const Line& L : lines) {\n                auto [new_count, bits, score] = simulate(st, L, pts);\n                apply_line(st, L, new_count, bits, pts);\n            }\n        }\n    }\n\n    // output\n    cout << lines.size() << \"\\n\";\n    for (const Line& L : lines) {\n        cout << L.p1x << \" \" << L.p1y << \" \" << L.p2x << \" \" << L.p2y << \"\\n\";\n    }\n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <array>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nstruct Pt { int x, y; };\n\nint main() {\n    auto start_time = chrono::steady_clock::now();\n\n    // read input\n    int N, M;\n    cin >> N >> M;\n    vector<Pt> initial_dots(M);\n    for (int i = 0; i < M; i++) cin >> initial_dots[i].x >> initial_dots[i].y;\n\n    int c = (N - 1) / 2;\n    vector<vector<int>> weight(N, vector<int>(N));\n    long long S = 0;\n    long long initial_sum = 0;\n    for (int x = 0; x < N; x++) for (int y = 0; y < N; y++) {\n        weight[x][y] = (x - c) * (x - c) + (y - c) * (y - c) + 1;\n        S += weight[x][y];\n    }\n    for (auto& p : initial_dots) initial_sum += weight[p.x][p.y];\n\n    // segment check / mark function\n    auto segment_operation = [&](Pt a, Pt b, bool check_only,\n                                 vector<vector<bool>>& dot,\n                                 vector<vector<bool>>& used_h,\n                                 vector<vector<bool>>& used_v,\n                                 vector<vector<bool>>& used_d1,\n                                 vector<vector<bool>>& used_d2) -> bool {\n        int dx = b.x - a.x, dy = b.y - a.y;\n        int steps = max(abs(dx), abs(dy));\n        int sx = (dx == 0 ? 0 : (dx > 0 ? 1 : -1));\n        int sy = (dy == 0 ? 0 : (dy > 0 ? 1 : -1));\n        int cx = a.x, cy = a.y;\n        for (int s = 1; s <= steps; s++) {\n            int nx = cx + sx, ny = cy + sy;\n            if (s < steps) {\n                if (dot[nx][ny]) return false;\n            }\n            if (sx != 0 && sy == 0) { // horizontal\n                int x = min(cx, nx), y = cy;\n                if (check_only) { if (used_h[x][y]) return false; }\n                else used_h[x][y] = true;\n            } else if (sx == 0 && sy != 0) { // vertical\n                int x = cx, y = min(cy, ny);\n                if (check_only) { if (used_v[x][y]) return false; }\n                else used_v[x][y] = true;\n            } else if (sx == 1 && sy == 1) { // diagonal (1,1)\n                if (check_only) { if (used_d1[cx][cy]) return false; }\n                else used_d1[cx][cy] = true;\n            } else if (sx == -1 && sy == -1) { // diagonal (-1,-1) -> reverse of (1,1)\n                if (check_only) { if (used_d1[nx][ny]) return false; }\n                else used_d1[nx][ny] = true;\n            } else if (sx == 1 && sy == -1) { // diagonal (1,-1)\n                if (check_only) { if (used_d2[cx][cy]) return false; }\n                else used_d2[cx][cy] = true;\n            } else if (sx == -1 && sy == 1) { // diagonal (-1,1) -> reverse of (1,-1)\n                if (check_only) { if (used_d2[nx][ny]) return false; }\n                else used_d2[nx][ny] = true;\n            } else return false;\n            cx = nx; cy = ny;\n        }\n        return true;\n    };\n\n    // one simulation\n    auto run_sim = [&](uint64_t seed) {\n        mt19937 rng(static_cast<unsigned int>(seed));\n\n        vector<vector<bool>> dot(N, vector<bool>(N, false));\n        vector<vector<bool>> used_h(N - 1, vector<bool>(N, false));\n        vector<vector<bool>> used_v(N, vector<bool>(N - 1, false));\n        vector<vector<bool>> used_d1(N - 1, vector<bool>(N - 1, false));\n        vector<vector<bool>> used_d2(N - 1, vector<bool>(N, false));\n        vector<vector<int>> row_dots(N), col_dots(N);\n\n        for (auto& p : initial_dots) {\n            dot[p.x][p.y] = true;\n            row_dots[p.y].push_back(p.x);\n            col_dots[p.x].push_back(p.y);\n        }\n        long long cur_sum = initial_sum;\n        vector<array<Pt, 4>> history;\n\n        auto is_valid = [&](array<Pt, 4>& p) {\n            if (dot[p[0].x][p[0].y]) return false;\n            if (!dot[p[1].x][p[1].y] || !dot[p[2].x][p[2].y] || !dot[p[3].x][p[3].y]) return false;\n            for (int i = 0; i < 4; i++) {\n                if (!segment_operation(p[i], p[(i + 1) % 4], true, dot, used_h, used_v, used_d1, used_d2))\n                    return false;\n            }\n            return true;\n        };\n        auto apply_move = [&](array<Pt, 4>& p) {\n            dot[p[0].x][p[0].y] = true;\n            row_dots[p[0].y].push_back(p[0].x);\n            col_dots[p[0].x].push_back(p[0].y);\n            cur_sum += weight[p[0].x][p[0].y];\n            for (int i = 0; i < 4; i++)\n                segment_operation(p[i], p[(i + 1) % 4], false, dot, used_h, used_v, used_d1, used_d2);\n        };\n\n        auto add_axis_moves = [&](int x, int y, vector<array<Pt, 4>>& cands) {\n            if (x + 1 < N && y + 1 < N) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x + 1, y}, Pt{x + 1, y + 1}, Pt{x, y + 1}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n            if (x > 0 && y + 1 < N) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x, y + 1}, Pt{x - 1, y + 1}, Pt{x - 1, y}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n            if (x > 0 && y > 0) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x - 1, y}, Pt{x - 1, y - 1}, Pt{x, y - 1}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n            if (x + 1 < N && y > 0) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x, y - 1}, Pt{x + 1, y - 1}, Pt{x + 1, y}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n        };\n\n        auto add_diamond_moves = [&](int x, int y, vector<array<Pt, 4>>& cands) {\n            // role 0: bottom\n            if (x + 2 < N && y >= 1 && y + 1 < N) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x + 1, y + 1}, Pt{x + 2, y}, Pt{x + 1, y - 1}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n            // role 1: right\n            if (x >= 1 && x + 1 < N && y >= 2 && y < N) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x + 1, y - 1}, Pt{x, y - 2}, Pt{x - 1, y - 1}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n            // role 2: top\n            if (x >= 2 && y >= 1 && y + 1 < N) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x - 1, y - 1}, Pt{x - 2, y}, Pt{x - 1, y + 1}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n            // role 3: left\n            if (x >= 1 && x + 1 < N && y + 2 < N) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x - 1, y + 1}, Pt{x, y + 2}, Pt{x + 1, y + 1}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n        };\n\n        auto add_large_moves = [&](int x1, int y1, vector<array<Pt, 4>>& cands) {\n            for (int x2 : row_dots[y1]) {\n                if (x2 == x1) continue;\n                for (int y2 : col_dots[x1]) {\n                    if (y2 == y1) continue;\n                    if (!dot[x2][y2]) continue;\n                    array<Pt, 4> p = {Pt{x1, y1}, Pt{x2, y1}, Pt{x2, y2}, Pt{x1, y2}};\n                    if (is_valid(p)) cands.push_back(p);\n                }\n            }\n        };\n\n        while (true) {\n            vector<array<Pt, 4>> cands;\n            // small moves\n            for (int x = 0; x < N; x++) {\n                for (int y = 0; y < N; y++) {\n                    if (dot[x][y]) continue;\n                    add_axis_moves(x, y, cands);\n                    add_diamond_moves(x, y, cands);\n                }\n            }\n            // large moves only if no small moves\n            if (cands.empty()) {\n                for (int x = 0; x < N; x++) {\n                    for (int y = 0; y < N; y++) {\n                        if (dot[x][y]) continue;\n                        add_large_moves(x, y, cands);\n                    }\n                }\n                if (cands.empty()) break;\n            }\n\n            // compute weights\n            vector<int> weights(cands.size());\n            for (size_t i = 0; i < cands.size(); i++)\n                weights[i] = weight[cands[i][0].x][cands[i][0].y];\n\n            int max_w = *max_element(weights.begin(), weights.end());\n            vector<int> top_idx;\n            for (size_t i = 0; i < cands.size(); i++)\n                if (weights[i] == max_w) top_idx.push_back(static_cast<int>(i));\n\n            int pick;\n            // 80% choose among best, 20% random\n            if (top_idx.size() == cands.size() || (rng() % 100) < 80) {\n                pick = top_idx[rng() % top_idx.size()];\n            } else {\n                pick = rng() % cands.size();\n            }\n            apply_move(cands[pick]);\n            history.push_back(cands[pick]);\n        }\n        return make_pair(cur_sum, history);\n    };\n\n    long long best_sum = -1;\n    vector<array<Pt, 4>> best_hist;\n    int sim = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > 4.85) break;\n        uint64_t seed = chrono::steady_clock::now().time_since_epoch().count() + sim * 12345;\n        auto result = run_sim(seed);\n        if (result.first > best_sum) {\n            best_sum = result.first;\n            best_hist = move(result.second);\n        }\n        sim++;\n    }\n\n    // output\n    cout << best_hist.size() << \"\\n\";\n    for (auto& p : best_hist) {\n        cout << p[0].x << \" \" << p[0].y << \" \"\n             << p[1].x << \" \" << p[1].y << \" \"\n             << p[2].x << \" \" << p[2].y << \" \"\n             << p[3].x << \" \" << p[3].y << \"\\n\";\n    }\n    return 0;\n}","ahc015":"#include <iostream>\n#include <cstring>\nusing namespace std;\n\n// Direction mapping\nconst char DIR_CHARS[4] = {'F', 'B', 'L', 'R'};\n\n// Fast RNG for sampling empty cells\nstatic unsigned rng_state = 123456789u;\ninline int fast_rand() {\n    rng_state = rng_state * 1103515245u + 12345u;\n    return rng_state & 0x7fffffff;\n}\n\n// Apply a tilt to src, write into dst\nvoid tilt(const int* src, int dir, int* dst) {\n    if (dir == 0) {          // Forward\n        for (int c = 0; c < 10; ++c) {\n            int d = 0;\n            for (int r = 0; r < 10; ++r) {\n                int v = src[r * 10 + c];\n                if (v) dst[d++ * 10 + c] = v;\n            }\n            for (; d < 10; ++d) dst[d * 10 + c] = 0;\n        }\n    } else if (dir == 1) {   // Backward\n        for (int c = 0; c < 10; ++c) {\n            int d = 9;\n            for (int r = 9; r >= 0; --r) {\n                int v = src[r * 10 + c];\n                if (v) dst[d-- * 10 + c] = v;\n            }\n            for (; d >= 0; --d) dst[d * 10 + c] = 0;\n        }\n    } else if (dir == 2) {   // Left\n        for (int r = 0; r < 10; ++r) {\n            int base = r * 10;\n            int d = 0;\n            for (int c = 0; c < 10; ++c) {\n                int v = src[base + c];\n                if (v) dst[base + d++] = v;\n            }\n            for (; d < 10; ++d) dst[base + d] = 0;\n        }\n    } else {                 // Right\n        for (int r = 0; r < 10; ++r) {\n            int base = r * 10;\n            int d = 9;\n            for (int c = 9; c >= 0; --c) {\n                int v = src[base + c];\n                if (v) dst[base + d--] = v;\n            }\n            for (; d >= 0; --d) dst[base + d] = 0;\n        }\n    }\n}\n\n// Compute sum of squares of connected components\nint sum_sq(const int* b) {\n    static int q[100];\n    static int vis[100];\n    static int ver = 0;\n    ++ver;\n    int sq = 0;\n    for (int i = 0; i < 100; ++i) {\n        if (b[i] != 0 && vis[i] != ver) {\n            int flavor = b[i];\n            int head = 0, tail = 0;\n            q[tail++] = i;\n            vis[i] = ver;\n            int size = 0;\n            while (head < tail) {\n                int idx = q[head++];\n                ++size;\n                int r = idx / 10, c = idx % 10;\n                if (r > 0) {\n                    int ni = idx - 10;\n                    if (b[ni] == flavor && vis[ni] != ver) {\n                        vis[ni] = ver; q[tail++] = ni;\n                    }\n                }\n                if (r < 9) {\n                    int ni = idx + 10;\n                    if (b[ni] == flavor && vis[ni] != ver) {\n                        vis[ni] = ver; q[tail++] = ni;\n                    }\n                }\n                if (c > 0) {\n                    int ni = idx - 1;\n                    if (b[ni] == flavor && vis[ni] != ver) {\n                        vis[ni] = ver; q[tail++] = ni;\n                    }\n                }\n                if (c < 9) {\n                    int ni = idx + 1;\n                    if (b[ni] == flavor && vis[ni] != ver) {\n                        vis[ni] = ver; q[tail++] = ni;\n                    }\n                }\n            }\n            sq += size * size;\n        }\n    }\n    return sq;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int flavors[100];\n    for (int i = 0; i < 100; ++i) {\n        cin >> flavors[i];\n    }\n\n    int board[100] = {0};\n\n    const int SAMPLE_SIZE = 5;\n\n    for (int t = 0; t < 100; ++t) {\n        int p;\n        cin >> p;\n\n        // Find the p-th empty cell (1-indexed, front-to-back, left-to-right)\n        int pos = -1;\n        int cnt = 0;\n        for (int i = 0; i < 100; ++i) {\n            if (board[i] == 0) {\n                ++cnt;\n                if (cnt == p) {\n                    pos = i;\n                    break;\n                }\n            }\n        }\n        board[pos] = flavors[t];\n\n        // Last candy: tilt does nothing, any output works\n        if (t == 99) {\n            cout << \"F\\n\" << flush;\n            break;\n        }\n\n        int best_dir = 0;\n        double best_val = -1e18;\n        int next_flavor = flavors[t + 1];\n\n        for (int d = 0; d < 4; ++d) {\n            int b1[100];\n            tilt(board, d, b1);\n\n            // Gather empty cells in b1\n            int empty_idx[100];\n            int n_empty = 0;\n            for (int i = 0; i < 100; ++i) {\n                if (b1[i] == 0) empty_idx[n_empty++] = i;\n            }\n\n            double val;\n            if (n_empty == 0) {\n                val = sum_sq(b1);  // should not happen before step 99\n            } else {\n                int sample_cnt = (n_empty > SAMPLE_SIZE) ? SAMPLE_SIZE : n_empty;\n                double sum_max = 0.0;\n                for (int s = 0; s < sample_cnt; ++s) {\n                    int e_idx;\n                    if (n_empty <= SAMPLE_SIZE) {\n                        e_idx = empty_idx[s];\n                    } else {\n                        e_idx = empty_idx[fast_rand() % n_empty];\n                    }\n\n                    int b2[100];\n                    memcpy(b2, b1, sizeof(b1));\n                    b2[e_idx] = next_flavor;\n\n                    int best_d2_sq = -1;\n                    for (int d2 = 0; d2 < 4; ++d2) {\n                        int b3[100];\n                        tilt(b2, d2, b3);\n                        int sq = sum_sq(b3);\n                        if (sq > best_d2_sq) best_d2_sq = sq;\n                    }\n                    sum_max += best_d2_sq;\n                }\n                val = sum_max / sample_cnt;\n            }\n\n            if (val > best_val) {\n                best_val = val;\n                best_dir = d;\n            }\n        }\n\n        cout << DIR_CHARS[best_dir] << '\\n' << flush;\n\n        // Apply the chosen tilt to the real board for the next step\n        int next_board[100];\n        tilt(board, best_dir, next_board);\n        memcpy(board, next_board, sizeof(board));\n    }\n\n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <numeric>\n\nusing namespace std;\n\nstruct GraphInfo {\n    vector<vector<bool>> mat;\n    vector<int> sorted_deg;\n    string adj_str;\n};\n\n// Build M threshold graphs with minimum L1 distance between degree sequences\n// based on target D_min derived from epsilon and N.\nvector<GraphInfo> build_threshold_graphs(int N, int M, double eps, mt19937& rng) {\n    int L = N * (N - 1) / 2;\n    double sigma = 2.0 * sqrt(L * eps * (1.0 - eps));\n    // try different multipliers for minimum distance\n    vector<int> d_targets;\n    for (int mult = 6; mult >= 1; mult--) {\n        int d = max(1, (int)ceil(mult * sigma));\n        d_targets.push_back(d);\n    }\n    \n    int pool_size = max(M * 50, 30000);\n    bernoulli_distribution bit_dist(0.5);\n    \n    // generate a large pool of random threshold graphs\n    struct Candidate {\n        vector<int> deg;\n        string adj;\n    };\n    vector<Candidate> pool;\n    pool.reserve(pool_size);\n    \n    for (int idx = 0; idx < pool_size; idx++) {\n        // binary signature c[0] = 0, c[1..N-1] random bits\n        vector<int> c(N, 0);\n        for (int j = 1; j < N; j++) c[j] = bit_dist(rng) ? 1 : 0;\n        \n        // compute suffix sums of c\n        vector<int> suff(N+1, 0);\n        for (int j = N-1; j >= 0; j--) {\n            suff[j] = suff[j+1] + c[j];\n        }\n        \n        // compute degrees\n        vector<int> deg(N);\n        for (int i = 0; i < N; i++) {\n            deg[i] = suff[i+1] + (c[i] ? i : 0);\n        }\n        sort(deg.begin(), deg.end(), greater<int>());\n        \n        // build adjacency string in lexicographic order\n        string adj(L, '0');\n        int pos = 0;\n        for (int i = 0; i < N; i++) {\n            for (int j = i+1; j < N; j++) {\n                if (c[j] == 1) adj[pos] = '1';\n                pos++;\n            }\n        }\n        pool.push_back({move(deg), move(adj)});\n    }\n    \n    // Greedy selection trying each target distance\n    for (int D_min : d_targets) {\n        vector<Candidate> selected;\n        selected.reserve(M);\n        // randomise order\n        shuffle(pool.begin(), pool.end(), rng);\n        for (auto& cand : pool) {\n            bool ok = true;\n            for (auto& sel : selected) {\n                int dist = 0;\n                for (int i = 0; i < N; i++) {\n                    dist += abs(cand.deg[i] - sel.deg[i]);\n                }\n                if (dist < D_min) {\n                    ok = false;\n                    break;\n                }\n            }\n            if (ok) {\n                selected.push_back(cand);\n                if ((int)selected.size() == M) break;\n            }\n        }\n        if ((int)selected.size() == M) {\n            // convert to GraphInfo (with matrix for simulation)\n            vector<GraphInfo> graphs;\n            graphs.reserve(M);\n            for (auto& sel : selected) {\n                // build matrix from adj_str\n                vector<vector<bool>> mat(N, vector<bool>(N, false));\n                int pos = 0;\n                for (int i = 0; i < N; i++) {\n                    for (int j = i+1; j < N; j++) {\n                        if (sel.adj[pos] == '1') {\n                            mat[i][j] = mat[j][i] = true;\n                        }\n                        pos++;\n                    }\n                }\n                graphs.push_back({move(mat), move(sel.deg), move(sel.adj)});\n            }\n            return graphs;\n        }\n    }\n    return {}; // failed\n}\n\n// Simulate 100 queries and return number of wrong predictions\nint simulate_errors(int N, const vector<GraphInfo>& graphs, double eps, mt19937& rng) {\n    int M = (int)graphs.size();\n    uniform_int_distribution<int> s_dist(0, M-1);\n    uniform_real_distribution<double> flip_dist(0.0, 1.0);\n    int errors = 0;\n    \n    for (int q = 0; q < 100; q++) {\n        int s = s_dist(rng);\n        auto noisy_mat = graphs[s].mat;\n        \n        // apply noise\n        for (int i = 0; i < N; i++) {\n            for (int j = i+1; j < N; j++) {\n                if (flip_dist(rng) < eps) {\n                    noisy_mat[i][j] = !noisy_mat[i][j];\n                    noisy_mat[j][i] = noisy_mat[i][j];\n                }\n            }\n        }\n        \n        // random shuffle\n        vector<int> perm(N);\n        iota(perm.begin(), perm.end(), 0);\n        shuffle(perm.begin(), perm.end(), rng);\n        \n        // build H_mat using the permuted indices\n        vector<vector<bool>> H_mat(N, vector<bool>(N, false));\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (noisy_mat[i][j]) {\n                    int ui = perm[i], uj = perm[j];\n                    H_mat[ui][uj] = true;\n                }\n            }\n        }\n        \n        // compute degrees of H (undirected, no self-loops)\n        vector<int> H_deg(N, 0);\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (H_mat[i][j]) H_deg[i]++;\n            }\n        }\n        sort(H_deg.begin(), H_deg.end(), greater<int>());\n        \n        // nearest neighbour\n        int best_t = 0;\n        int best_dist = 1e9;\n        for (int t = 0; t < M; t++) {\n            int dist = 0;\n            for (int i = 0; i < N; i++) {\n                dist += abs(H_deg[i] - graphs[t].sorted_deg[i]);\n            }\n            if (dist < best_dist) {\n                best_dist = dist;\n                best_t = t;\n            }\n        }\n        if (best_t != s) errors++;\n    }\n    return errors;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int M;\n    double eps;\n    cin >> M >> eps;\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    double best_score = -1.0;\n    int best_N = 20;\n    vector<GraphInfo> best_graphs;\n    \n    auto start_time = chrono::steady_clock::now();\n    auto time_limit = chrono::milliseconds(4700);\n    \n    // Search over possible number of vertices\n    for (int N = 4; N <= 100; N++) {\n        auto now = chrono::steady_clock::now();\n        if (now - start_time > time_limit) break;\n        \n        auto graphs = build_threshold_graphs(N, M, eps, rng);\n        if (graphs.empty()) continue;\n        \n        // evaluate by simulation\n        int total_err = 0;\n        int sims = 3;\n        for (int s = 0; s < sims; s++) {\n            total_err += simulate_errors(N, graphs, eps, rng);\n        }\n        double avg_err = (double)total_err / sims;\n        double score = round(1e9 * pow(0.9, avg_err) / N);\n        \n        if (score > best_score) {\n            best_score = score;\n            best_N = N;\n            best_graphs = move(graphs);\n        }\n    }\n    \n    // Fallback: if nothing succeeded, create a simple set\n    if (best_graphs.empty()) {\n        int N = 20;\n        best_N = N;\n        best_graphs = build_threshold_graphs(N, M, eps, rng);\n    }\n    \n    // Output the chosen graphs\n    cout << best_N << \"\\n\";\n    for (auto& g : best_graphs) {\n        cout << g.adj_str << \"\\n\";\n    }\n    cout.flush();\n    \n    // Answer 100 queries\n    int N = best_N;\n    for (int q = 0; q < 100; q++) {\n        string H_str;\n        cin >> H_str;\n        \n        // compute sorted degree sequence\n        vector<int> H_deg(N, 0);\n        int pos = 0;\n        for (int i = 0; i < N; i++) {\n            for (int j = i+1; j < N; j++) {\n                if (H_str[pos] == '1') {\n                    H_deg[i]++;\n                    H_deg[j]++;\n                }\n                pos++;\n            }\n        }\n        sort(H_deg.begin(), H_deg.end(), greater<int>());\n        \n        // nearest neighbour among the stored candidates\n        int best_t = 0;\n        int best_dist = 1e9;\n        for (int t = 0; t < M; t++) {\n            int dist = 0;\n            for (int i = 0; i < N; i++) {\n                dist += abs(H_deg[i] - best_graphs[t].sorted_deg[i]);\n            }\n            if (dist < best_dist) {\n                best_dist = dist;\n                best_t = t;\n            }\n        }\n        cout << best_t << \"\\n\";\n        cout.flush();\n    }\n    \n    return 0;\n}","ahc017":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <chrono>\n#include <limits>\n#include <tuple>\nusing namespace std;\nusing ll = long long;\n\nconst int INF = 1'000'000'000;\n\nint main() {\n    auto start_time = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count();\n    };\n    \n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n    vector<int> U(M), V(M), W(M);\n    vector<vector<tuple<int,int,int>>> orig_adj(N); // to, weight, edge_id\n    vector<int> edge_idx(N*N, -1);\n    for (int i = 0; i < M; ++i) {\n        cin >> U[i] >> V[i] >> W[i];\n        --U[i]; --V[i];\n        orig_adj[U[i]].emplace_back(V[i], W[i], i);\n        orig_adj[V[i]].emplace_back(U[i], W[i], i);\n        edge_idx[U[i]*N + V[i]] = i;\n        edge_idx[V[i]*N + U[i]] = i;\n    }\n    // read and ignore coordinates\n    int dummy;\n    for (int i = 0; i < N; ++i) cin >> dummy >> dummy;\n    \n    // Compute original all-pairs shortest paths and edge centralities\n    vector<int> orig(N*N, INF);\n    vector<ll> cnt(M, 0);\n    vector<int> dist(N);\n    priority_queue<pair<int,int>, vector<pair<int,int>>, greater<>> pq;\n    \n    for (int s = 0; s < N; ++s) {\n        fill(dist.begin(), dist.end(), INF);\n        vector<int> parent_node(N, -1);\n        vector<int> parent_edge(N, -1);\n        dist[s] = 0;\n        pq.push({0, s});\n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop();\n            if (d != dist[u]) continue;\n            for (auto &edge : orig_adj[u]) {\n                int v = get<0>(edge), w = get<1>(edge), eid = get<2>(edge);\n                if (dist[v] > d + w) {\n                    dist[v] = d + w;\n                    parent_node[v] = u;\n                    parent_edge[v] = eid;\n                    pq.push({dist[v], v});\n                }\n            }\n        }\n        for (int t = 0; t < N; ++t) {\n            orig[s*N + t] = dist[t];\n        }\n        // compute subtree sizes for centrality\n        vector<int> sub(N, 1);\n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) { return dist[a] > dist[b]; });\n        for (int v : order) {\n            if (v == s) continue;\n            int p = parent_node[v];\n            if (p != -1) {\n                sub[p] += sub[v];\n                if (parent_edge[v] != -1) {\n                    cnt[parent_edge[v]] += sub[v];\n                }\n            }\n        }\n    }\n    \n    // Greedy assignment based on cnt\n    vector<int> assign(M, -1);\n    vector<int> day_cnt(D, 0);\n    vector<ll> day_sum_cnt(D, 0);\n    vector<int> sorted_edges(M);\n    iota(sorted_edges.begin(), sorted_edges.end(), 0);\n    sort(sorted_edges.begin(), sorted_edges.end(), [&](int a, int b) { return cnt[a] > cnt[b]; });\n    for (int e : sorted_edges) {\n        int best_d = -1;\n        ll best_sum = numeric_limits<ll>::max();\n        for (int d = 0; d < D; ++d) {\n            if (day_cnt[d] < K && day_sum_cnt[d] < best_sum) {\n                best_sum = day_sum_cnt[d];\n                best_d = d;\n            }\n        }\n        assign[e] = best_d;\n        day_cnt[best_d]++;\n        day_sum_cnt[best_d] += cnt[e];\n    }\n    \n    // Store day edges\n    vector<vector<int>> day_edges(D);\n    for (int e = 0; e < M; ++e) {\n        day_edges[assign[e]].push_back(e);\n    }\n    \n    // Exact evaluation helper\n    vector<bool> removed(M);\n    auto compute_day_dist = [&](const vector<int>& removed_edges, vector<int>& out_dist, ll& out_diff) {\n        fill(removed.begin(), removed.end(), false);\n        for (int e : removed_edges) removed[e] = true;\n        out_dist.assign(N*N, INF);\n        out_diff = 0;\n        for (int s = 0; s < N; ++s) {\n            fill(dist.begin(), dist.end(), INF);\n            dist[s] = 0;\n            pq.push({0, s});\n            while (!pq.empty()) {\n                auto [d, u] = pq.top(); pq.pop();\n                if (d != dist[u]) continue;\n                for (auto &edge : orig_adj[u]) {\n                    int v = get<0>(edge), w = get<1>(edge), eid = get<2>(edge);\n                    if (removed[eid]) continue;\n                    if (dist[v] > d + w) {\n                        dist[v] = d + w;\n                        pq.push({dist[v], v});\n                    }\n                }\n            }\n            int base = s * N;\n            for (int t = 0; t < N; ++t) {\n                out_dist[base + t] = dist[t];\n            }\n            for (int t = s+1; t < N; ++t) {\n                out_diff += dist[t] - orig[base + t];\n            }\n        }\n    };\n    \n    // Initial exact evaluation\n    vector<vector<int>> day_dist(D);\n    vector<ll> day_diff(D, 0);\n    ll total_diff = 0;\n    for (int d = 0; d < D; ++d) {\n        compute_day_dist(day_edges[d], day_dist[d], day_diff[d]);\n        total_diff += day_diff[d];\n    }\n    ll best_total_diff = total_diff;\n    vector<int> best_assign = assign;\n    \n    // Local search\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> real_dist(0.0, 1.0);\n    \n    const int TIME_LIMIT_MS = 5800;\n    while (elapsed() < TIME_LIMIT_MS) {\n        // Pick a day A weighted by day_diff\n        ll sum_weights = accumulate(day_diff.begin(), day_diff.end(), 0LL);\n        int A;\n        if (sum_weights > 0) {\n            discrete_distribution<int> day_sel(day_diff.begin(), day_diff.end());\n            A = day_sel(rng);\n        } else {\n            uniform_int_distribution<int> unif(0, D-1);\n            A = unif(rng);\n        }\n        if (day_edges[A].empty()) continue;\n        \n        // Pick a random edge in A\n        uniform_int_distribution<int> edge_sel_A(0, (int)day_edges[A].size() - 1);\n        int e = day_edges[A][edge_sel_A(rng)];\n        \n        // Pick a random B != A with capacity\n        vector<int> candidates;\n        for (int d = 0; d < D; ++d) {\n            if (d != A && day_cnt[d] < K) candidates.push_back(d);\n        }\n        if (candidates.empty()) continue;\n        uniform_int_distribution<int> cand_sel(0, (int)candidates.size() - 1);\n        int B = candidates[cand_sel(rng)];\n        \n        // Evaluate move: remove e from A, add e to B\n        vector<int> new_A_edges = day_edges[A];\n        new_A_edges.erase(remove(new_A_edges.begin(), new_A_edges.end(), e), new_A_edges.end());\n        vector<int> new_dA;\n        ll new_diffA;\n        compute_day_dist(new_A_edges, new_dA, new_diffA);\n        \n        // New B: S_B U {e} (incremental update)\n        vector<int> oldB = day_dist[B];\n        vector<int> new_dB = oldB;\n        int u = U[e], v = V[e], w = W[e];\n        for (int i = 0; i < N; ++i) {\n            int iu = oldB[i*N + u];\n            int iv = oldB[i*N + v];\n            int base_i = i * N;\n            for (int j = 0; j < N; ++j) {\n                int idx = base_i + j;\n                int via_u = iu + w + oldB[v*N + j];\n                int via_v = iv + w + oldB[u*N + j];\n                if (via_u < new_dB[idx]) new_dB[idx] = via_u;\n                if (via_v < new_dB[idx]) new_dB[idx] = via_v;\n            }\n        }\n        ll new_diffB = 0;\n        for (int i = 0; i < N; ++i) {\n            int base = i * N;\n            for (int j = i+1; j < N; ++j) {\n                new_diffB += new_dB[base + j] - orig[base + j];\n            }\n        }\n        \n        ll new_total_diff = total_diff - day_diff[A] - day_diff[B] + new_diffA + new_diffB;\n        if (new_total_diff < total_diff) {\n            // Accept move\n            assign[e] = B;\n            day_cnt[A]--;\n            day_cnt[B]++;\n            auto &vecA = day_edges[A];\n            vecA.erase(remove(vecA.begin(), vecA.end(), e), vecA.end());\n            day_edges[B].push_back(e);\n            day_dist[A] = move(new_dA);\n            day_dist[B] = move(new_dB);\n            day_diff[A] = new_diffA;\n            day_diff[B] = new_diffB;\n            total_diff = new_total_diff;\n            if (total_diff < best_total_diff) {\n                best_total_diff = total_diff;\n                best_assign = assign;\n            }\n        }\n    }\n    \n    // Output best assignment\n    for (int i = 0; i < M; ++i) {\n        if (i) cout << \" \";\n        cout << best_assign[i] + 1;\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc019":"#include <iostream>\n#include <vector>\n#include <string>\n#include <tuple>\n#include <algorithm>\n\nusing namespace std;\n\nconst int perms[6][3] = {{0,1,2},{0,2,1},{1,0,2},{1,2,0},{2,0,1},{2,1,0}};\n\nint main() {\n    int D;\n    cin >> D;\n    vector<string> f[2], r[2];\n    for (int i = 0; i < 2; i++) {\n        f[i].resize(D);\n        for (int k = 0; k < D; k++) cin >> f[i][k];\n        r[i].resize(D);\n        for (int k = 0; k < D; k++) cin >> r[i][k];\n    }\n\n    int total = D * D * D;\n    vector<bool> allowed[2], used[2];\n    vector<vector<bool>> uncov_f[2], uncov_r[2];\n    vector<int> bid[2];\n\n    for (int i = 0; i < 2; i++) {\n        allowed[i].assign(total, false);\n        used[i].assign(total, false);\n        uncov_f[i].assign(D, vector<bool>(D, false));\n        uncov_r[i].assign(D, vector<bool>(D, false));\n        bid[i].assign(total, 0);\n    }\n\n    auto idx = [&](int x, int y, int z) {\n        return x * D * D + y * D + z;\n    };\n\n    // Initialize allowed and uncovered\n    for (int i = 0; i < 2; i++) {\n        for (int z = 0; z < D; z++) {\n            for (int x = 0; x < D; x++) {\n                if (f[i][z][x] == '1') uncov_f[i][z][x] = true;\n            }\n            for (int y = 0; y < D; y++) {\n                if (r[i][z][y] == '1') uncov_r[i][z][y] = true;\n            }\n        }\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    if (f[i][z][x] == '1' && r[i][z][y] == '1') {\n                        allowed[i][idx(x, y, z)] = true;\n                    }\n                }\n            }\n        }\n    }\n\n    auto can_place = [&](int i, int x0, int y0, int z0, int dx, int dy, int dz) {\n        for (int x = x0; x < x0 + dx; x++)\n            for (int y = y0; y < y0 + dy; y++)\n                for (int z = z0; z < z0 + dz; z++)\n                    if (!allowed[i][idx(x, y, z)] || used[i][idx(x, y, z)])\n                        return false;\n        return true;\n    };\n\n    auto count_covered = [&](int i, int x0, int y0, int z0, int dx, int dy, int dz) {\n        bool fc[14][14] = {false}, rc[14][14] = {false};\n        for (int x = x0; x < x0 + dx; x++)\n            for (int y = y0; y < y0 + dy; y++)\n                for (int z = z0; z < z0 + dz; z++) {\n                    if (uncov_f[i][z][x]) fc[z][x] = true;\n                    if (uncov_r[i][z][y]) rc[z][y] = true;\n                }\n        int cnt = 0;\n        for (int z = 0; z < D; z++) for (int x = 0; x < D; x++) if (fc[z][x]) cnt++;\n        for (int z = 0; z < D; z++) for (int y = 0; y < D; y++) if (rc[z][y]) cnt++;\n        return cnt;\n    };\n\n    auto apply_placement = [&](int i, int x0, int y0, int z0, int dx, int dy, int dz, int b_id) {\n        for (int x = x0; x < x0 + dx; x++)\n            for (int y = y0; y < y0 + dy; y++)\n                for (int z = z0; z < z0 + dz; z++) {\n                    int id = idx(x, y, z);\n                    used[i][id] = true;\n                    bid[i][id] = b_id;\n                    uncov_f[i][z][x] = false;\n                    uncov_r[i][z][y] = false;\n                }\n    };\n\n    auto compute_maximal_box = [&](int i, int sx, int sy, int sz,\n                                   int &x0, int &y0, int &z0, int &dx, int &dy, int &dz) {\n        x0 = sx; y0 = sy; z0 = sz;\n        int x1 = sx, y1 = sy, z1 = sz;\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            while (x0 > 0) {\n                bool ok = true;\n                for (int y = y0; y <= y1 && ok; y++)\n                    for (int z = z0; z <= z1 && ok; z++)\n                        if (!allowed[i][idx(x0-1, y, z)] || used[i][idx(x0-1, y, z)]) ok = false;\n                if (ok) { x0--; changed = true; } else break;\n            }\n            while (x1 < D-1) {\n                bool ok = true;\n                for (int y = y0; y <= y1 && ok; y++)\n                    for (int z = z0; z <= z1 && ok; z++)\n                        if (!allowed[i][idx(x1+1, y, z)] || used[i][idx(x1+1, y, z)]) ok = false;\n                if (ok) { x1++; changed = true; } else break;\n            }\n            while (y0 > 0) {\n                bool ok = true;\n                for (int x = x0; x <= x1 && ok; x++)\n                    for (int z = z0; z <= z1 && ok; z++)\n                        if (!allowed[i][idx(x, y0-1, z)] || used[i][idx(x, y0-1, z)]) ok = false;\n                if (ok) { y0--; changed = true; } else break;\n            }\n            while (y1 < D-1) {\n                bool ok = true;\n                for (int x = x0; x <= x1 && ok; x++)\n                    for (int z = z0; z <= z1 && ok; z++)\n                        if (!allowed[i][idx(x, y1+1, z)] || used[i][idx(x, y1+1, z)]) ok = false;\n                if (ok) { y1++; changed = true; } else break;\n            }\n            while (z0 > 0) {\n                bool ok = true;\n                for (int x = x0; x <= x1 && ok; x++)\n                    for (int y = y0; y <= y1 && ok; y++)\n                        if (!allowed[i][idx(x, y, z0-1)] || used[i][idx(x, y, z0-1)]) ok = false;\n                if (ok) { z0--; changed = true; } else break;\n            }\n            while (z1 < D-1) {\n                bool ok = true;\n                for (int x = x0; x <= x1 && ok; x++)\n                    for (int y = y0; y <= y1 && ok; y++)\n                        if (!allowed[i][idx(x, y, z1+1)] || used[i][idx(x, y, z1+1)]) ok = false;\n                if (ok) { z1++; changed = true; } else break;\n            }\n        }\n        dx = x1 - x0 + 1;\n        dy = y1 - y0 + 1;\n        dz = z1 - z0 + 1;\n    };\n\n    auto find_best_placement = [&](int j, int dx, int dy, int dz,\n                                   int &bx0, int &by0, int &bz0, int &bdx, int &bdy, int &bdz) {\n        int best_cc = -1;\n        int dims[3] = {dx, dy, dz};\n        for (auto &p : perms) {\n            int gdx = dims[p[0]], gdy = dims[p[1]], gdz = dims[p[2]];\n            for (int x0 = 0; x0 <= D - gdx; x0++) {\n                for (int y0 = 0; y0 <= D - gdy; y0++) {\n                    for (int z0 = 0; z0 <= D - gdz; z0++) {\n                        if (can_place(j, x0, y0, z0, gdx, gdy, gdz)) {\n                            int cc = count_covered(j, x0, y0, z0, gdx, gdy, gdz);\n                            if (cc > best_cc) {\n                                best_cc = cc;\n                                bx0 = x0; by0 = y0; bz0 = z0;\n                                bdx = gdx; bdy = gdy; bdz = gdz;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        return best_cc >= 0;\n    };\n\n    struct Block {\n        // for debugging / not strictly needed\n        int dx, dy, dz;\n    };\n    vector<Block> blocks;\n\n    while (true) {\n        int uncov_cnt[2] = {0, 0};\n        for (int i = 0; i < 2; i++) {\n            for (int z = 0; z < D; z++) {\n                for (int x = 0; x < D; x++) if (uncov_f[i][z][x]) uncov_cnt[i]++;\n                for (int y = 0; y < D; y++) if (uncov_r[i][z][y]) uncov_cnt[i]++;\n            }\n        }\n        if (uncov_cnt[0] == 0 && uncov_cnt[1] == 0) break;\n\n        int i = (uncov_cnt[0] >= uncov_cnt[1]) ? 0 : 1;\n        int j = 1 - i;\n\n        int z_sel = -1, x_sel = -1, y_sel = -1;\n        bool is_front = false;\n        for (int z = 0; z < D && z_sel == -1; z++) {\n            for (int x = 0; x < D; x++) if (uncov_f[i][z][x]) {\n                z_sel = z; x_sel = x; is_front = true; break;\n            }\n            if (z_sel == -1) {\n                for (int y = 0; y < D; y++) if (uncov_r[i][z][y]) {\n                    z_sel = z; y_sel = y; is_front = false; break;\n                }\n            }\n        }\n\n        vector<tuple<int,int,int>> seeds;\n        if (is_front) {\n            for (int y = 0; y < D; y++) {\n                if (allowed[i][idx(x_sel, y, z_sel)] && !used[i][idx(x_sel, y, z_sel)])\n                    seeds.emplace_back(x_sel, y, z_sel);\n            }\n        } else {\n            for (int x = 0; x < D; x++) {\n                if (allowed[i][idx(x, y_sel, z_sel)] && !used[i][idx(x, y_sel, z_sel)])\n                    seeds.emplace_back(x, y_sel, z_sel);\n            }\n        }\n        if (seeds.empty()) {\n            for (int x = 0; x < D; x++) for (int y = 0; y < D; y++) for (int z = 0; z < D; z++) {\n                if (allowed[i][idx(x, y, z)] && !used[i][idx(x, y, z)]) {\n                    seeds.emplace_back(x, y, z);\n                    goto seed_done;\n                }\n            }\n            seed_done:;\n        }\n\n        struct SeedInfo {\n            int sx, sy, sz;\n            int x0, y0, z0, dx, dy, dz;\n            int score;\n            bool matchable;\n            int jx0, jy0, jz0, jdx, jdy, jdz;\n        };\n        vector<SeedInfo> infos;\n        for (auto [sx, sy, sz] : seeds) {\n            int x0, y0, z0, dx, dy, dz;\n            compute_maximal_box(i, sx, sy, sz, x0, y0, z0, dx, dy, dz);\n            int vol = dx * dy * dz;\n            int cc = count_covered(i, x0, y0, z0, dx, dy, dz);\n            int score = vol * 1000 + cc;\n            int jx0, jy0, jz0, jdx, jdy, jdz;\n            bool ok = find_best_placement(j, dx, dy, dz, jx0, jy0, jz0, jdx, jdy, jdz);\n            infos.push_back({sx, sy, sz, x0, y0, z0, dx, dy, dz, score, ok, jx0, jy0, jz0, jdx, jdy, jdz});\n        }\n\n        // pick best matchable seed\n        int best_idx = -1;\n        for (int k = 0; k < (int)infos.size(); k++) {\n            if (!infos[k].matchable) continue;\n            if (best_idx == -1 || infos[k].score > infos[best_idx].score)\n                best_idx = k;\n        }\n\n        if (best_idx != -1) {\n            // place in both\n            SeedInfo &info = infos[best_idx];\n            int id = blocks.size() + 1;\n            apply_placement(i, info.x0, info.y0, info.z0, info.dx, info.dy, info.dz, id);\n            apply_placement(j, info.jx0, info.jy0, info.jz0, info.jdx, info.jdy, info.jdz, id);\n            blocks.push_back({info.dx, info.dy, info.dz});\n            continue;\n        }\n\n        // No matchable seed -> try sub-boxes of the best seed (by score)\n        best_idx = 0;\n        for (int k = 1; k < (int)infos.size(); k++) {\n            if (infos[k].score > infos[best_idx].score) best_idx = k;\n        }\n        SeedInfo &best = infos[best_idx];\n        int bx0 = best.x0, by0 = best.y0, bz0 = best.z0;\n        int bdx = best.dx, bdy = best.dy, bdz = best.dz;\n        vector<tuple<int,int,int,int,int,int>> sub_boxes;\n        for (int x0 = bx0; x0 <= best.sx; x0++) {\n            for (int x1 = best.sx; x1 < bx0 + bdx; x1++) {\n                int dx_sub = x1 - x0 + 1;\n                for (int y0 = by0; y0 <= best.sy; y0++) {\n                    for (int y1 = best.sy; y1 < by0 + bdy; y1++) {\n                        int dy_sub = y1 - y0 + 1;\n                        for (int z0 = bz0; z0 <= best.sz; z0++) {\n                            for (int z1 = best.sz; z1 < bz0 + bdz; z1++) {\n                                int dz_sub = z1 - z0 + 1;\n                                sub_boxes.emplace_back(x0, y0, z0, dx_sub, dy_sub, dz_sub);\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        sort(sub_boxes.begin(), sub_boxes.end(), [](auto &a, auto &b) {\n            return get<3>(a)*get<4>(a)*get<5>(a) > get<3>(b)*get<4>(b)*get<5>(b);\n        });\n\n        bool placed_sub = false;\n        for (auto &sub : sub_boxes) {\n            int sx0 = get<0>(sub), sy0 = get<1>(sub), sz0 = get<2>(sub);\n            int sdx = get<3>(sub), sdy = get<4>(sub), sdz = get<5>(sub);\n            int jx0, jy0, jz0, jdx, jdy, jdz;\n            if (find_best_placement(j, sdx, sdy, sdz, jx0, jy0, jz0, jdx, jdy, jdz)) {\n                int id = blocks.size() + 1;\n                apply_placement(i, sx0, sy0, sz0, sdx, sdy, sdz, id);\n                apply_placement(j, jx0, jy0, jz0, jdx, jdy, jdz, id);\n                blocks.push_back({sdx, sdy, sdz});\n                placed_sub = true;\n                break;\n            }\n        }\n\n        if (!placed_sub) {\n            // fallback: place the best seed's maximal box only in i\n            int id = blocks.size() + 1;\n            apply_placement(i, bx0, by0, bz0, bdx, bdy, bdz, id);\n            blocks.push_back({bdx, bdy, bdz});\n        }\n    }\n\n    int n = blocks.size();\n    cout << n << \"\\n\";\n    for (int i = 0; i < 2; i++) {\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 (x != 0 || y != 0 || z != 0) cout << \" \";\n                    cout << bid[i][idx(x, y, z)];\n                }\n            }\n        }\n        cout << \"\\n\";\n    }\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\nusing int64 = long long;\n\ninline int64 ceil_sqrt(int64 x) {\n    if (x <= 0) return 0;\n    int64 r = (int64)sqrt((long double)x);\n    while (r * r < x) ++r;\n    while (r * r > x) --r; // just in case\n    if (r * r < x) ++r;\n    return r;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start_time = chrono::steady_clock::now();\n    auto elapsed = [&]() { return chrono::duration<double>(chrono::steady_clock::now() - start_time).count(); };\n\n    int N, M, K;\n    cin >> N >> M >> K;\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; ++i) cin >> x[i] >> y[i];\n    vector<tuple<int, int, int>> edges(M);\n    vector<vector<pair<int, int>>> adj(N);\n    for (int j = 0; j < M; ++j) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        --u; --v;\n        edges[j] = {u, v, w};\n        adj[u].push_back({v, w});\n        adj[v].push_back({u, w});\n    }\n    vector<int> a(K), b(K);\n    for (int k = 0; k < K; ++k) cin >> a[k] >> b[k];\n\n    // all-pairs shortest paths (int64) and next node for reconstruction\n    vector<vector<int64>> dist(N, vector<int64>(N));\n    vector<vector<int>> nxt(N, vector<int>(N, -1));\n    for (int s = 0; s < N; ++s) {\n        priority_queue<pair<int64, int>, vector<pair<int64, int>>, greater<>> pq;\n        vector<int64> d(N, numeric_limits<int64>::max());\n        d[s] = 0;\n        pq.push({0, s});\n        while (!pq.empty()) {\n            auto [du, node] = pq.top(); pq.pop();\n            if (du != d[node]) continue;\n            for (auto &[to, w] : adj[node]) {\n                if (d[node] + w < d[to]) {\n                    d[to] = d[node] + w;\n                    pq.push({d[to], to});\n                    nxt[s][to] = node;\n                }\n            }\n        }\n        dist[s] = d;\n    }\n    // nxt[s][s] = s\n    for (int s = 0; s < N; ++s) nxt[s][s] = s;\n\n    // precompute squared Euclidean distances between stations and residents\n    // and lists of residents within 5000 radius (squared distance <= 25000000)\n    vector<vector<int64>> dsq(N, vector<int64>(K));\n    vector<vector<int>> station_res(N);\n    const int64 R2 = 25000000LL; // 5000^2\n    for (int i = 0; i < N; ++i) {\n        for (int k = 0; k < K; ++k) {\n            int64 dx = x[i] - a[k];\n            int64 dy = y[i] - b[k];\n            int64 d2 = dx * dx + dy * dy;\n            dsq[i][k] = d2;\n            if (d2 <= R2) station_res[i].push_back(k);\n        }\n    }\n\n    // cov_count[k] = number of active stations within 5000 of resident k\n    vector<int> cov_count(K, 0);\n\n    auto add_station = [&](int i, vector<bool> &active) {\n        if (active[i]) return;\n        active[i] = true;\n        for (int k : station_res[i]) ++cov_count[k];\n    };\n    auto del_station = [&](int i, vector<bool> &active) {\n        if (!active[i]) return;\n        active[i] = false;\n        for (int k : station_res[i]) --cov_count[k];\n    };\n\n    // evaluate cost of current active set (active[0] must be true)\n    // assumes cov_count[k] > 0 for all k\n    auto evaluate = [&](const vector<bool> &active) -> int64 {\n        vector<int> act;\n        for (int i = 0; i < N; ++i) if (active[i]) act.push_back(i);\n        int t = act.size();\n        int64 tree_cost = 0;\n        if (t > 1) {\n            // MST on complete graph with distances dist[][]\n            vector<bool> inmst(t, false);\n            vector<int64> minw(t, numeric_limits<int64>::max());\n            minw[0] = 0;\n            for (int i = 0; i < t; ++i) {\n                int u = -1;\n                for (int j = 0; j < t; ++j)\n                    if (!inmst[j] && (u == -1 || minw[j] < minw[u])) u = j;\n                inmst[u] = true;\n                tree_cost += minw[u];\n                for (int v = 0; v < t; ++v) {\n                    if (!inmst[v]) {\n                        int64 wgt = dist[act[u]][act[v]];\n                        if (wgt < minw[v]) minw[v] = wgt;\n                    }\n                }\n            }\n        }\n        // power cost: nearest active station for each resident, track max squared distance\n        vector<int64> max_dsq(N, 0);\n        for (int k = 0; k < K; ++k) {\n            int best_i = -1;\n            int64 best_d = numeric_limits<int64>::max();\n            for (int i : act) {\n                int64 d = dsq[i][k];\n                if (d < best_d) {\n                    best_d = d;\n                    best_i = i;\n                }\n            }\n            if (best_d > max_dsq[best_i]) max_dsq[best_i] = best_d;\n        }\n        int64 power_cost = 0;\n        for (int i = 0; i < N; ++i) {\n            if (max_dsq[i] > 0) {\n                int64 P = ceil_sqrt(max_dsq[i]);\n                if (P > 5000) return numeric_limits<int64>::max();\n                power_cost += P * P;\n            }\n        }\n        return tree_cost + power_cost;\n    };\n\n    // initial active set: greedy set cover to cover all residents\n    vector<bool> cur_active(N, false);\n    cur_active[0] = true;\n    add_station(0, cur_active);\n    vector<bool> covered(K, false);\n    int uncovered = K;\n    for (int k : station_res[0]) { covered[k] = true; --uncovered; }\n    while (uncovered > 0) {\n        int best_i = -1;\n        int best_cov = 0;\n        for (int i = 1; i < N; ++i) {\n            if (cur_active[i]) continue;\n            int cnt = 0;\n            for (int k : station_res[i]) if (!covered[k]) ++cnt;\n            if (cnt > best_cov) { best_cov = cnt; best_i = i; }\n        }\n        if (best_i == -1) break; // should not happen\n        add_station(best_i, cur_active);\n        for (int k : station_res[best_i]) if (!covered[k]) { covered[k] = true; --uncovered; }\n    }\n    // if still uncovered, activate all stations that can cover any uncovered (fallback)\n    for (int i = 1; i < N && uncovered > 0; ++i) {\n        if (!cur_active[i]) {\n            for (int k : station_res[i]) if (!covered[k]) {\n                add_station(i, cur_active);\n                for (int kk : station_res[i]) if (!covered[kk]) { covered[kk] = true; --uncovered; }\n                break;\n            }\n        }\n    }\n    cur_active[0] = true; // ensure\n\n    int64 cur_cost = evaluate(cur_active);\n    vector<bool> best_active = cur_active;\n    int64 best_cost = cur_cost;\n\n    // SA\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> rand_vertex(1, N - 1);\n    uniform_real_distribution<double> rand_double(0.0, 1.0);\n\n    double T_start = max(1e6, (double)cur_cost * 0.05);\n    double T_end = T_start * 1e-6;\n    int64 prev_cost = cur_cost;\n    double start_time_sa = elapsed();\n\n    while (elapsed() < 1.9) {\n        double frac = (elapsed() - start_time_sa) / (1.9 - start_time_sa);\n        double T = T_start * pow(T_end / T_start, frac);\n        if (T < 1e-9) T = 1e-9;\n\n        int i = rand_vertex(rng);\n        bool old = cur_active[i];\n        int delta_cov = 0;\n        // toggle temporarily\n        if (old) {\n            del_station(i, cur_active);\n            // check coverage\n            bool ok = true;\n            for (int k : station_res[i]) if (cov_count[k] == 0) { ok = false; break; }\n            if (!ok) {\n                add_station(i, cur_active);\n                continue;\n            }\n        } else {\n            add_station(i, cur_active);\n        }\n\n        int64 new_cost = evaluate(cur_active);\n        bool accept = (new_cost < cur_cost);\n        if (!accept && new_cost != numeric_limits<int64>::max()) {\n            double delta = (double)(int64)(new_cost - cur_cost);\n            double prob = exp(-delta / T);\n            if (rand_double(rng) < prob) accept = true;\n        }\n        if (accept) {\n            cur_cost = new_cost;\n            if (new_cost < best_cost) {\n                best_cost = new_cost;\n                best_active = cur_active;\n            }\n        } else {\n            // revert\n            if (old) add_station(i, cur_active);\n            else del_station(i, cur_active);\n        }\n    }\n\n    // final hill-climbing\n    bool improved = true;\n    while (improved && elapsed() < 1.95) {\n        improved = false;\n        for (int i = 1; i < N; ++i) {\n            bool old = cur_active[i];\n            if (old) {\n                del_station(i, cur_active);\n                bool ok = true;\n                for (int k : station_res[i]) if (cov_count[k] == 0) { ok = false; break; }\n                if (!ok) { add_station(i, cur_active); continue; }\n            } else {\n                add_station(i, cur_active);\n            }\n            int64 new_cost = evaluate(cur_active);\n            if (new_cost < cur_cost) {\n                cur_cost = new_cost;\n                if (new_cost < best_cost) {\n                    best_cost = new_cost;\n                    best_active = cur_active;\n                }\n                improved = true;\n            } else {\n                if (old) add_station(i, cur_active);\n                else del_station(i, cur_active);\n            }\n        }\n    }\n\n    // --- construct final answer from best_active ---\n    vector<int> act;\n    for (int i = 0; i < N; ++i) if (best_active[i]) act.push_back(i);\n    int t = act.size();\n\n    // edge selection: MST metric tree on terminals, then Kruskal on reachable subgraph\n    vector<pair<int, int>> mst_edges;\n    if (t > 1) {\n        vector<bool> inmst(t, false);\n        vector<int64> minw(t, numeric_limits<int64>::max());\n        vector<int> parent(t, -1);\n        minw[0] = 0;\n        for (int i = 0; i < t; ++i) {\n            int u = -1;\n            for (int j = 0; j < t; ++j)\n                if (!inmst[j] && (u == -1 || minw[j] < minw[u])) u = j;\n            inmst[u] = true;\n            if (parent[u] != -1)\n                mst_edges.push_back({act[u], act[parent[u]]});\n            for (int v = 0; v < t; ++v) {\n                if (!inmst[v]) {\n                    int64 wgt = dist[act[u]][act[v]];\n                    if (wgt < minw[v]) {\n                        minw[v] = wgt;\n                        parent[v] = u;\n                    }\n                }\n            }\n        }\n    }\n\n    set<pair<int, int>> used_edges;\n    auto add_path = [&](int src, int dst) {\n        int cur = dst;\n        while (cur != src) {\n            int p = nxt[src][cur];\n            if (p == -1) break;\n            int a = min(cur, p), b = max(cur, p);\n            used_edges.insert({a, b});\n            cur = p;\n        }\n    };\n    for (auto &[u, v] : mst_edges) add_path(u, v);\n\n    vector<int> final_B(M, 0);\n    vector<bool> reachable(N, false);\n    {\n        vector<vector<int>> radj(N);\n        for (auto &[u, v] : used_edges) {\n            // find edge index\n            for (int j = 0; j < M; ++j) {\n                auto [eu, ev, w] = edges[j];\n                if ((eu == u && ev == v) || (eu == v && ev == u)) {\n                    radj[u].push_back(v);\n                    radj[v].push_back(u);\n                    break;\n                }\n            }\n        }\n        queue<int> q;\n        reachable[0] = true; q.push(0);\n        while (!q.empty()) {\n            int node = q.front(); q.pop();\n            for (int to : radj[node]) {\n                if (!reachable[to]) {\n                    reachable[to] = true;\n                    q.push(to);\n                }\n            }\n        }\n    }\n\n    // Kruskal on reachable subgraph\n    {\n        vector<tuple<int64, int, int>> edges_sorted;\n        for (int j = 0; j < M; ++j) {\n            auto [u, v, w] = edges[j];\n            if (reachable[u] && reachable[v]) {\n                edges_sorted.push_back({w, u, v});\n            }\n        }\n        sort(edges_sorted.begin(), edges_sorted.end());\n        vector<int> uf(N);\n        iota(uf.begin(), uf.end(), 0);\n        function<int(int)> find = [&](int x) { return uf[x] == x ? x : uf[x] = find(uf[x]); };\n        int comps = count(reachable.begin(), reachable.end(), true);\n        int used_cnt = 0;\n        for (auto &[w, u, v] : edges_sorted) {\n            int ru = find(u), rv = find(v);\n            if (ru != rv) {\n                uf[ru] = rv;\n                // find edge index\n                for (int j = 0; j < M; ++j) {\n                    auto [eu, ev, ww] = edges[j];\n                    if ((eu == u && ev == v) || (eu == v && ev == u)) {\n                        final_B[j] = 1;\n                        break;\n                    }\n                }\n                if (++used_cnt == comps - 1) break;\n            }\n        }\n    }\n\n    vector<int> final_P(N, 0);\n    {\n        vector<int64> max_dsq(N, 0);\n        for (int k = 0; k < K; ++k) {\n            int best_i = -1;\n            int64 best_d = numeric_limits<int64>::max();\n            for (int i : act) {\n                if (!reachable[i]) continue; // only reachable stations can broadcast\n                int64 d = dsq[i][k];\n                if (d < best_d) {\n                    best_d = d;\n                    best_i = i;\n                }\n            }\n            if (best_i != -1 && best_d > max_dsq[best_i])\n                max_dsq[best_i] = best_d;\n        }\n        for (int i : act) {\n            if (reachable[i] && max_dsq[i] > 0) {\n                int64 P = ceil_sqrt(max_dsq[i]);\n                if (P > 5000) P = 5000;\n                final_P[i] = (int)P;\n            }\n        }\n    }\n\n    // output\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << final_P[i];\n    }\n    cout << '\\n';\n    for (int j = 0; j < M; ++j) {\n        if (j) cout << ' ';\n        cout << final_B[j];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <random>\n#include <cmath>\n#include <chrono>\nusing namespace std;\n\nconst int N = 30;\nconst int V = N * (N + 1) / 2;   // 465\n\nint xc[V], yc[V];\nint id(int x, int y) { return x * (x + 1) / 2 + y; }\n\nbool is_anc(int a, int b) {\n    int xa = xc[a], ya = yc[a];\n    int xb = xc[b], yb = yc[b];\n    if (xa > xb) return false;\n    if (ya > yb) return false;\n    if (yb - ya > xb - xa) return false;\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    // init coordinates\n    for (int x = 0; x < N; ++x)\n        for (int y = 0; y <= x; ++y) {\n            int i = id(x, y);\n            xc[i] = x;\n            yc[i] = y;\n        }\n\n    // adjacency, parents, children\n    vector<vector<int>> adj(V), parents(V), children(V);\n    for (int i = 0; i < V; ++i) {\n        int x = xc[i], y = yc[i];\n        if (x > 0) {\n            if (y > 0) {\n                int p = id(x - 1, y - 1);\n                adj[i].push_back(p);\n                parents[i].push_back(p);\n            }\n            if (y <= x - 1) {\n                int p = id(x - 1, y);\n                adj[i].push_back(p);\n                parents[i].push_back(p);\n            }\n        }\n        if (y > 0) adj[i].push_back(id(x, y - 1));\n        if (y < x) adj[i].push_back(id(x, y + 1));\n        if (x < N - 1) {\n            int c1 = id(x + 1, y);\n            int c2 = id(x + 1, y + 1);\n            adj[i].push_back(c1);\n            adj[i].push_back(c2);\n            children[i].push_back(c1);\n            children[i].push_back(c2);\n        }\n    }\n\n    // input\n    vector<int> init_pos(V);\n    vector<int> grid(V);\n    for (int x = 0; x < N; ++x)\n        for (int y = 0; y <= x; ++y) {\n            int v;\n            cin >> v;\n            int node = id(x, y);\n            grid[node] = v;\n            init_pos[v] = node;\n        }\n\n    // precompute all-pairs distances\n    vector<vector<int>> dist(V, vector<int>(V, -1));\n    for (int s = 0; s < V; ++s) {\n        queue<int> q;\n        q.push(s);\n        dist[s][s] = 0;\n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            for (int v : adj[u]) {\n                if (dist[s][v] == -1) {\n                    dist[s][v] = dist[s][u] + 1;\n                    q.push(v);\n                }\n            }\n        }\n    }\n\n    // canonical row assignment for the initial target\n    vector<int> val_row(V);\n    {\n        int cur = 0;\n        for (int r = 0; r < N; ++r)\n            for (int c = 0; c <= r; ++c)\n                val_row[cur++] = r;\n    }\n\n    // Hungarian algorithm\n    auto hungarian = [&](const vector<vector<int>>& cost) -> vector<int> {\n        int n = cost.size(), m = cost[0].size();\n        if (n == 0) return {};\n        vector<int> u(n + 1), v(m + 1), p(m + 1), way(m + 1);\n        for (int i = 1; i <= n; ++i) {\n            p[0] = i;\n            int j0 = 0;\n            vector<int> minv(m + 1, 1e9);\n            vector<char> used(m + 1, false);\n            do {\n                used[j0] = true;\n                int i0 = p[j0], delta = 1e9, j1 = 0;\n                for (int j = 1; j <= m; ++j) {\n                    if (!used[j]) {\n                        int cur = cost[i0 - 1][j - 1] - u[i0] - v[j];\n                        if (cur < minv[j]) {\n                            minv[j] = cur;\n                            way[j] = j0;\n                        }\n                        if (minv[j] < delta) {\n                            delta = minv[j];\n                            j1 = j;\n                        }\n                    }\n                }\n                for (int j = 0; j <= m; ++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        vector<int> ass(n);\n        for (int j = 1; j <= m; ++j)\n            if (p[j] != 0)\n                ass[p[j] - 1] = j - 1;\n        return ass;\n    };\n\n    // initial target by row\u2011wise Hungarian\n    vector<int> target_val(V, -1), target_node(V, -1);\n    for (int r = 0; r < N; ++r) {\n        vector<int> nodes_r, vals_r;\n        for (int i = 0; i < V; ++i) {\n            if (xc[i] == r) nodes_r.push_back(i);\n            if (val_row[i] == r) vals_r.push_back(i);\n        }\n        if (vals_r.empty()) continue;\n        int sz = vals_r.size();\n        vector<vector<int>> cost(sz, vector<int>(sz));\n        for (int i = 0; i < sz; ++i) {\n            int v = vals_r[i];\n            int start = init_pos[v];\n            for (int j = 0; j < sz; ++j)\n                cost[i][j] = dist[start][nodes_r[j]];\n        }\n        vector<int> ass = hungarian(cost);\n        for (int i = 0; i < sz; ++i) {\n            int v = vals_r[i];\n            int node = nodes_r[ass[i]];\n            target_val[node] = v;\n            target_node[v] = node;\n        }\n    }\n\n    long long cur_cost = 0;\n    for (int v = 0; v < V; ++v)\n        cur_cost += dist[init_pos[v]][target_node[v]];\n\n    // SA parameters\n    mt19937 rng(random_device{}());\n    uniform_real_distribution<double> prob_dist(0.0, 1.0);\n    uniform_int_distribution<int> node_dist(0, V - 1);\n\n    double T_start = 10000.0, T_end = 0.1;\n    double time_limit = 1.9;  // seconds for SA\n    auto start_time = chrono::steady_clock::now();\n    long long iter = 0;\n    double T = T_start;\n\n    while (true) {\n        if ((iter & 1023) == 0) {\n            double elapsed =\n                chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n            if (elapsed > time_limit) break;\n            T = T_start * pow(T_end / T_start, min(elapsed / time_limit, 1.0));\n        }\n        ++iter;\n\n        int u = node_dist(rng);\n        int v = node_dist(rng);\n        if (u == v) continue;\n        if (is_anc(u, v) || is_anc(v, u)) continue;\n\n        int val_u = target_val[u];\n        int val_v = target_val[v];\n\n        bool ok = true;\n        for (int p : parents[u])\n            if (target_val[p] > val_v) { ok = false; break; }\n        if (ok)\n            for (int c : children[u])\n                if (val_v > target_val[c]) { ok = false; break; }\n        if (ok)\n            for (int p : parents[v])\n                if (target_val[p] > val_u) { ok = false; break; }\n        if (ok)\n            for (int c : children[v])\n                if (val_u > target_val[c]) { ok = false; break; }\n        if (!ok) continue;\n\n        long long delta = dist[init_pos[val_u]][v] + dist[init_pos[val_v]][u] -\n                          dist[init_pos[val_u]][u] - dist[init_pos[val_v]][v];\n\n        if (delta <= 0 || prob_dist(rng) < exp(-delta / T)) {\n            target_val[u] = val_v;\n            target_val[v] = val_u;\n            target_node[val_u] = v;\n            target_node[val_v] = u;\n            cur_cost += delta;\n        }\n    }\n\n    // ---------- routing phase ----------\n    vector<int> cur_pos = init_pos;\n    vector<bool> locked(V, false);\n    vector<pair<int, int>> moves;\n\n    // bottom \u2192 top, left \u2192 right\n    for (int r = N - 1; r >= 0; --r) {\n        for (int c = 0; c <= r; ++c) {\n            int tgt_id = id(r, c);\n            int v = target_val[tgt_id];\n            if (cur_pos[v] == tgt_id) {\n                locked[tgt_id] = true;\n                continue;\n            }\n\n            vector<int> parent(V, -1);\n            queue<int> q;\n            int start = cur_pos[v];\n            q.push(start);\n            parent[start] = start;\n            while (!q.empty()) {\n                int u = q.front(); q.pop();\n                if (u == tgt_id) break;\n                for (int w : adj[u])\n                    if (!locked[w] && parent[w] == -1) {\n                        parent[w] = u;\n                        q.push(w);\n                    }\n            }\n\n            vector<int> path;\n            for (int at = tgt_id; at != start; at = parent[at])\n                path.push_back(at);\n            path.push_back(start);\n            reverse(path.begin(), path.end());\n\n            for (size_t i = 0; i + 1 < path.size(); ++i) {\n                int n1 = path[i], n2 = path[i + 1];\n                int val1 = grid[n1], val2 = grid[n2];\n                swap(grid[n1], grid[n2]);\n                cur_pos[val1] = n2;\n                cur_pos[val2] = n1;\n                moves.emplace_back(n1, n2);\n                if (moves.size() >= 10000) goto output_moves;\n            }\n            locked[tgt_id] = true;\n        }\n    }\n\noutput_moves:\n    cout << moves.size() << \"\\n\";\n    for (auto [a, b] : moves)\n        cout << xc[a] << \" \" << yc[a] << \" \" << xc[b] << \" \" << yc[b] << \"\\n\";\n\n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <functional>\n#include <utility>\n\nusing namespace std;\n\nint main() {\n    // Read initial information\n    int D, N;\n    cin >> D >> N;\n    int ent_r = 0, ent_c = (D - 1) / 2;\n    int start = ent_r * D + ent_c;\n\n    // Mark cells that cannot hold containers (entrance + obstacles)\n    vector<vector<bool>> blocked(D, vector<bool>(D, false));\n    blocked[ent_r][ent_c] = true;  // entrance\n    for (int i = 0; i < N; i++) {\n        int r, c;\n        cin >> r >> c;\n        blocked[r][c] = true;\n    }\n\n    int K = D * D - 1 - N;  // number of containers\n\n    // BFS distances from entrance over free cells\n    vector<int> dist(D * D, -1);\n    queue<int> q;\n    dist[start] = 0;\n    q.push(start);\n    const int dr[4] = {-1, 1, 0, 0};\n    const int dc[4] = {0, 0, -1, 1};\n\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        int r = u / D, c = u % D;\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n            if (blocked[nr][nc]) continue;\n            int v = nr * D + nc;\n            if (dist[v] == -1) {\n                dist[v] = dist[u] + 1;\n                q.push(v);\n            }\n        }\n    }\n\n    // Collect all free cells (non-blocked, non-entrance)\n    vector<int> free_cells;\n    for (int r = 0; r < D; r++) {\n        for (int c = 0; c < D; c++) {\n            if (!blocked[r][c]) {\n                free_cells.push_back(r * D + c);\n            }\n        }\n    }\n\n    // Sort free cells by distance, then by ID (row-major)\n    sort(free_cells.begin(), free_cells.end(), [&](int a, int b) {\n        if (dist[a] != dist[b]) return dist[a] < dist[b];\n        return a < b;\n    });\n\n    // Prepare mapping: order of each cell, and ideal cell for each rank\n    vector<int> ord(D * D, -1);\n    vector<int> ideal(K);\n    for (int i = 0; i < K; i++) {\n        int cell = free_cells[i];\n        ord[cell] = i;\n        ideal[i] = cell;\n    }\n\n    // State of the warehouse\n    vector<bool> occupied(D * D, false);\n    vector<int> rank_at(D * D, -1);\n\n    // Process arrivals\n    for (int d = 0; d < K; d++) {\n        int rank;\n        cin >> rank;\n\n        // Get all empty cells currently reachable from entrance\n        vector<int> reachable;\n        vector<bool> vis(D * D, false);\n        queue<int> bfs;\n        bfs.push(start);\n        vis[start] = true;\n        while (!bfs.empty()) {\n            int u = bfs.front(); bfs.pop();\n            reachable.push_back(u);\n            int r = u / D, c = u % D;\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (blocked[nr][nc]) continue;\n                int v = nr * D + nc;\n                if (occupied[v]) continue;\n                if (!vis[v]) {\n                    vis[v] = true;\n                    bfs.push(v);\n                }\n            }\n        }\n\n        // Build adjacency among reachable cells\n        vector<vector<int>> adj(D * D);\n        for (int u : reachable) {\n            int r = u / D, c = u % D;\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (blocked[nr][nc]) continue;\n                int v = nr * D + nc;\n                if (occupied[v]) continue;\n                if (vis[v]) {\n                    adj[u].push_back(v);\n                }\n            }\n        }\n\n        // Find articulation points (cells that would disconnect the empty area)\n        vector<int> disc(D * D, -1), low(D * D, -1);\n        vector<bool> is_art(D * D, false);\n        int timer = 0;\n        function<void(int, int)> dfs = [&](int u, int parent) {\n            disc[u] = low[u] = timer++;\n            int children = 0;\n            for (int v : adj[u]) {\n                if (v == parent) continue;\n                if (disc[v] == -1) {\n                    dfs(v, u);\n                    low[u] = min(low[u], low[v]);\n                    if (parent != -1 && low[v] >= disc[u]) {\n                        is_art[u] = true;\n                    }\n                    children++;\n                } else {\n                    low[u] = min(low[u], disc[v]);\n                }\n            }\n            if (parent == -1 && children > 1) {\n                is_art[u] = true;\n            }\n        };\n        dfs(start, -1);\n\n        // Safe cells = reachable empty cells except entrance and articulation points\n        vector<int> safe;\n        for (int u : reachable) {\n            if (u == start) continue;\n            if (!is_art[u]) {\n                safe.push_back(u);\n            }\n        }\n\n        // Choose placement cell\n        int target = ideal[rank];\n        int chosen = -1;\n        bool target_safe = false;\n        for (int u : safe) if (u == target) { target_safe = true; break; }\n\n        if (target_safe) {\n            chosen = target;\n        } else {\n            int best_diff = 1e9;\n            for (int u : safe) {\n                int diff = abs(ord[u] - rank);\n                if (diff < best_diff) {\n                    best_diff = diff;\n                    chosen = u;\n                } else if (diff == best_diff) {\n                    if (ord[u] < ord[chosen]) {\n                        chosen = u;\n                    }\n                }\n            }\n        }\n\n        // Place the container\n        occupied[chosen] = true;\n        rank_at[chosen] = rank;\n        cout << chosen / D << \" \" << chosen % D << endl;\n    }\n\n    // Removal phase\n    vector<bool> removed(D * D, false);\n    vector<pair<int, int>> removal_seq;\n\n    while (removal_seq.size() < K) {\n        queue<int> bfs;\n        vector<bool> vis(D * D, false);\n        bfs.push(start);\n        vis[start] = true;\n        vector<int> candidates;\n\n        while (!bfs.empty()) {\n            int u = bfs.front(); bfs.pop();\n            int r = u / D, c = u % D;\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (blocked[nr][nc]) continue;\n                int v = nr * D + nc;\n                if (vis[v]) continue;\n                if (removed[v] || v == start) {\n                    vis[v] = true;\n                    bfs.push(v);\n                } else if (occupied[v] && !removed[v]) {\n                    candidates.push_back(v);\n                }\n            }\n        }\n\n        sort(candidates.begin(), candidates.end());\n        candidates.erase(unique(candidates.begin(), candidates.end()), candidates.end());\n\n        int best = -1, best_rank = 1e9;\n        for (int v : candidates) {\n            if (rank_at[v] < best_rank) {\n                best_rank = rank_at[v];\n                best = v;\n            }\n        }\n\n        removed[best] = true;\n        removal_seq.emplace_back(best / D, best % D);\n    }\n\n    for (auto [r, c] : removal_seq) {\n        cout << r << \" \" << c << endl;\n    }\n\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 50;\nconst int N2 = N * N;\nconst int MAXC = 101; // 0..100\n\nbool adj_req[MAXC][MAXC];\nint vis[N2];\nint vis_token = 0;\nint bfs_queue[N2];\nvector<array<int,4>> nb(N2);\nvector<int> boundary_idx;\n\nvoid compute_energy(const int* g, int m, int& E, int& viol_conn, int& viol_adj) {\n    ++vis_token;\n    E = 0;\n    viol_conn = 0;\n    viol_adj = 0;\n    int comp_count[MAXC] = {0};\n    int cell_count[MAXC] = {0};\n\n    // Connectivity for colors 1..m\n    for (int i = 0; i < N2; ++i) {\n        int c = g[i];\n        if (c == 0) {\n            ++E;\n        } else {\n            cell_count[c]++;\n            if (vis[i] != vis_token) {\n                comp_count[c]++;\n                int head = 0, tail = 0;\n                bfs_queue[tail++] = i;\n                vis[i] = vis_token;\n                while (head < tail) {\n                    int v = bfs_queue[head++];\n                    for (int nbr : nb[v]) {\n                        if (nbr != -1 && g[nbr] == c && vis[nbr] != vis_token) {\n                            vis[nbr] = vis_token;\n                            bfs_queue[tail++] = nbr;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    for (int c = 1; c <= m; ++c) {\n        if (cell_count[c] == 0) viol_conn += 1;\n        else if (comp_count[c] != 1) viol_conn += comp_count[c] - 1;\n    }\n\n    // Connectivity for 0 (must be connected to the outside)\n    int head = 0, tail = 0;\n    for (int idx : boundary_idx) {\n        if (g[idx] == 0 && vis[idx] != vis_token) {\n            vis[idx] = vis_token;\n            bfs_queue[tail++] = idx;\n        }\n    }\n    while (head < tail) {\n        int v = bfs_queue[head++];\n        for (int nbr : nb[v]) {\n            if (nbr != -1 && g[nbr] == 0 && vis[nbr] != vis_token) {\n                vis[nbr] = vis_token;\n                bfs_queue[tail++] = nbr;\n            }\n        }\n    }\n    int unvisited_0 = 0;\n    for (int i = 0; i < N2; ++i) {\n        if (g[i] == 0 && vis[i] != vis_token) ++unvisited_0;\n    }\n    viol_conn += unvisited_0;\n\n    // Adjacency\n    int adj[MAXC][MAXC] = {0};\n    for (int i = 0; i < N2; ++i) {\n        int c1 = g[i];\n        if (i % N < N - 1) {\n            int c2 = g[i + 1];\n            if (c1 != c2) { adj[c1][c2]++; adj[c2][c1]++; }\n        }\n        if (i / N < N - 1) {\n            int c2 = g[i + N];\n            if (c1 != c2) { adj[c1][c2]++; adj[c2][c1]++; }\n        }\n    }\n    // Boundary edges with outside 0\n    for (int idx : boundary_idx) {\n        int c = g[idx];\n        if (c != 0) {\n            adj[c][0]++;\n            adj[0][c]++;\n        }\n    }\n    for (int a = 0; a <= m; ++a) {\n        for (int b = a + 1; b <= m; ++b) {\n            if (adj_req[a][b]) {\n                if (adj[a][b] == 0) viol_adj++;\n            } else {\n                if (adj[a][b] > 0) viol_adj += adj[a][b];\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start_time = chrono::high_resolution_clock::now();\n    auto elapsed_ms = [&]() {\n        return chrono::duration_cast<chrono::milliseconds>(\n            chrono::high_resolution_clock::now() - start_time).count();\n    };\n\n    int n, m;\n    cin >> n >> m;\n    vector<vector<int>> orig(n, vector<int>(n));\n    for (int i = 0; i < n; ++i)\n        for (int j = 0; j < n; ++j)\n            cin >> orig[i][j];\n\n    // Build required adjacency graph from the original map\n    memset(adj_req, 0, sizeof(adj_req));\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c1 = orig[i][j];\n            if (j < n - 1) {\n                int c2 = orig[i][j + 1];\n                if (c1 != c2) adj_req[c1][c2] = adj_req[c2][c1] = true;\n            }\n            if (i < n - 1) {\n                int c2 = orig[i + 1][j];\n                if (c1 != c2) adj_req[c1][c2] = adj_req[c2][c1] = true;\n            }\n            if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                adj_req[c1][0] = adj_req[0][c1] = true;\n            }\n        }\n    }\n\n    // Precompute 4\u2011neighbors and boundary indices\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int idx = i * n + j;\n            nb[idx][0] = (i > 0) ? idx - n : -1;\n            nb[idx][1] = (i < n - 1) ? idx + n : -1;\n            nb[idx][2] = (j > 0) ? idx - 1 : -1;\n            nb[idx][3] = (j < n - 1) ? idx + 1 : -1;\n            if (i == 0 || i == n - 1 || j == 0 || j == n - 1)\n                boundary_idx.push_back(idx);\n        }\n    }\n\n    // ----- Phase 1: greedy erosion from the boundary -----\n    int g2d[N][N];\n    int count[MAXC] = {0};\n    int adj[MAXC][MAXC] = {0};\n\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            g2d[i][j] = orig[i][j];\n            count[orig[i][j]]++;\n        }\n    }\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c1 = g2d[i][j];\n            if (j < n - 1) {\n                int c2 = g2d[i][j + 1];\n                if (c1 != c2) { adj[c1][c2]++; adj[c2][c1]++; }\n            }\n            if (i < n - 1) {\n                int c2 = g2d[i + 1][j];\n                if (c1 != c2) { adj[c1][c2]++; adj[c2][c1]++; }\n            }\n            if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                if (c1 != 0) { adj[c1][0]++; adj[0][c1]++; }\n            }\n        }\n    }\n\n    int vis_g[N][N];\n    int vis_token_g = 0;\n    auto has_zero_neighbor = [&](int i, int j) -> bool {\n        if (i == 0 || i == n - 1 || j == 0 || j == n - 1) return true;\n        if (g2d[i - 1][j] == 0 || g2d[i + 1][j] == 0 ||\n            g2d[i][j - 1] == 0 || g2d[i][j + 1] == 0) return true;\n        return false;\n    };\n\n    auto try_remove = [&](int i, int j) -> bool {\n        int c = g2d[i][j];\n        if (c == 0 || count[c] <= 1) return false;\n        const int di[] = {-1, 1, 0, 0};\n        const int dj[] = {0, 0, -1, 1};\n\n        int lost[MAXC] = {0}, gain[MAXC] = {0};\n        for (int k = 0; k < 4; ++k) {\n            int ni = i + di[k], nj = j + dj[k];\n            int d;\n            if (ni < 0 || ni >= n || nj < 0 || nj >= n) d = 0;\n            else d = g2d[ni][nj];\n            if (d == c) continue;\n            lost[d]++;\n            if (d != 0) gain[d]++;\n        }\n        for (int d = 0; d <= m; ++d) {\n            if (lost[d] > 0 && adj_req[c][d] && adj[c][d] - lost[d] < 1) return false;\n            if (gain[d] > 0 && !adj_req[0][d]) return false;\n        }\n\n        // Connectivity of color c after removal\n        int si = -1, sj = -1;\n        for (int k = 0; k < 4; ++k) {\n            int ni = i + di[k], nj = j + dj[k];\n            if (ni >= 0 && ni < n && nj >= 0 && nj < n && g2d[ni][nj] == c) {\n                si = ni; sj = nj; break;\n            }\n        }\n        if (si == -1) return false;\n        ++vis_token_g;\n        queue<pair<int,int>> q;\n        q.push({si, sj});\n        vis_g[si][sj] = vis_token_g;\n        int visited = 0;\n        while (!q.empty()) {\n            auto [x, y] = q.front(); q.pop();\n            visited++;\n            for (int k = 0; k < 4; ++k) {\n                int nx = x + di[k], ny = y + dj[k];\n                if (nx >= 0 && nx < n && ny >= 0 && ny < n &&\n                    !(nx == i && ny == j) && g2d[nx][ny] == c &&\n                    vis_g[nx][ny] != vis_token_g) {\n                    vis_g[nx][ny] = vis_token_g;\n                    q.push({nx, ny});\n                }\n            }\n        }\n        if (visited != count[c] - 1) return false;\n        return true;\n    };\n\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                if (g2d[i][j] == 0 || !has_zero_neighbor(i, j)) continue;\n                if (try_remove(i, j)) {\n                    int c = g2d[i][j];\n                    const int di[] = {-1, 1, 0, 0};\n                    const int dj[] = {0, 0, -1, 1};\n                    for (int k = 0; k < 4; ++k) {\n                        int ni = i + di[k], nj = j + dj[k];\n                        int d;\n                        if (ni < 0 || ni >= n || nj < 0 || nj >= n) d = 0;\n                        else d = g2d[ni][nj];\n                        if (d == c) continue;\n                        adj[c][d]--; adj[d][c]--;\n                        if (d != 0) { adj[0][d]++; adj[d][0]++; }\n                    }\n                    g2d[i][j] = 0;\n                    count[c]--;\n                    changed = true;\n                }\n            }\n        }\n    }\n\n    // Convert greedy result to 1D\n    int init_g[N2];\n    for (int i = 0; i < n; ++i)\n        for (int j = 0; j < n; ++j)\n            init_g[i * n + j] = g2d[i][j];\n\n    // ----- Phase 2: Simulated Annealing -----\n    int cur_g[N2];\n    memcpy(cur_g, init_g, sizeof(cur_g));\n    int best_valid_g[N2];\n    memcpy(best_valid_g, init_g, sizeof(best_valid_g));\n    int best_valid_E = -1;\n\n    int testE, testVc, testVa;\n    compute_energy(init_g, m, testE, testVc, testVa);\n    if (testVc == 0 && testVa == 0) best_valid_E = testE;\n\n    const double W_CONN = 5000.0;\n    const double W_ADJ  = 5000.0;\n    const double T_start = 100000.0;\n    const double T_end   = 0.1;\n\n    int cur_E, cur_vc, cur_va;\n    compute_energy(cur_g, m, cur_E, cur_vc, cur_va);\n    double cur_energy = -cur_E + W_CONN * cur_vc + W_ADJ * cur_va;\n    double best_energy = cur_energy;\n\n    uint64_t rng_state = 123456789;\n    auto rng_next = [&]() -> uint64_t {\n        rng_state = rng_state * 6364136223846793005ULL + 1442695040888963407ULL;\n        return rng_state >> 33;\n    };\n    auto rng_int = [&](int n) { return rng_next() % n; };\n    auto rng_double = [&]() { return (rng_next() & 0xFFFFFFFF) / 4294967296.0; };\n\n    while (elapsed_ms() < 1800) {\n        double progress = elapsed_ms() / 1800.0;\n        double T = T_start * pow(T_end / T_start, progress);\n\n        int idx = rng_int(N2);\n        int old_c = cur_g[idx];\n        int new_c = (rng_double() < 0.5) ? 0 : (rng_int(m) + 1);\n        if (new_c == old_c) continue;\n\n        cur_g[idx] = new_c;\n        int new_E, new_vc, new_va;\n        compute_energy(cur_g, m, new_E, new_vc, new_va);\n        double new_energy = -new_E + W_CONN * new_vc + W_ADJ * new_va;\n        double delta = new_energy - cur_energy;\n\n        bool accept = (delta <= 0) || (rng_double() < exp(-delta / T));\n        if (accept) {\n            cur_energy = new_energy;\n            cur_E = new_E; cur_vc = new_vc; cur_va = new_va;\n            if (new_energy < best_energy) best_energy = new_energy;\n            if (new_vc == 0 && new_va == 0 && new_E > best_valid_E) {\n                best_valid_E = new_E;\n                memcpy(best_valid_g, cur_g, sizeof(best_valid_g));\n            }\n        } else {\n            cur_g[idx] = old_c;\n        }\n    }\n\n    // Output the best valid grid found (fallback to the original if none)\n    if (best_valid_E < 0) {\n        // Use the original input (always valid)\n        for (int i = 0; i < n; ++i)\n            for (int j = 0; j < n; ++j)\n                best_valid_g[i * n + j] = orig[i][j];\n    }\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (j) cout << ' ';\n            cout << best_valid_g[i * n + j];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <cmath>\n#include <chrono>\n\nusing namespace std;\n\n// ---------- query interface ----------\nint query_count = 0;\nint Q_total;\n\nchar ask(int nL, int nR, const vector<int>& L, const vector<int>& R) {\n    cout << nL << \" \" << nR;\n    for (int x : L) cout << \" \" << x;\n    for (int x : R) cout << \" \" << x;\n    cout << endl;\n    char res; cin >> res;\n    query_count++;\n    return res;\n}\n\n// compare two single items, returns '<','>','='\nchar compare_items(int a, int b) {\n    vector<int> L = {a}, R = {b};\n    return ask(1, 1, L, R);\n}\n\n// ---------- tournament sort ----------\nstruct TournamentTree {\n    int N;\n    int size;          // power of two >= N\n    vector<int> tree;  // size 2*size, leaves at [size, 2*size-1]\n    vector<int> leaf_pos; // mapping item -> leaf index\n    vector<int> sorted;   // extracted items in descending order\n    int extracted = 0;\n\n    TournamentTree(int n) : N(n) {\n        size = 1;\n        while (size < N) size <<= 1;\n        tree.assign(2 * size, -1);\n        leaf_pos.resize(N);\n        for (int i = 0; i < N; ++i) {\n            int leaf = size + i;\n            tree[leaf] = i;\n            leaf_pos[i] = leaf;\n        }\n        // build tree\n        for (int i = size - 1; i >= 1; --i) {\n            int l = tree[2*i], r = tree[2*i+1];\n            if (l == -1) tree[i] = r;\n            else if (r == -1) tree[i] = l;\n            else {\n                char res = compare_items(l, r);\n                if (res == '>') tree[i] = l;\n                else if (res == '<') tree[i] = r;\n                else tree[i] = l; // equal, pick l\n            }\n        }\n    }\n\n    // extract current winner, returns item index, or -1 if none\n    int extract() {\n        if (tree[1] == -1) return -1;\n        int winner = tree[1];\n        int leaf = leaf_pos[winner];\n        tree[leaf] = -1;\n        int node = leaf / 2;\n        while (node >= 1) {\n            int l = tree[2*node], r = tree[2*node+1];\n            if (l == -1) tree[node] = r;\n            else if (r == -1) tree[node] = l;\n            else {\n                if (query_count >= Q_total) {\n                    // cannot query, stop extraction\n                    return -2; // signal need to break\n                }\n                char res = compare_items(l, r);\n                if (res == '>') tree[node] = l;\n                else if (res == '<') tree[node] = r;\n                else tree[node] = l;\n            }\n            node /= 2;\n        }\n        extracted++;\n        sorted.push_back(winner);\n        return winner;\n    }\n\n    // extract as many as possible within query budget (Q_total - query_count)\n    void extract_all_possible() {\n        int height = 0;\n        for (int s = size; s > 1; s >>= 1) height++;\n        while (extracted < N && query_count < Q_total) {\n            if (query_count + height > Q_total) break; // not enough for a full extraction\n            int res = extract();\n            if (res == -2) break; // query limit hit inside\n        }\n    }\n\n    // return unextracted items (leaves that are not -1)\n    vector<int> get_remaining() {\n        vector<int> rem;\n        for (int i = 0; i < N; ++i) {\n            int leaf = leaf_pos[i];\n            if (tree[leaf] == i) rem.push_back(i);\n        }\n        return rem;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int N, D, Q;\n    cin >> N >> D >> Q;\n    Q_total = Q;\n\n    // precompute expected weights (exponential order statistics, lambda=1e-5)\n    vector<double> H(N + 1, 0.0);\n    for (int i = 1; i <= N; ++i) H[i] = H[i-1] + 1.0 / i;\n    vector<double> expected(N);\n    for (int r = 0; r < N; ++r) {\n        // r=0 largest, gets sum_{t=r+1..N} 1/t = H[N] - H[r]\n        expected[r] = 100000.0 * (H[N] - H[r]);\n    }\n\n    // ---------- Phase 1: tournament sort ----------\n    TournamentTree tt(N);\n    tt.extract_all_possible();\n    int K = tt.extracted;\n\n    // remaining items\n    vector<int> rem_items = tt.get_remaining();\n    int M = rem_items.size();\n\n    // assign initial weights\n    vector<double> w(N, 1.0);\n    for (int i = 0; i < K; ++i) {\n        w[tt.sorted[i]] = expected[i];\n    }\n    // assign remaining items the expected weights for ranks K..N-1, in original order\n    for (int j = 0; j < M; ++j) {\n        w[rem_items[j]] = expected[K + j];\n    }\n\n    // ---------- Phase 2: refinement with remaining queries ----------\n    // greedy assignment helper\n    auto greedy_partition = [&]() -> vector<int> {\n        vector<pair<double,int>> items(N);\n        for (int i = 0; i < N; ++i) items[i] = {w[i], i};\n        sort(items.begin(), items.end(), [](auto& a, auto& b) { return a.first > b.first; });\n        vector<int> P(N, 0);\n        vector<double> bin_sum(D, 0.0);\n        for (auto& p : items) {\n            int idx = p.second;\n            int best = 0;\n            for (int b = 1; b < D; ++b) if (bin_sum[b] < bin_sum[best]) best = b;\n            P[idx] = best;\n            bin_sum[best] += p.first;\n        }\n        return P;\n    };\n\n    vector<int> P_curr = greedy_partition();\n\n    while (query_count < Q) {\n        // find two bins with closest estimated sums\n        vector<double> bin_sum(D, 0.0);\n        for (int i = 0; i < N; ++i) bin_sum[P_curr[i]] += w[i];\n        int b1 = -1, b2 = -1;\n        double min_diff = 1e30;\n        for (int i = 0; i < D; ++i) {\n            if (bin_sum[i] == 0) continue;\n            for (int j = i+1; j < D; ++j) {\n                if (bin_sum[j] == 0) continue;\n                double diff = fabs(bin_sum[i] - bin_sum[j]);\n                if (diff < min_diff) {\n                    min_diff = diff;\n                    b1 = i; b2 = j;\n                }\n            }\n        }\n        // fallback\n        if (b1 == -1) b1 = 0, b2 = 1 % D;\n        vector<int> L, R;\n        for (int i = 0; i < N; ++i) {\n            if (P_curr[i] == b1) L.push_back(i);\n            else if (P_curr[i] == b2) R.push_back(i);\n        }\n\n        char res = ask(L.size(), R.size(), L, R);\n\n        // update weights using a simple gradient step\n        double sL = 0.0, sR = 0.0;\n        for (int i : L) sL += w[i];\n        for (int i : R) sR += w[i];\n        double diff = sL - sR;\n        double error = 0.0;\n        if (res == '<' && diff >= 0) error = diff + 1.0;      // need diff < 0\n        else if (res == '>' && diff <= 0) error = diff - 1.0; // need diff > 0\n        else if (res == '=' && diff != 0) error = diff;       // need diff == 0\n        if (error != 0.0) {\n            double lr = 0.1 / (1.0 + (query_count - K) * 0.01);\n            double adjL = lr * error / (double)L.size();\n            double adjR = lr * error / (double)R.size();\n            for (int i : L) w[i] -= adjL;\n            for (int i : R) w[i] += adjR;\n            // clip\n            for (int i : L) if (w[i] < 1.0) w[i] = 1.0;\n            for (int i : R) if (w[i] < 1.0) w[i] = 1.0;\n        }\n\n        // occasionally recompute partition\n        if ((query_count - tt.N) % 10 == 0) {\n            P_curr = greedy_partition();\n        }\n    }\n\n    // ---------- Phase 3: final partition with SA ----------\n    vector<int> P = greedy_partition();\n    vector<double> bin_sum(D, 0.0);\n    for (int i = 0; i < N; ++i) bin_sum[P[i]] += w[i];\n    double mean = 0.0;\n    for (double s : bin_sum) mean += s;\n    mean /= D;\n    double var = 0.0;\n    for (double s : bin_sum) var += (s - mean)*(s - mean);\n    var /= D;\n\n    mt19937 rng(12345);\n    uniform_int_distribution<int> dist_item(0, N-1);\n    uniform_int_distribution<int> dist_bin(0, D-1);\n    uniform_real_distribution<double> uni(0.0, 1.0);\n\n    const int SA_ITERS = 200000;\n    double T = 1.0;\n    for (int it = 0; it < SA_ITERS; ++it) {\n        int i = dist_item(rng);\n        int old_b = P[i];\n        int new_b = dist_bin(rng);\n        if (new_b == old_b) continue;\n\n        double new_old = bin_sum[old_b] - w[i];\n        double new_new = bin_sum[new_b] + w[i];\n        double delta = ((new_old - mean)*(new_old - mean) + (new_new - mean)*(new_new - mean)\n                     - (bin_sum[old_b] - mean)*(bin_sum[old_b] - mean)\n                     - (bin_sum[new_b] - mean)*(bin_sum[new_b] - mean)) / D;\n        if (delta < 0 || uni(rng) < exp(-delta / T)) {\n            P[i] = new_b;\n            bin_sum[old_b] = new_old;\n            bin_sum[new_b] = new_new;\n            var += delta;\n        }\n        T *= 0.99995;\n        if (T < 0.001) T = 0.001;\n    }\n\n    // output final division\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << \" \";\n        cout << P[i];\n    }\n    cout << endl;\n\n    return 0;\n}","ahc026":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <utility>\n\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    int n, m;\n    cin >> n >> m;\n    \n    vector<vector<int>> stacks(m);\n    // pos[box] = {stack_index, position_from_bottom}\n    vector<pair<int,int>> pos(n + 1);\n    \n    for (int i = 0; i < m; i++) {\n        stacks[i].resize(n / m);\n        for (int j = 0; j < n / m; j++) {\n            cin >> stacks[i][j];\n            pos[stacks[i][j]] = {i, j};\n        }\n    }\n    \n    vector<pair<int,int>> ops;\n    \n    for (int v = 1; v <= n; v++) {\n        auto [s, p] = pos[v];\n        // v should always be present in the current state\n        if (p == (int)stacks[s].size() - 1) {\n            // v is on top, carry it out directly\n            ops.push_back({v, 0});\n            stacks[s].pop_back();\n            pos[v] = {-1, -1};\n        } else {\n            // Boxes above v form a block that needs to be moved\n            int u = stacks[s][p + 1]; // bottom of the block just above v\n            // Compute max value in the block\n            int max_B = 0;\n            for (int i = p + 1; i < (int)stacks[s].size(); i++) {\n                max_B = max(max_B, stacks[s][i]);\n            }\n            \n            // Choose destination stack t\n            int best_t = -1;\n            int best_priority = -1; // 2: ideal, 1: empty, 0: violation\n            int best_key = 0;\n            \n            for (int t = 0; t < m; t++) {\n                if (t == s) continue;\n                if (stacks[t].empty()) {\n                    if (best_priority < 1) {\n                        best_priority = 1;\n                        best_t = t;\n                    }\n                } else {\n                    int min_t = *min_element(stacks[t].begin(), stacks[t].end());\n                    if (min_t > max_B) {\n                        // ideal: all boxes in t are larger than the whole block\n                        if (best_priority < 2) {\n                            best_priority = 2;\n                            best_key = min_t;\n                            best_t = t;\n                        } else if (best_priority == 2 && min_t < best_key) {\n                            best_key = min_t;\n                            best_t = t;\n                        }\n                    } else {\n                        // violation: some boxes in t may be blocked\n                        if (best_priority < 0) {\n                            best_priority = 0;\n                            best_key = min_t;\n                            best_t = t;\n                        } else if (best_priority == 0 && min_t > best_key) {\n                            best_key = min_t;\n                            best_t = t;\n                        }\n                    }\n                }\n            }\n            \n            // Perform move operation (1-indexed stack in output)\n            ops.push_back({u, best_t + 1});\n            vector<int> block(stacks[s].begin() + p + 1, stacks[s].end());\n            stacks[s].erase(stacks[s].begin() + p + 1, stacks[s].end());\n            for (int val : block) {\n                stacks[best_t].push_back(val);\n                pos[val] = {best_t, (int)stacks[best_t].size() - 1};\n            }\n            \n            // Now v is on top, carry it out\n            ops.push_back({v, 0});\n            stacks[s].pop_back();\n            pos[v] = {-1, -1};\n        }\n    }\n    \n    // Output all operations\n    for (auto [val, dst] : ops) {\n        cout << val << \" \" << dst << \"\\n\";\n    }\n    \n    return 0;\n}","ahc027":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <functional>\n\nusing namespace std;\n\nint64_t calc_sum_sq(const vector<int>& times, int L) {\n    if (times.empty()) return 0;\n    int64_t res = 0;\n    int k = times.size();\n    for (int i = 0; i < k - 1; ++i) {\n        int64_t diff = times[i + 1] - times[i];\n        res += diff * diff;\n    }\n    int64_t diff = times[0] + L - times.back();\n    res += diff * diff;\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int N;\n    cin >> N;\n    int V = N * N;\n    vector<string> h(N - 1), v(N);\n    for (int i = 0; i < N - 1; ++i) cin >> h[i];\n    for (int i = 0; i < N; ++i) cin >> v[i];\n    vector<int> d(V);\n    for (int i = 0; i < V; ++i) cin >> d[i];\n\n    auto id = [&](int i, int j) { return i * N + j; };\n\n    vector<vector<int>> adj(V);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = id(i, j);\n            if (j + 1 < N && v[i][j] == '0') {\n                int w = id(i, j + 1);\n                adj[u].push_back(w);\n                adj[w].push_back(u);\n            }\n            if (i + 1 < N && h[i][j] == '0') {\n                int w = id(i + 1, j);\n                adj[u].push_back(w);\n                adj[w].push_back(u);\n            }\n        }\n    }\n\n    // BFS from (0,0) to obtain shortest paths\n    vector<int> dist(V, -1), parent(V, -1);\n    queue<int> q;\n    q.push(0);\n    dist[0] = 0;\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (int w : adj[u]) {\n            if (dist[w] == -1) {\n                dist[w] = dist[u] + 1;\n                parent[w] = u;\n                q.push(w);\n            }\n        }\n    }\n\n    // Iterative DFS to build a base route (doubled spanning tree)\n    vector<int> base_seq;\n    vector<bool> visited(V, false);\n    vector<int> stack = {0};\n    vector<int> edge_idx(V, 0);\n    visited[0] = true;\n    while (!stack.empty()) {\n        int u = stack.back();\n        if (edge_idx[u] < (int)adj[u].size()) {\n            int w = adj[u][edge_idx[u]++];\n            if (!visited[w]) {\n                visited[w] = true;\n                base_seq.push_back(w);\n                stack.push_back(w);\n            }\n        } else {\n            stack.pop_back();\n            if (!stack.empty()) {\n                base_seq.push_back(stack.back());\n            }\n        }\n    }\n    // base_seq ends with 0\n\n    int L0 = base_seq.size();\n    vector<int> cur_k(V, 0);\n    for (int c : base_seq) cur_k[c]++;\n\n    int L_target = 100000;\n    vector<int> seq = base_seq;\n    int L = L0;\n\n    // simple target proportions\n    double sum_sqrt = 0;\n    for (int i = 0; i < V; ++i) sum_sqrt += sqrt(d[i]);\n    vector<double> target_k(V);\n    for (int i = 0; i < V; ++i) target_k[i] = L_target * sqrt(d[i]) / sum_sqrt;\n\n    // add extra cycles until we reach the length limit\n    while (L < L_target) {\n        int best = -1;\n        double best_score = -1;\n        for (int i = 0; i < V; ++i) {\n            double deficit = target_k[i] - cur_k[i];\n            if (deficit > 0) {\n                double score = d[i] * deficit;\n                if (score > best_score) {\n                    best_score = score;\n                    best = i;\n                }\n            }\n        }\n        if (best == -1) break;\n        int dest = best;\n\n        vector<int> path;\n        for (int u = dest; u != 0; u = parent[u]) path.push_back(u);\n        reverse(path.begin(), path.end()); // a1 ... dest\n        int cycle_len = 2 * (int)path.size();\n        if (L + cycle_len > L_target) break;\n\n        // append the cycle 0 -> ... -> dest -> ... -> 0\n        for (int c : path) seq.push_back(c);\n        for (int i = (int)path.size() - 2; i >= 0; --i) seq.push_back(path[i]);\n        seq.push_back(0);\n\n        // update visit counts\n        for (int i = 0; i < (int)path.size(); ++i) {\n            int c = path[i];\n            if (i == (int)path.size() - 1) cur_k[c] += 1; // dest\n            else cur_k[c] += 2;                             // intermediate\n        }\n        cur_k[0] += 1;\n        L += cycle_len;\n    }\n\n    // Build visit times and initial objective\n    vector<vector<int>> times(V);\n    for (int i = 0; i < L; ++i) times[seq[i]].push_back(i);\n\n    int64_t total_O = 0;\n    for (int i = 0; i < V; ++i) total_O += d[i] * calc_sum_sq(times[i], L);\n\n    vector<int> best_seq = seq;\n    int64_t best_O = total_O;\n\n    // Simulated Annealing\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> uni01(0.0, 1.0);\n\n    double T_start = max(1e7, (double)total_O / 1000.0);\n    double T_end = 1e2;\n    double total_time = 1.95;\n    auto start_time = chrono::steady_clock::now();\n\n    vector<int> affected;\n    vector<bool> is_aff(V, false);\n    vector<vector<int>> old_pos(V);\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed >= total_time) break;\n        double ratio = elapsed / total_time;\n        if (ratio > 1.0) ratio = 1.0;\n        double T = T_start * pow(T_end / T_start, ratio);\n\n        // clean up from previous iteration\n        for (int c : affected) {\n            old_pos[c].clear();\n            is_aff[c] = false;\n        }\n        affected.clear();\n\n        if (L < 3) break;\n        int max_len = min(200, L - 2);\n        if (max_len < 1) continue;\n        uniform_int_distribution<int> l_dist(1, L - 3);\n        int l = l_dist(rng);\n        int max_r = min(L - 2, l + max_len - 1);\n        if (max_r < l) continue;\n        uniform_int_distribution<int> r_dist(l, max_r);\n        int r = r_dist(rng);\n\n        int prev = l - 1, next = r + 1;\n        int u1 = seq[prev], v1 = seq[r];\n        int u2 = seq[l], v2 = seq[next];\n        bool adj1 = false, adj2 = false;\n        for (int w : adj[u1]) if (w == v1) { adj1 = true; break; }\n        for (int w : adj[u2]) if (w == v2) { adj2 = true; break; }\n        if (!adj1 || !adj2) continue;\n\n        // collect segment information\n        for (int p = l; p <= r; ++p) {\n            int c = seq[p];\n            if (!is_aff[c]) {\n                is_aff[c] = true;\n                affected.push_back(c);\n            }\n            old_pos[c].push_back(p);\n        }\n\n        int64_t delta = 0;\n        vector<pair<int, vector<int>>> updates;\n        for (int c : affected) {\n            const vector<int>& old_times = times[c];\n            const vector<int>& op = old_pos[c];\n            int64_t old_sq = calc_sum_sq(old_times, L);\n\n            vector<int> new_times;\n            for (int t : old_times) if (t < l) new_times.push_back(t);\n            vector<int> np;\n            for (int p : op) np.push_back(l + r - p);\n            sort(np.begin(), np.end());\n            for (int t : np) new_times.push_back(t);\n            for (int t : old_times) if (t > r) new_times.push_back(t);\n\n            int64_t new_sq = calc_sum_sq(new_times, L);\n            delta += d[c] * (new_sq - old_sq);\n            updates.emplace_back(c, std::move(new_times));\n        }\n\n        bool accept = (delta <= 0);\n        if (!accept) {\n            double prob = exp(-delta / T);\n            if (uni01(rng) < prob) accept = true;\n        }\n\n        if (accept) {\n            reverse(seq.begin() + l, seq.begin() + r + 1);\n            for (auto& p : updates) {\n                times[p.first] = std::move(p.second);\n            }\n            total_O += delta;\n            if (total_O < best_O) {\n                best_O = total_O;\n                best_seq = seq;\n            }\n        }\n    }\n\n    // Output the best route found\n    string ans;\n    int cur = 0;\n    for (int i = 0; i < L; ++i) {\n        int nxt = best_seq[i];\n        int ci = cur / N, cj = cur % N;\n        int ni = nxt / N, nj = nxt % N;\n        if (ni == ci - 1) ans += 'U';\n        else if (ni == ci + 1) ans += 'D';\n        else if (nj == cj - 1) ans += 'L';\n        else if (nj == cj + 1) ans += 'R';\n        else ans += 'U'; // fallback\n        cur = nxt;\n    }\n    cout << ans << endl;\n\n    return 0;\n}","ahc028":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <chrono>\n#include <cmath>\n#include <cstdlib>\n#include <unordered_map>\n#include <utility>\n\nusing namespace std;\n\nconst int INF = 1e9;\n\nstruct Xorshift {\n    unsigned int x, y, z, w;\n    Xorshift() {\n        auto seed = chrono::steady_clock::now().time_since_epoch().count();\n        x = seed & 0xFFFFFFFF;\n        y = (seed >> 32) ^ 0x12345678;\n        z = seed ^ 0x9abcdef0;\n        w = seed ^ 0xdeadbeef;\n    }\n    unsigned int next() {\n        unsigned int t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = w ^ (w >> 19) ^ t ^ (t >> 8);\n    }\n    int nextInt(int n) { return next() % n; }\n};\n\nint N, M;\nint start_i, start_j;\nchar grid[15][15];\nvector<string> t;\nvector<int> pos[26];\nint dist[225][225];\nint start_idx;\n\nint dp_prev[225], dp_cur[225];\n\nint compute_DP_cost(const string& S) {\n    if (S.empty()) return 0;\n    char c0 = S[0] - 'A';\n    auto& cells0 = pos[c0];\n    int sz0 = cells0.size();\n    for (int i = 0; i < sz0; ++i) {\n        dp_prev[i] = dist[start_idx][cells0[i]] + 1;\n    }\n    const int* cells_prev = cells0.data();\n    int sz_prev = sz0;\n    for (size_t k = 1; k < S.size(); ++k) {\n        char c = S[k] - 'A';\n        auto& cells_cur = pos[c];\n        int sz_cur = cells_cur.size();\n        fill_n(dp_cur, sz_cur, INF);\n        for (int j = 0; j < sz_prev; ++j) {\n            int prev_cell = cells_prev[j];\n            int base = dp_prev[j] + 1;\n            const int* drow = dist[prev_cell];\n            for (int i = 0; i < sz_cur; ++i) {\n                int cost = base + drow[cells_cur[i]];\n                if (cost < dp_cur[i]) dp_cur[i] = cost;\n            }\n        }\n        swap(dp_prev, dp_cur);\n        cells_prev = cells_cur.data();\n        sz_prev = sz_cur;\n    }\n    return *min_element(dp_prev, dp_prev + sz_prev);\n}\n\nvoid compute_DP_path(const string& S, vector<int>& path_out) {\n    int L = S.size();\n    path_out.resize(L);\n    if (L == 0) return;\n    vector<vector<int>> step_cells(L);\n    vector<vector<int>> step_prev(L);\n    char c0 = S[0] - 'A';\n    auto& cells0 = pos[c0];\n    int sz0 = cells0.size();\n    step_cells[0] = cells0;\n    step_prev[0].assign(sz0, -1);\n    for (int i = 0; i < sz0; ++i) dp_prev[i] = dist[start_idx][cells0[i]] + 1;\n    const int* cells_prev = cells0.data();\n    int sz_prev = sz0;\n    for (int k = 1; k < L; ++k) {\n        char c = S[k] - 'A';\n        auto& cells_cur = pos[c];\n        int sz_cur = cells_cur.size();\n        step_cells[k] = cells_cur;\n        step_prev[k].assign(sz_cur, -1);\n        fill_n(dp_cur, sz_cur, INF);\n        for (int j = 0; j < sz_prev; ++j) {\n            int prev_cell = cells_prev[j];\n            int base = dp_prev[j] + 1;\n            const int* drow = dist[prev_cell];\n            for (int i = 0; i < sz_cur; ++i) {\n                int cost = base + drow[cells_cur[i]];\n                if (cost < dp_cur[i]) {\n                    dp_cur[i] = cost;\n                    step_prev[k][i] = j;\n                }\n            }\n        }\n        swap(dp_prev, dp_cur);\n        cells_prev = cells_cur.data();\n        sz_prev = sz_cur;\n    }\n    int best_idx = min_element(dp_prev, dp_prev + sz_prev) - dp_prev;\n    for (int k = L - 1; k >= 0; --k) {\n        path_out[k] = step_cells[k][best_idx];\n        best_idx = step_prev[k][best_idx];\n    }\n}\n\nint main() {\n    auto start_time = chrono::steady_clock::now();\n    const double time_limit = 1.95;\n\n    cin >> N >> M;\n    cin >> start_i >> start_j;\n    for (int i = 0; i < N; ++i) {\n        string line;\n        cin >> line;\n        for (int j = 0; j < N; ++j) grid[i][j] = line[j];\n    }\n    t.resize(M);\n    for (int i = 0; i < M; ++i) cin >> t[i];\n\n    // precomputation\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            int idx = i * N + j;\n            pos[grid[i][j] - 'A'].push_back(idx);\n        }\n    start_idx = start_i * N + start_j;\n    for (int i = 0; i < 225; ++i) {\n        int xi = i / N, yi = i % N;\n        int* drow = dist[i];\n        for (int j = 0; j < 225; ++j) {\n            int xj = j / N, yj = j % N;\n            drow[j] = abs(xi - xj) + abs(yi - yj);\n        }\n    }\n\n    unordered_map<string, int> word_to_idx;\n    for (int i = 0; i < M; ++i) word_to_idx[t[i]] = i;\n\n    vector<vector<int>> ov(M, vector<int>(M, 0));\n    for (int i = 0; i < M; ++i)\n        for (int j = 0; j < M; ++j)\n            for (int k = 1; k <= 5; ++k)\n                if (t[i].substr(5 - k) == t[j].substr(0, k))\n                    ov[i][j] = k;\n\n    Xorshift rnd;\n\n    vector<pair<int, vector<int>>> candidates;\n    int best_len = INF;\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > time_limit * 0.6) break;\n\n        vector<bool> used(M, false);\n        vector<bool> present(M, false);\n        vector<int> perm;\n        string S;\n        int last = -1;\n        int used_cnt = 0;\n\n        while (used_cnt < M) {\n            vector<int> skips;\n            for (int i = 0; i < M; ++i)\n                if (!used[i] && present[i]) skips.push_back(i);\n            if (!skips.empty()) {\n                int pick = skips[rnd.nextInt(skips.size())];\n                used[pick] = true;\n                perm.push_back(pick);\n                used_cnt++;\n                continue;\n            }\n            int best_ov = -1;\n            vector<int> best_candidates;\n            for (int i = 0; i < M; ++i) {\n                if (used[i]) continue;\n                int cur_ov = (last == -1) ? 0 : ov[last][i];\n                if (cur_ov > best_ov) {\n                    best_ov = cur_ov;\n                    best_candidates.clear();\n                    best_candidates.push_back(i);\n                } else if (cur_ov == best_ov) {\n                    best_candidates.push_back(i);\n                }\n            }\n            int pick = best_candidates[rnd.nextInt(best_candidates.size())];\n            used[pick] = true;\n            perm.push_back(pick);\n            int old_len = S.size();\n            if (last == -1)\n                S = t[pick];\n            else\n                S += t[pick].substr(best_ov);\n            last = pick;\n            int new_len = S.size();\n            for (int start = max(0, old_len - 4); start <= new_len - 5; ++start) {\n                string sub = S.substr(start, 5);\n                auto it = word_to_idx.find(sub);\n                if (it != word_to_idx.end()) present[it->second] = true;\n            }\n            used_cnt++;\n        }\n        int len = S.size();\n        if (len <= best_len || candidates.size() < 50) {\n            candidates.push_back({len, perm});\n            sort(candidates.begin(), candidates.end());\n            if (candidates.size() > 50) candidates.pop_back();\n            best_len = candidates[0].first;\n        }\n    }\n\n    int best_total_cost = INF;\n    vector<int> best_path;\n    for (auto& p : candidates) {\n        string S;\n        vector<bool> present(M, false);\n        S.clear();\n        int last = -1;\n        for (int idx : p.second) {\n            if (present[idx]) continue;\n            int old_len = S.size();\n            int best_ov = (last == -1) ? 0 : ov[last][idx];\n            if (last == -1)\n                S = t[idx];\n            else\n                S += t[idx].substr(best_ov);\n            last = idx;\n            int new_len = S.size();\n            for (int start = max(0, old_len - 4); start <= new_len - 5; ++start) {\n                string sub = S.substr(start, 5);\n                auto it = word_to_idx.find(sub);\n                if (it != word_to_idx.end()) present[it->second] = true;\n            }\n        }\n        int cost = compute_DP_cost(S);\n        if (cost < best_total_cost) {\n            best_total_cost = cost;\n            compute_DP_path(S, best_path);\n        }\n    }\n\n    for (int cell : best_path) {\n        int i = cell / N, j = cell % N;\n        cout << i << \" \" << j << \"\\n\";\n    }\n\n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <bitset>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\nconstexpr int MAX_N2 = 400;   // 20*20 = 400\nconstexpr double INF = 1e100;\n\ndouble normal_cdf(double x) {\n    return 0.5 * erfc(-x / sqrt(2.0));\n}\n\nint N, M;\ndouble eps;\nint V_total;\n\nstruct Placement {\n    bitset<MAX_N2> cells;\n    vector<int> q_overlap;   // size Q, contribution to each query\n    vector<char> d_contrib;  // dynamic, size D, 1 if placement covers the drilled cell\n};\n\nstruct FieldInfo {\n    vector<Placement> placements;\n    vector<int> valid;       // indices of placements currently valid\n};\nvector<FieldInfo> fields;\n\n// queries\nint Q = 0;\nvector<bitset<MAX_N2>> query_sets;\nvector<int> query_results;\nvector<vector<double>> log_prob;  // Q x (V_total+1)\n\n// drills\nint D = 0;\nvector<int> drill_cells;\nvector<int> observed;\n\n// Random engine\nmt19937 gen(chrono::steady_clock::now().time_since_epoch().count());\n\ninline int idx(int i, int j) { return i * N + j; }\ninline pair<int,int> unidx(int id) { return {id / N, id % N}; }\n\nvoid read_input() {\n    cin >> N >> M >> eps;\n    fields.resize(M);\n    V_total = 0;\n    for (int k = 0; k < M; ++k) {\n        int d; cin >> d;\n        fields[k].placements.reserve( (N-0)*(N-0) ); // upper bound\n        vector<pair<int,int>> shape(d);\n        for (int a = 0; a < d; ++a) {\n            cin >> shape[a].first >> shape[a].second;\n        }\n        int max_i = 0, max_j = 0;\n        for (auto &p : shape) {\n            max_i = max(max_i, p.first);\n            max_j = max(max_j, p.second);\n        }\n        for (int dx = 0; dx <= N - 1 - max_i; ++dx) {\n            for (int dy = 0; dy <= N - 1 - max_j; ++dy) {\n                Placement pl;\n                bitset<MAX_N2> b;\n                for (auto &p : shape) {\n                    int r = dx + p.first;\n                    int c = dy + p.second;\n                    b.set(idx(r, c));\n                }\n                pl.cells = b;\n                fields[k].placements.push_back(pl);\n            }\n        }\n        V_total += d;\n        // initially all placements are valid\n        fields[k].valid.resize(fields[k].placements.size());\n        iota(fields[k].valid.begin(), fields[k].valid.end(), 0);\n    }\n}\n\nvoid generate_initial_queries(int num_queries) {\n    Q = num_queries;\n    if (Q > 2 * N * N - 10) Q = max(0, 2 * N * N - 10);\n    query_sets.resize(Q);\n    query_results.resize(Q);\n    \n    uniform_int_distribution<int> k_dist(max(2, N*N/2), N*N);\n    vector<int> indices(N*N);\n    iota(indices.begin(), indices.end(), 0);\n    \n    for (int i = 0; i < Q; ++i) {\n        int k = k_dist(gen);\n        shuffle(indices.begin(), indices.end(), gen);\n        bitset<MAX_N2> s;\n        for (int t = 0; t < k; ++t) s.set(indices[t]);\n        query_sets[i] = s;\n        \n        // output query\n        cout << \"q \" << k;\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                if (s.test(idx(r, c))) cout << \" \" << r << \" \" << c;\n            }\n        }\n        cout << \"\\n\" << flush;\n    }\n    \n    for (int i = 0; i < Q; ++i) {\n        cin >> query_results[i];\n    }\n}\n\nvoid precompute_log_prob() {\n    log_prob.resize(Q, vector<double>(V_total + 1));\n    for (int i = 0; i < Q; ++i) {\n        int k = (int)query_sets[i].count();\n        int y = query_results[i];\n        double sigma = sqrt(k * eps * (1.0 - eps));\n        for (int v = 0; v <= V_total; ++v) {\n            double mu = k * eps + v * (1.0 - 2.0 * eps);\n            double prob;\n            if (y == 0) {\n                prob = normal_cdf((0.5 - mu) / sigma);\n            } else {\n                prob = normal_cdf((y + 0.5 - mu) / sigma) - normal_cdf((y - 0.5 - mu) / sigma);\n            }\n            if (prob <= 0.0) prob = 1e-300;\n            log_prob[i][v] = log(prob);\n        }\n    }\n}\n\nvoid precompute_overlaps() {\n    for (int k = 0; k < M; ++k) {\n        for (auto &pl : fields[k].placements) {\n            pl.q_overlap.resize(Q);\n            for (int i = 0; i < Q; ++i) {\n                pl.q_overlap[i] = (pl.cells & query_sets[i]).count();\n            }\n        }\n    }\n}\n\n// ----------------------------------------------------------------------\n// Simulated Annealing\n\nstruct SAState {\n    vector<int> assign;        // absolute placement index for each field\n    vector<int> qover;         // sum of overlaps for each query\n    vector<int> dcnt;          // drill counts (matched exactly)\n    double energy;\n};\n\nSAState create_random_state() {\n    SAState st;\n    st.assign.resize(M);\n    for (int k = 0; k < M; ++k) {\n        const auto &valid = fields[k].valid;\n        uniform_int_distribution<int> dis(0, valid.size() - 1);\n        st.assign[k] = valid[dis(gen)];\n    }\n    st.qover.assign(Q, 0);\n    st.dcnt.assign(D, 0);\n    for (int k = 0; k < M; ++k) {\n        int p = st.assign[k];\n        const auto &pl = fields[k].placements[p];\n        for (int i = 0; i < Q; ++i) st.qover[i] += pl.q_overlap[i];\n        for (int d = 0; d < D; ++d) st.dcnt[d] += pl.d_contrib[d];\n    }\n    st.energy = 0;\n    for (int i = 0; i < Q; ++i) {\n        st.energy += log_prob[i][st.qover[i]];\n    }\n    return st;\n}\n\nSAState run_sa(int moves) {\n    SAState state = create_random_state();\n    vector<int> assign = state.assign;\n    vector<int> qover = state.qover;\n    vector<int> dcnt = state.dcnt;\n    double energy = state.energy;\n\n    double best_energy = energy;\n    vector<int> best_assign = assign;\n\n    uniform_real_distribution<double> real_dis(0.0, 1.0);\n    uniform_int_distribution<int> field_dis(0, M - 1);\n\n    double T_start = 10.0, T_end = 0.01;\n    for (int step = 0; step < moves; ++step) {\n        double frac = (double)step / moves;\n        double T = T_start * pow(T_end / T_start, frac);\n        int k = field_dis(gen);\n        const auto &valid = fields[k].valid;\n        if (valid.size() <= 1) continue;\n        int old_p = assign[k];\n        int idx_new = uniform_int_distribution<int>(0, valid.size() - 1)(gen);\n        int new_p = valid[idx_new];\n        if (new_p == old_p) continue;\n\n        const auto &old_pl = fields[k].placements[old_p];\n        const auto &new_pl = fields[k].placements[new_p];\n\n        // hard drill constraints\n        bool ok = true;\n        for (int d = 0; d < D; ++d) {\n            int new_cnt = dcnt[d] - old_pl.d_contrib[d] + new_pl.d_contrib[d];\n            if (new_cnt != observed[d]) { ok = false; break; }\n        }\n        if (!ok) continue;\n\n        // compute new energy\n        double new_energy = energy;\n        for (int i = 0; i < Q; ++i) {\n            int old_val = qover[i];\n            int new_val = old_val - old_pl.q_overlap[i] + new_pl.q_overlap[i];\n            new_energy += log_prob[i][new_val] - log_prob[i][old_val];\n        }\n\n        if (new_energy >= energy || real_dis(gen) < exp((new_energy - energy) / T)) {\n            assign[k] = new_p;\n            energy = new_energy;\n            for (int i = 0; i < Q; ++i) {\n                qover[i] = qover[i] - old_pl.q_overlap[i] + new_pl.q_overlap[i];\n            }\n            for (int d = 0; d < D; ++d) {\n                dcnt[d] = dcnt[d] - old_pl.d_contrib[d] + new_pl.d_contrib[d];\n            }\n            if (energy > best_energy) {\n                best_energy = energy;\n                best_assign = assign;\n            }\n        }\n    }\n\n    SAState result;\n    result.assign = best_assign;\n    result.qover.assign(Q, 0);\n    result.dcnt.assign(D, 0);\n    for (int k = 0; k < M; ++k) {\n        int p = best_assign[k];\n        const auto &pl = fields[k].placements[p];\n        for (int i = 0; i < Q; ++i) result.qover[i] += pl.q_overlap[i];\n        for (int d = 0; d < D; ++d) result.dcnt[d] += pl.d_contrib[d];\n    }\n    result.energy = 0;\n    for (int i = 0; i < Q; ++i) result.energy += log_prob[i][result.qover[i]];\n    return result;\n}\n\nbitset<MAX_N2> get_mask(const vector<int> &assign) {\n    bitset<MAX_N2> mask;\n    for (int k = 0; k < M; ++k) {\n        mask |= fields[k].placements[assign[k]].cells;\n    }\n    return mask;\n}\n\n// ----------------------------------------------------------------------\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cout << fixed << setprecision(10);\n\n    read_input();\n    int max_ops = 2 * N * N;\n    int ops_used = 0;\n\n    // Phase 1: a few cheap large queries\n    int Q_planned = 50;\n    if (Q_planned > max_ops - 5) Q_planned = max(0, max_ops - 5);\n    generate_initial_queries(Q_planned);\n    ops_used += Q;\n    \n    precompute_log_prob();\n    precompute_overlaps();\n\n    // Phase 2: run SA to quickly guess\n    SAState best;\n    double best_energy = -INF;\n    // run 3 independent SA runs and keep the best\n    for (int r = 0; r < 3; ++r) {\n        SAState st = run_sa(20000);   // 20k moves each\n        if (st.energy > best_energy) {\n            best_energy = st.energy;\n            best = st;\n        }\n    }\n\n    // Guess based on best state\n    bitset<MAX_N2> guess_mask = get_mask(best.assign);\n    vector<pair<int,int>> guess_cells;\n    for (int r = 0; r < N; ++r)\n        for (int c = 0; c < N; ++c)\n            if (guess_mask.test(idx(r, c)))\n                guess_cells.emplace_back(r, c);\n    \n    cout << \"a \" << guess_cells.size();\n    for (auto &p : guess_cells) cout << \" \" << p.first << \" \" << p.second;\n    cout << \"\\n\" << flush;\n    ++ops_used;\n\n    int answer_result;\n    cin >> answer_result;\n    if (answer_result == 1) return 0;\n\n    // Phase 3: guess was wrong \u2014 fallback to full drill\n    // We drill every cell not yet drilled (currently none) and record v>0.\n    vector<pair<int,int>> positive;\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            if (ops_used >= max_ops - 1) break; // need one op for final guess\n            cout << \"q 1 \" << r << \" \" << c << \"\\n\" << flush;\n            ++ops_used;\n            int v;\n            cin >> v;\n            if (v > 0) positive.emplace_back(r, c);\n        }\n    }\n\n    // Final guess with exactly the true positive cells\n    cout << \"a \" << positive.size();\n    for (auto &p : positive) cout << \" \" << p.first << \" \" << p.second;\n    cout << \"\\n\" << flush;\n    // Expect 1\n    cin >> answer_result;\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int i0, j0, i1, j1;\n    int area() const { return (i1 - i0) * (j1 - j0); }\n};\n\nint W, D, N;\nvector<vector<int>> a;\nvector<vector<Rect>> rects;\nint HORIZ_COUNT, VERT_COUNT, SEG;\nvector<uint8_t> wall_counts;\nint total_area_penalty = 0;\nint total_L_sum = 0;\n\n// xorshift random\nunsigned int rng_state = 123456789;\nunsigned int xorshift() {\n    rng_state ^= rng_state << 13;\n    rng_state ^= rng_state >> 17;\n    rng_state ^= rng_state << 5;\n    return rng_state;\n}\ndouble rand_double() {\n    return (xorshift() & 0xFFFFFFFF) / 4294967296.0;\n}\nint rand_int(int n) {\n    return xorshift() % n;\n}\n\nbool overlap(const Rect& a, const Rect& b) {\n    return a.i0 < b.i1 && b.i0 < a.i1 && a.j0 < b.j1 && b.j0 < a.j1;\n}\n\nvoid get_boundaries(const Rect& r, vector<int>& segs) {\n    segs.clear();\n    if (r.i0 >= 1 && r.i0 <= W - 1) {\n        int base = (r.i0 - 1) * W + r.j0;\n        for (int j = 0; j < r.j1 - r.j0; ++j) segs.push_back(base + j);\n    }\n    if (r.i1 >= 1 && r.i1 <= W - 1) {\n        int base = (r.i1 - 1) * W + r.j0;\n        for (int j = 0; j < r.j1 - r.j0; ++j) segs.push_back(base + j);\n    }\n    if (r.j0 >= 1 && r.j0 <= W - 1) {\n        int base = HORIZ_COUNT + (r.j0 - 1);\n        for (int i = r.i0; i < r.i1; ++i) segs.push_back(base + i * (W - 1));\n    }\n    if (r.j1 >= 1 && r.j1 <= W - 1) {\n        int base = HORIZ_COUNT + (r.j1 - 1);\n        for (int i = r.i0; i < r.i1; ++i) segs.push_back(base + i * (W - 1));\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> W >> D >> N;\n    a.resize(D, vector<int>(N));\n    for (int d = 0; d < D; ++d)\n        for (int k = 0; k < N; ++k)\n            cin >> a[d][k];\n\n    HORIZ_COUNT = (W - 1) * W;\n    VERT_COUNT = W * (W - 1);\n    SEG = HORIZ_COUNT + VERT_COUNT;\n\n    rects.resize(D, vector<Rect>(N));\n\n    // ----- initial packing per day (maxrects best\u2011fit) -----\n    for (int d = 0; d < D; ++d) {\n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int x, int y) {\n            return a[d][x] > a[d][y];\n        });\n\n        struct FreeRect { int i0, j0, i1, j1; };\n        vector<FreeRect> free;\n        free.push_back({0, 0, W, W});\n        vector<Rect> placed(N);\n        bool ok = true;\n\n        for (int idx : order) {\n            int req = a[d][idx];\n\n            // best\u2011fit free rectangle\n            int best = -1;\n            int best_area = INT_MAX;\n            for (int i = 0; i < (int)free.size(); ++i) {\n                int fa = (free[i].i1 - free[i].i0) * (free[i].j1 - free[i].j0);\n                if (fa >= req && fa < best_area) {\n                    best_area = fa;\n                    best = i;\n                }\n            }\n            if (best == -1) {\n                // fallback : take first that fits (should not happen)\n                for (int i = 0; i < (int)free.size(); ++i) {\n                    int fa = (free[i].i1 - free[i].i0) * (free[i].j1 - free[i].j0);\n                    if (fa >= req) { best = i; break; }\n                }\n            }\n            if (best == -1) { ok = false; break; }\n\n            FreeRect fr = free[best];\n            free.erase(free.begin() + best);\n\n            int avail_w = fr.j1 - fr.j0;\n            int avail_h = fr.i1 - fr.i0;\n            int w = min(avail_w, max(1, (int)ceil(sqrt(req))));\n            int h = (req + w - 1) / w;\n            if (h > avail_h) {\n                h = avail_h;\n                w = (req + h - 1) / h;\n                if (w > avail_w) w = avail_w;\n            }\n            Rect r;\n            r.i0 = fr.i0; r.j0 = fr.j0;\n            r.i1 = r.i0 + h; r.j1 = r.j0 + w;\n\n            if (r.j1 < fr.j1) free.push_back({fr.i0, r.j1, r.i1, fr.j1});\n            if (r.i1 < fr.i1) free.push_back({r.i1, fr.j0, fr.i1, fr.j1});\n\n            placed[idx] = r;\n        }\n\n        if (!ok) {\n            // fallback : simple row strip packing (height = 1)\n            free.clear();\n            free.push_back({0, 0, W, W});\n            for (int idx : order) {\n                int req = a[d][idx];\n                int best = -1;\n                for (int i = 0; i < (int)free.size(); ++i) {\n                    if ((free[i].i1 - free[i].i0) * (free[i].j1 - free[i].j0) >= req) {\n                        best = i; break;\n                    }\n                }\n                FreeRect fr = free[best];\n                free.erase(free.begin() + best);\n                int w = min(fr.j1 - fr.j0, req);\n                int h = (req + w - 1) / w;\n                if (h > fr.i1 - fr.i0) h = fr.i1 - fr.i0;\n                Rect r;\n                r.i0 = fr.i0; r.j0 = fr.j0;\n                r.i1 = fr.i0 + h; r.j1 = fr.j0 + w;\n                if (r.j1 < fr.j1) free.push_back({fr.i0, r.j1, r.i1, fr.j1});\n                if (r.i1 < fr.i1) free.push_back({r.i1, fr.j0, fr.i1, fr.j1});\n                placed[idx] = r;\n            }\n        }\n        rects[d] = placed;\n    }\n\n    // ----- build wall_counts and initial cost -----\n    wall_counts.assign(D * SEG, 0);\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            vector<int> segs;\n            get_boundaries(rects[d][k], segs);\n            for (int s : segs) wall_counts[d * SEG + s]++;\n        }\n    }\n\n    total_area_penalty = 0;\n    for (int d = 0; d < D; ++d)\n        for (int k = 0; k < N; ++k) {\n            int area = rects[d][k].area();\n            if (area < a[d][k]) total_area_penalty += 100 * (a[d][k] - area);\n        }\n\n    total_L_sum = 0;\n    for (int d = 1; d < D; ++d) {\n        int off_prev = (d - 1) * SEG;\n        int off_cur = d * SEG;\n        for (int s = 0; s < SEG; ++s) {\n            total_L_sum += ((wall_counts[off_prev + s] > 0) != (wall_counts[off_cur + s] > 0));\n        }\n    }\n\n    int best_cost = total_area_penalty + total_L_sum;\n    vector<vector<Rect>> best_rects = rects;\n\n    // ----- SA -----\n    double T0 = 10000.0;\n    double time_limit = 2.9;\n    auto start_time = chrono::steady_clock::now();\n\n    vector<int> old_segs, new_segs;\n    old_segs.reserve(4000);\n    new_segs.reserve(4000);\n    vector<int> only_old, only_new;\n    only_old.reserve(4000);\n    only_new.reserve(4000);\n\n    while (true) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n        if (elapsed > time_limit) break;\n        double T = T0 * (1.0 - elapsed / time_limit);\n        if (T < 0.1) T = 0.1;\n\n        for (int sub = 0; sub < 200; ++sub) {\n            int d = rand_int(D);\n            int k = rand_int(N);\n            int move_type = rand_int(3);\n            Rect old_rect = rects[d][k];\n            Rect new_rect;\n\n            if (move_type == 0) {   // shift\n                int dx = rand_int(7) - 3;\n                int dy = rand_int(7) - 3;\n                if (dx == 0 && dy == 0) continue;\n                new_rect = {old_rect.i0 + dx, old_rect.j0 + dy, old_rect.i1 + dx, old_rect.j1 + dy};\n            } else if (move_type == 1) {  // resize\n                int side = rand_int(4);\n                int delta = rand_int(11) - 5;\n                if (delta == 0) continue;\n                new_rect = old_rect;\n                if (side == 0) new_rect.i0 += delta;\n                else if (side == 1) new_rect.i1 += delta;\n                else if (side == 2) new_rect.j0 += delta;\n                else new_rect.j1 += delta;\n            } else {  // copy from adjacent day\n                int adj = d + (rand_int(2) == 0 ? -1 : 1);\n                if (adj < 0 || adj >= D) continue;\n                new_rect = rects[adj][k];\n            }\n\n            // fast validity checks\n            if (new_rect.i0 < 0 || new_rect.j0 < 0 || new_rect.i1 > W || new_rect.j1 > W) continue;\n            if (new_rect.i0 >= new_rect.i1 || new_rect.j0 >= new_rect.j1) continue;\n            bool bad = false;\n            for (int k2 = 0; k2 < N; ++k2) {\n                if (k2 == k) continue;\n                if (overlap(new_rect, rects[d][k2])) { bad = true; break; }\n            }\n            if (bad) continue;\n\n            // area penalty change\n            int old_area = old_rect.area();\n            int new_area = new_rect.area();\n            int old_short = max(0, a[d][k] - old_area);\n            int new_short = max(0, a[d][k] - new_area);\n            int delta_area = 100 * (new_short - old_short);\n\n            // boundary segments (old / new)\n            get_boundaries(old_rect, old_segs);\n            get_boundaries(new_rect, new_segs);\n            sort(old_segs.begin(), old_segs.end());\n            sort(new_segs.begin(), new_segs.end());\n\n            only_old.clear(); only_new.clear();\n            size_t i = 0, j = 0;\n            while (i < old_segs.size() || j < new_segs.size()) {\n                if (i < old_segs.size() && (j == new_segs.size() || old_segs[i] < new_segs[j])) {\n                    only_old.push_back(old_segs[i]); ++i;\n                } else if (j < new_segs.size() && (i == old_segs.size() || new_segs[j] < old_segs[i])) {\n                    only_new.push_back(new_segs[j]); ++j;\n                } else {\n                    ++i; ++j;\n                }\n            }\n\n            int delta_L = 0;\n            int off_d = d * SEG;\n\n            for (int seg : only_old) {\n                int wc = wall_counts[off_d + seg];\n                bool old_st = (wc > 0);\n                bool new_st = ((wc - 1) > 0);\n                if (old_st != new_st) {\n                    if (d > 0) {\n                        bool prev_st = (wall_counts[(d - 1) * SEG + seg] > 0);\n                        delta_L += (new_st != prev_st) - (old_st != prev_st);\n                    }\n                    if (d + 1 < D) {\n                        bool next_st = (wall_counts[(d + 1) * SEG + seg] > 0);\n                        delta_L += (new_st != next_st) - (old_st != next_st);\n                    }\n                }\n            }\n            for (int seg : only_new) {\n                int wc = wall_counts[off_d + seg];\n                bool old_st = (wc > 0);\n                bool new_st = ((wc + 1) > 0);\n                if (old_st != new_st) {\n                    if (d > 0) {\n                        bool prev_st = (wall_counts[(d - 1) * SEG + seg] > 0);\n                        delta_L += (new_st != prev_st) - (old_st != prev_st);\n                    }\n                    if (d + 1 < D) {\n                        bool next_st = (wall_counts[(d + 1) * SEG + seg] > 0);\n                        delta_L += (new_st != next_st) - (old_st != next_st);\n                    }\n                }\n            }\n\n            int delta_cost = delta_area + delta_L;\n            if (delta_cost <= 0 || rand_double() < exp(-delta_cost / T)) {\n                // accept\n                rects[d][k] = new_rect;\n                total_area_penalty += delta_area;\n                total_L_sum += delta_L;\n                for (int seg : only_old) wall_counts[off_d + seg]--;\n                for (int seg : only_new) wall_counts[off_d + seg]++;\n            }\n        }\n\n        int cur_cost = total_area_penalty + total_L_sum;\n        if (cur_cost < best_cost) {\n            best_cost = cur_cost;\n            best_rects = rects;\n        }\n    }\n\n    // ----- output best solution -----\n    for (int d = 0; d < D; ++d)\n        for (int k = 0; k < N; ++k) {\n            Rect r = best_rects[d][k];\n            cout << r.i0 << \" \" << r.j0 << \" \" << r.i1 << \" \" << r.j1 << \"\\n\";\n        }\n\n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <array>\n#include <chrono>\n#include <random>\n#include <climits>\n#include <cmath>\n\nusing namespace std;\nusing ll = long long;\nusing ull = unsigned long long;\n\nconst int MOD = 998244353;\n\nstruct Move {\n    int m, p, q;\n    int cells[9];\n    int vals[9];\n};\n\nstruct XorShift {\n    ull s;\n    XorShift(ull seed) : s(seed) {}\n    ull next() {\n        s ^= s << 13;\n        s ^= s >> 7;\n        s ^= s << 17;\n        return s;\n    }\n    int next_int(int mod) {\n        return next() % mod;\n    }\n    double next_double() {\n        return (next() >> 11) * (1.0 / (1ULL << 53));\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K;\n    cin >> N >> M >> K;\n    \n    int initial_a[81];\n    int board[81];\n    ll sum_score = 0;\n    for(int i=0; i<N*N; ++i) {\n        int x; cin >> x;\n        initial_a[i] = x;\n        board[i] = x;\n        sum_score += x;\n    }\n\n    vector<vector<vector<int>>> stamps(M, vector<vector<int>>(3, vector<int>(3)));\n    for(int m=0; m<M; ++m) {\n        for(int i=0; i<3; ++i) for(int j=0; j<3; ++j) cin >> stamps[m][i][j];\n    }\n\n    // Precompute all possible moves (stamp placement)\n    vector<Move> moves;\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                Move mv;\n                mv.m = m; mv.p = p; mv.q = q;\n                int idx = 0;\n                for(int i=0; i<3; ++i) {\n                    for(int j=0; j<3; ++j) {\n                        int cell = (p+i)*N + (q+j);\n                        mv.cells[idx] = cell;\n                        mv.vals[idx] = stamps[m][i][j];\n                        ++idx;\n                    }\n                }\n                moves.push_back(mv);\n            }\n        }\n    }\n    int total_moves = moves.size();\n\n    // Lambda functions for board operations\n    auto eval_add = [&](int move_id) -> ll {\n        ll d = 0;\n        const auto& mv = moves[move_id];\n        for(int i=0; i<9; ++i) {\n            int c = mv.cells[i];\n            int v = mv.vals[i];\n            int old = board[c];\n            int nv = old + v;\n            if(nv >= MOD) nv -= MOD;\n            d += nv - old;\n        }\n        return d;\n    };\n    auto eval_remove = [&](int move_id) -> ll {\n        ll d = 0;\n        const auto& mv = moves[move_id];\n        for(int i=0; i<9; ++i) {\n            int c = mv.cells[i];\n            int v = mv.vals[i];\n            int old = board[c];\n            int nv = old - v;\n            if(nv < 0) nv += MOD;\n            d += nv - old;\n        }\n        return d;\n    };\n    auto apply_add = [&](int move_id) {\n        const auto& mv = moves[move_id];\n        for(int i=0; i<9; ++i) {\n            int c = mv.cells[i];\n            int v = mv.vals[i];\n            int old = board[c];\n            int nv = old + v;\n            if(nv >= MOD) nv -= MOD;\n            board[c] = nv;\n            sum_score += nv - old;\n        }\n    };\n    auto apply_remove = [&](int move_id) {\n        const auto& mv = moves[move_id];\n        for(int i=0; i<9; ++i) {\n            int c = mv.cells[i];\n            int v = mv.vals[i];\n            int old = board[c];\n            int nv = old - v;\n            if(nv < 0) nv += MOD;\n            board[c] = nv;\n            sum_score += nv - old;\n        }\n    };\n\n    vector<int> applied_moves;\n\n    // 1. Greedy initial solution\n    while((int)applied_moves.size() < K) {\n        ll best_delta = 0;\n        int best_move = -1;\n        for(int m=0; m<total_moves; ++m) {\n            ll d = eval_add(m);\n            if(d > best_delta) {\n                best_delta = d;\n                best_move = m;\n            }\n        }\n        if(best_delta <= 0) break;\n        apply_add(best_move);\n        applied_moves.push_back(best_move);\n    }\n\n    vector<int> best_applied = applied_moves;\n    ll best_score = sum_score;\n\n    // 2. Simulated Annealing\n    random_device rd;\n    ull seed = ((ull)rd() << 32) | rd();\n    XorShift rng(seed);\n\n    chrono::steady_clock::time_point start_time = chrono::steady_clock::now();\n    double time_limit = 1.9;                // seconds for SA\n    double T_start = 1e9;\n    double T_end = 1e0;\n    double log_ratio = log(T_end / T_start); // negative\n\n    int iter = 0;\n    double T = T_start;\n    while(true) {\n        if((iter & 255) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if(elapsed >= time_limit) break;\n            double progress = elapsed / time_limit;\n            T = T_start * exp(progress * log_ratio);\n        }\n        int L = applied_moves.size();\n        if(L == 0) {\n            int nm = rng.next_int(total_moves);\n            ll delta = eval_add(nm);\n            if(delta >= 0 || rng.next_double() < exp(delta / T)) {\n                apply_add(nm);\n                applied_moves.push_back(nm);\n                if(sum_score > best_score) {\n                    best_score = sum_score;\n                    best_applied = applied_moves;\n                }\n            }\n        } else if(L == K) {\n            double r = rng.next_double();\n            if(r < 0.5) {\n                int idx = rng.next_int(L);\n                int old_move = applied_moves[idx];\n                ll delta = eval_remove(old_move);\n                if(delta >= 0 || rng.next_double() < exp(delta / T)) {\n                    apply_remove(old_move);\n                    applied_moves[idx] = applied_moves.back();\n                    applied_moves.pop_back();\n                    if(sum_score > best_score) {\n                        best_score = sum_score;\n                        best_applied = applied_moves;\n                    }\n                }\n            } else {\n                int idx = rng.next_int(L);\n                int old_move = applied_moves[idx];\n                ll score_before = sum_score;\n                apply_remove(old_move);\n                int new_move = rng.next_int(total_moves);\n                ll delta_add = eval_add(new_move);\n                ll total_delta = (sum_score - score_before) + delta_add;\n                if(total_delta >= 0 || rng.next_double() < exp(total_delta / T)) {\n                    apply_add(new_move);\n                    applied_moves[idx] = new_move;\n                    if(sum_score > best_score) {\n                        best_score = sum_score;\n                        best_applied = applied_moves;\n                    }\n                } else {\n                    apply_add(old_move);\n                }\n            }\n        } else {\n            double r = rng.next_double();\n            if(r < 0.4) {\n                int nm = rng.next_int(total_moves);\n                ll delta = eval_add(nm);\n                if(delta >= 0 || rng.next_double() < exp(delta / T)) {\n                    apply_add(nm);\n                    applied_moves.push_back(nm);\n                    if(sum_score > best_score) {\n                        best_score = sum_score;\n                        best_applied = applied_moves;\n                    }\n                }\n            } else if(r < 0.7) {\n                int idx = rng.next_int(L);\n                int old_move = applied_moves[idx];\n                ll score_before = sum_score;\n                apply_remove(old_move);\n                int new_move = rng.next_int(total_moves);\n                ll delta_add = eval_add(new_move);\n                ll total_delta = (sum_score - score_before) + delta_add;\n                if(total_delta >= 0 || rng.next_double() < exp(total_delta / T)) {\n                    apply_add(new_move);\n                    applied_moves[idx] = new_move;\n                    if(sum_score > best_score) {\n                        best_score = sum_score;\n                        best_applied = applied_moves;\n                    }\n                } else {\n                    apply_add(old_move);\n                }\n            } else {\n                int idx = rng.next_int(L);\n                int old_move = applied_moves[idx];\n                ll delta = eval_remove(old_move);\n                if(delta >= 0 || rng.next_double() < exp(delta / T)) {\n                    apply_remove(old_move);\n                    applied_moves[idx] = applied_moves.back();\n                    applied_moves.pop_back();\n                    if(sum_score > best_score) {\n                        best_score = sum_score;\n                        best_applied = applied_moves;\n                    }\n                }\n            }\n        }\n        ++iter;\n    }\n\n    // 3. Restore the best state found by SA\n    applied_moves = best_applied;\n    sum_score = 0;\n    for(int i=0; i<N*N; ++i) {\n        board[i] = initial_a[i];\n        sum_score += board[i];\n    }\n    for(int m_id : applied_moves) {\n        apply_add(m_id);\n    }\n\n    // 4. Final hill-climbing polishing\n    bool improved = true;\n    while(improved) {\n        improved = false;\n        int L = applied_moves.size();\n\n        // Try to add a move\n        if(L < K) {\n            int best_move = -1;\n            ll best_delta = 0;\n            for(int m=0; m<total_moves; ++m) {\n                ll d = eval_add(m);\n                if(d > best_delta) {\n                    best_delta = d;\n                    best_move = m;\n                }\n            }\n            if(best_delta > 0) {\n                apply_add(best_move);\n                applied_moves.push_back(best_move);\n                improved = true;\n                if(sum_score > best_score) {\n                    best_score = sum_score;\n                    best_applied = applied_moves;\n                }\n                continue;\n            }\n        }\n\n        // Try to remove a move\n        if(L > 0) {\n            int best_idx = -1;\n            ll best_delta = 0;\n            for(int i=0; i<L; ++i) {\n                ll d = eval_remove(applied_moves[i]);\n                if(d > best_delta) {\n                    best_delta = d;\n                    best_idx = i;\n                }\n            }\n            if(best_delta > 0) {\n                int m = applied_moves[best_idx];\n                apply_remove(m);\n                applied_moves[best_idx] = applied_moves.back();\n                applied_moves.pop_back();\n                improved = true;\n                if(sum_score > best_score) {\n                    best_score = sum_score;\n                    best_applied = applied_moves;\n                }\n                continue;\n            }\n        }\n\n        // Try to replace a move\n        if(L > 0) {\n            bool found_replace = false;\n            for(int i=0; i<L && !found_replace; ++i) {\n                int old_move = applied_moves[i];\n                ll score_before = sum_score;\n                apply_remove(old_move);\n\n                int best_new = -1;\n                ll best_total_delta = 0; // we only care about positive improvement\n                for(int new_m=0; new_m<total_moves; ++new_m) {\n                    ll delta_add = eval_add(new_m);\n                    ll total_delta = (sum_score - score_before) + delta_add;\n                    if(total_delta > best_total_delta) {\n                        best_total_delta = total_delta;\n                        best_new = new_m;\n                    }\n                }\n                if(best_total_delta > 0) {\n                    apply_add(best_new);\n                    applied_moves[i] = best_new;\n                    improved = true;\n                    if(sum_score > best_score) {\n                        best_score = sum_score;\n                        best_applied = applied_moves;\n                    }\n                    found_replace = true;\n                } else {\n                    // revert removal\n                    apply_add(old_move);\n                }\n            }\n            if(found_replace) continue;\n        }\n    }\n\n    // Output the best sequence of operations\n    cout << best_applied.size() << \"\\n\";\n    for(int m_id : best_applied) {\n        cout << moves[m_id].m << \" \" << moves[m_id].p << \" \" << moves[m_id].q << \"\\n\";\n    }\n\n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <tuple>\n#include <queue>\nusing namespace std;\n\nint main() {\n    const int N = 5;\n    vector<vector<int>> A(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> A[i][j];\n\n    vector<int> id_to_row(N * N);\n    vector<int> arrival_order[N];\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            id_to_row[A[i][j]] = i;\n            arrival_order[i].push_back(A[i][j]);\n        }\n    }\n\n    int arrival_idx[N] = {0};\n    int ground[N][N];\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            ground[i][j] = -1;\n\n    int container_pos[25];\n    for (int i = 0; i < 25; ++i) container_pos[i] = -1;  // -1: not on ground, -2: dispatched\n\n    int L_r = 0, L_c = 0;\n    int L_holding = -1;\n    int cur_target = 0;\n    string L_actions;\n    int turn = 0;\n\n    auto move_towards = [&](int tr, int tc) -> char {\n        if (L_r < tr) return 'D';\n        if (L_r > tr) return 'U';\n        if (L_c < tc) return 'R';\n        if (L_c > tc) return 'L';\n        return '.';\n    };\n\n    auto find_buffer_cell = [&](int cont) -> pair<int,int> {\n        int tr = cont / 5;\n        // 1) current cell if it is empty and not a dispatch gate\n        if (ground[L_r][L_c] == -1) {\n            if (L_c != 4 && !(L_c == 0 && arrival_idx[L_r] < N)) {\n                return {L_r, L_c};\n            }\n        }\n        // 2) target row, preferred columns 3,2,1\n        for (int c : {3, 2, 1}) {\n            if (ground[tr][c] == -1) return {tr, c};\n        }\n        if (arrival_idx[tr] >= N && ground[tr][0] == -1) return {tr, 0};\n        // 3) other rows\n        for (int r = 0; r < N; ++r) {\n            if (r == tr) continue;\n            for (int c : {3, 2, 1}) {\n                if (ground[r][c] == -1) return {r, c};\n            }\n            if (arrival_idx[r] >= N && ground[r][0] == -1) return {r, 0};\n        }\n        // 4) any other cell except dispatch gates (col 4) and receiving gates that still have pending containers\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c <= 3; ++c) {\n                if (ground[r][c] == -1) {\n                    if (c == 0 && arrival_idx[r] < N) continue;\n                    return {r, c};\n                }\n            }\n        }\n        // absolute fallback (should never be reached)\n        return {L_r, L_c};\n    };\n\n    while (cur_target < 25 && turn < 10000) {\n        // ---------- Step 1 : Receiving ----------\n        for (int i = 0; i < N; ++i) {\n            if (ground[i][0] == -1 && arrival_idx[i] < N) {\n                // arrival is blocked only if a crane holding a container is present\n                bool blocked = (L_holding != -1 && L_r == i && L_c == 0);\n                if (!blocked) {\n                    int cont = arrival_order[i][arrival_idx[i]++];\n                    ground[i][0] = cont;\n                    container_pos[cont] = i * 5 + 0;\n                }\n            }\n        }\n\n        // ---------- Step 2 : Large crane action ----------\n        char act = '.';\n        if (L_holding != -1) {\n            int cont = L_holding;\n            if (cont == cur_target) {\n                int tr = cont / 5;\n                int tc = 4;\n                if (L_r == tr && L_c == tc) {\n                    act = 'Q';\n                } else {\n                    act = move_towards(tr, tc);\n                }\n            } else {\n                auto [tr, tc] = find_buffer_cell(cont);\n                if (L_r == tr && L_c == tc) {\n                    act = 'Q';\n                } else {\n                    act = move_towards(tr, tc);\n                }\n            }\n        } else {\n            int c = cur_target;\n            int r = id_to_row[c];\n            if (container_pos[c] >= 0) {\n                int pos = container_pos[c];\n                int tr = pos / 5, tc = pos % 5;\n                if (L_r == tr && L_c == tc) {\n                    act = 'P';\n                } else {\n                    act = move_towards(tr, tc);\n                }\n            } else {\n                // not on ground\n                if (ground[r][0] == c) {\n                    if (L_r == r && L_c == 0) {\n                        act = 'P';\n                    } else {\n                        act = move_towards(r, 0);\n                    }\n                } else if (ground[r][0] != -1) {\n                    // gate blocked by another container\n                    if (L_r == r && L_c == 0) {\n                        act = 'P';\n                    } else {\n                        act = move_towards(r, 0);\n                    }\n                } else {\n                    // wait near the gate\n                    int tr = r, tc = 1;\n                    if (L_r == tr && L_c == tc) {\n                        act = '.';\n                    } else {\n                        act = move_towards(tr, tc);\n                    }\n                }\n            }\n        }\n\n        // Apply L action\n        if (act == 'U') L_r--;\n        else if (act == 'D') L_r++;\n        else if (act == 'L') L_c--;\n        else if (act == 'R') L_c++;\n        else if (act == 'P') {\n            int cont = ground[L_r][L_c];\n            ground[L_r][L_c] = -1;\n            L_holding = cont;\n            container_pos[cont] = -1;\n        } else if (act == 'Q') {\n            ground[L_r][L_c] = L_holding;\n            container_pos[L_holding] = L_r * 5 + L_c;\n            L_holding = -1;\n        }\n        L_actions.push_back(act);\n\n        // ---------- Step 3 : Dispatching ----------\n        for (int i = 0; i < N; ++i) {\n            if (ground[i][4] != -1) {\n                int cont = ground[i][4];\n                ground[i][4] = -1;\n                container_pos[cont] = -2;\n                if (cont == cur_target) {\n                    ++cur_target;\n                }\n            }\n        }\n\n        ++turn;\n    }\n\n    // Output\n    cout << L_actions << \"\\n\";\n    for (int i = 1; i < N; ++i) {\n        cout << \"B\\n\";\n    }\n\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Task {\n    int r, c, h;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N; // N = 20\n    vector<vector<int>> H(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> H[i][j];\n        }\n    }\n\n    // Collect non-zero cells as tasks\n    vector<Task> tasks;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (H[i][j] != 0) {\n                tasks.push_back({i, j, H[i][j]});\n            }\n        }\n    }\n    int S = tasks.size();\n    if (S == 0) {\n        // All zero, no operations\n        return 0;\n    }\n\n    // Manhattan distance\n    auto manhattan = [&](int r1, int c1, int r2, int c2) {\n        return abs(r1 - r2) + abs(c1 - c2);\n    };\n\n    // Precompute distances\n    vector<int> start_dist(S);\n    for (int i = 0; i < S; ++i) {\n        start_dist[i] = manhattan(0, 0, tasks[i].r, tasks[i].c);\n    }\n    vector<vector<int>> dist(S, vector<int>(S));\n    for (int i = 0; i < S; ++i) {\n        for (int j = 0; j < S; ++j) {\n            dist[i][j] = manhattan(tasks[i].r, tasks[i].c, tasks[j].r, tasks[j].c);\n        }\n    }\n\n    // Evaluate a permutation (movement cost only, infeasible if load < 0 at any point)\n    auto evaluate = [&](const vector<int>& perm) -> pair<long long, bool> {\n        long long cost = 0;\n        int load = 0;\n        int pos = -1; // -1 means (0,0)\n        for (int idx : perm) {\n            int d = (pos == -1) ? start_dist[idx] : dist[pos][idx];\n            cost += d * (100LL + load);\n            load += tasks[idx].h;\n            if (load < 0) return {0, false};\n            pos = idx;\n        }\n        // load should be 0 at the end because sum of h = 0, but we don't strictly check\n        return {cost, true};\n    };\n\n    // Build initial solution: all positives first, then negatives\n    vector<int> pos_idx, neg_idx;\n    for (int i = 0; i < S; ++i) {\n        if (tasks[i].h > 0) pos_idx.push_back(i);\n        else neg_idx.push_back(i);\n    }\n\n    // Greedy construction for positives (nearest neighbor from (0,0))\n    auto build_greedy_positives = [&]() {\n        vector<int> order;\n        vector<bool> used(S, false);\n        int cur_r = 0, cur_c = 0;\n        while ((int)order.size() < (int)pos_idx.size()) {\n            int best = -1;\n            int best_d = 1e9;\n            for (int i : pos_idx) {\n                if (used[i]) continue;\n                int d = manhattan(cur_r, cur_c, tasks[i].r, tasks[i].c);\n                if (d < best_d) {\n                    best_d = d;\n                    best = i;\n                }\n            }\n            order.push_back(best);\n            used[best] = true;\n            cur_r = tasks[best].r;\n            cur_c = tasks[best].c;\n        }\n        return order;\n    };\n\n    // Greedy construction for negatives (nearest neighbor from last positive)\n    auto build_greedy_negatives = [&](int start_r, int start_c) {\n        vector<int> order;\n        vector<bool> used(S, false);\n        // mark positives as used (they are already in the positive order, but we just need to pick negatives)\n        // simpler: just pass used negatives\n        int cur_r = start_r, cur_c = start_c;\n        while ((int)order.size() < (int)neg_idx.size()) {\n            int best = -1;\n            int best_d = 1e9;\n            for (int i : neg_idx) {\n                // we don't have a global used here; we just pick from neg_idx each time\n                // Use a local bool array or just ensure we don't pick already chosen\n                // We'll use a vector<bool> local_used(neg_idx.size(), false) manually.\n                // But easier: just iterate over neg_idx and skip already in order.\n                if (find(order.begin(), order.end(), i) != order.end()) continue;\n                int d = manhattan(cur_r, cur_c, tasks[i].r, tasks[i].c);\n                if (d < best_d) {\n                    best_d = d;\n                    best = i;\n                }\n            }\n            order.push_back(best);\n            cur_r = tasks[best].r;\n            cur_c = tasks[best].c;\n        }\n        return order;\n    };\n\n    int last_pos_r = 0, last_pos_c = 0;\n    vector<int> best_perm;\n    if (!pos_idx.empty()) {\n        vector<int> pos_order = build_greedy_positives();\n        last_pos_r = tasks[pos_order.back()].r;\n        last_pos_c = tasks[pos_order.back()].c;\n        vector<int> neg_order = build_greedy_negatives(last_pos_r, last_pos_c);\n        best_perm = pos_order;\n        best_perm.insert(best_perm.end(), neg_order.begin(), neg_order.end());\n    } else {\n        // All negatives? Should not happen with sum=0 and non-zero tasks, but just in case.\n        // Start from (0,0) with load 0, cannot unload, so put negatives first would be infeasible.\n        // Actually if all negatives, sum != 0, so impossible.\n        // We'll leave best_perm empty; program will likely fail but won't happen.\n    }\n\n    auto [best_cost, feasible] = evaluate(best_perm);\n    // If the greedy result is infeasible (shouldn't be), fallback to simple all positives first by sorting.\n    if (!feasible) {\n        // Just concatenate positives then negatives in arbitrary order\n        best_perm = pos_idx;\n        best_perm.insert(best_perm.end(), neg_idx.begin(), neg_idx.end());\n        auto res = evaluate(best_perm);\n        best_cost = res.first;\n    }\n\n    // Try a few random shuffles of positives and negatives separately to improve initial solution\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto rand_int = [&](int lo, int hi) {\n        return uniform_int_distribution<int>(lo, hi)(rng);\n    };\n    auto shuffle_vec = [&](vector<int>& v) {\n        shuffle(v.begin(), v.end(), rng);\n    };\n\n    int initial_trials = 50;\n    for (int t = 0; t < initial_trials; ++t) {\n        vector<int> pos = pos_idx, neg = neg_idx;\n        shuffle_vec(pos);\n        shuffle_vec(neg);\n        vector<int> cand = pos;\n        cand.insert(cand.end(), neg.begin(), neg.end());\n        auto [cst, ok] = evaluate(cand);\n        if (ok && cst < best_cost) {\n            best_cost = cst;\n            best_perm = move(cand);\n        }\n    }\n\n    // SA parameters\n    auto start_time = chrono::steady_clock::now();\n    double T = 1000000.0;\n    double T_min = 0.1;\n    double alpha = 0.9999;\n    int iter = 0;\n    vector<int> cur_perm = best_perm;\n    long long cur_cost = best_cost;\n\n    uniform_real_distribution<double> rand_double(0.0, 1.0);\n\n    while (true) {\n        int move_type = rand_int(0, 2); // 0:swap, 1:reverse, 2:insert\n        bool improved = false;\n        if (move_type == 0) { // swap\n            int i = rand_int(0, S - 1);\n            int j = rand_int(0, S - 1);\n            if (i == j) continue;\n            swap(cur_perm[i], cur_perm[j]);\n            auto [new_cost, feas] = evaluate(cur_perm);\n            if (feas && (new_cost < cur_cost || rand_double(rng) < exp((cur_cost - new_cost) / T))) {\n                cur_cost = new_cost;\n                improved = true;\n            } else {\n                swap(cur_perm[i], cur_perm[j]); // revert\n            }\n        } else if (move_type == 1) { // reverse\n            if (S < 2) continue;\n            int i = rand_int(0, S - 2);\n            int j = rand_int(i + 1, S - 1);\n            reverse(cur_perm.begin() + i, cur_perm.begin() + j + 1);\n            auto [new_cost, feas] = evaluate(cur_perm);\n            if (feas && (new_cost < cur_cost || rand_double(rng) < exp((cur_cost - new_cost) / T))) {\n                cur_cost = new_cost;\n                improved = true;\n            } else {\n                reverse(cur_perm.begin() + i, cur_perm.begin() + j + 1); // revert\n            }\n        } else { // insert\n            int i = rand_int(0, S - 1);\n            int j = rand_int(0, S - 1);\n            if (i == j) continue;\n            vector<int> new_perm = cur_perm;\n            int val = new_perm[i];\n            new_perm.erase(new_perm.begin() + i);\n            new_perm.insert(new_perm.begin() + j, val);\n            auto [new_cost, feas] = evaluate(new_perm);\n            if (feas && (new_cost < cur_cost || rand_double(rng) < exp((cur_cost - new_cost) / T))) {\n                cur_perm = move(new_perm);\n                cur_cost = new_cost;\n                improved = true;\n            }\n        }\n\n        if (improved && cur_cost < best_cost) {\n            best_cost = cur_cost;\n            best_perm = cur_perm;\n        }\n\n        T *= alpha;\n        if (T < T_min) T = T_min;\n        ++iter;\n        if (iter % 1000 == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > 1.9) break;\n        }\n    }\n\n    // Final hill-climbing (T=0)\n    for (int rep = 0; rep < 5000; ++rep) {\n        int move_type = rand_int(0, 2);\n        if (move_type == 0) {\n            int i = rand_int(0, S - 1), j = rand_int(0, S - 1);\n            if (i == j) continue;\n            swap(cur_perm[i], cur_perm[j]);\n            auto [new_cost, feas] = evaluate(cur_perm);\n            if (feas && new_cost < cur_cost) {\n                cur_cost = new_cost;\n                if (cur_cost < best_cost) {\n                    best_cost = cur_cost;\n                    best_perm = cur_perm;\n                }\n            } else {\n                swap(cur_perm[i], cur_perm[j]);\n            }\n        } else if (move_type == 1) {\n            if (S < 2) continue;\n            int i = rand_int(0, S - 2), j = rand_int(i + 1, S - 1);\n            reverse(cur_perm.begin() + i, cur_perm.begin() + j + 1);\n            auto [new_cost, feas] = evaluate(cur_perm);\n            if (feas && new_cost < cur_cost) {\n                cur_cost = new_cost;\n                if (cur_cost < best_cost) {\n                    best_cost = cur_cost;\n                    best_perm = cur_perm;\n                }\n            } else {\n                reverse(cur_perm.begin() + i, cur_perm.begin() + j + 1);\n            }\n        } else {\n            int i = rand_int(0, S - 1), j = rand_int(0, S - 1);\n            if (i == j) continue;\n            vector<int> new_perm = cur_perm;\n            int val = new_perm[i];\n            new_perm.erase(new_perm.begin() + i);\n            new_perm.insert(new_perm.begin() + j, val);\n            auto [new_cost, feas] = evaluate(new_perm);\n            if (feas && new_cost < cur_cost) {\n                cur_perm = move(new_perm);\n                cur_cost = new_cost;\n                if (cur_cost < best_cost) {\n                    best_cost = cur_cost;\n                    best_perm = cur_perm;\n                }\n            }\n        }\n    }\n\n    // Generate output\n    vector<string> ops;\n    int cur_r = 0, cur_c = 0;\n    for (int idx : best_perm) {\n        int tr = tasks[idx].r, tc = tasks[idx].c;\n        while (cur_r < tr) { ops.push_back(\"D\"); cur_r++; }\n        while (cur_r > tr) { ops.push_back(\"U\"); cur_r--; }\n        while (cur_c < tc) { ops.push_back(\"R\"); cur_c++; }\n        while (cur_c > tc) { ops.push_back(\"L\"); cur_c--; }\n        if (tasks[idx].h > 0) {\n            ops.push_back(\"+\" + to_string(tasks[idx].h));\n        } else {\n            ops.push_back(\"-\" + to_string(-tasks[idx].h));\n        }\n    }\n\n    for (auto& s : ops) cout << s << '\\n';\n\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <chrono>\n#include <cstdint>\n\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, T;\n    cin >> N >> M >> T;\n    const int seed_count = 2 * N * (N - 1); // 60\n\n    vector<vector<int>> seeds(seed_count, vector<int>(M));\n    for (int i = 0; i < seed_count; ++i) {\n        for (int j = 0; j < M; ++j) {\n            cin >> seeds[i][j];\n        }\n    }\n\n    // initial global maximums\n    vector<int> global_max(M, 0);\n    for (int i = 0; i < seed_count; ++i) {\n        for (int j = 0; j < M; ++j) {\n            if (seeds[i][j] > global_max[j]) global_max[j] = seeds[i][j];\n        }\n    }\n\n    // random generator\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    // precompute edge list (as cell indices r*N+c)\n    vector<pair<int,int>> edges;\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            if (r + 1 < N) edges.push_back({r*N+c, (r+1)*N+c});\n            if (c + 1 < N) edges.push_back({r*N+c, r*N+c+1});\n        }\n    }\n\n    // cell degrees\n    vector<int> cell_deg(N*N);\n    for (int r=0; r<N; ++r) {\n        for (int c=0; c<N; ++c) {\n            int d = 0;\n            if (r > 0) d++;\n            if (r < N-1) d++;\n            if (c > 0) d++;\n            if (c < N-1) d++;\n            cell_deg[r*N+c] = d;\n        }\n    }\n\n    // order cells by degree descending\n    vector<int> cell_order(N*N);\n    iota(cell_order.begin(), cell_order.end(), 0);\n    sort(cell_order.begin(), cell_order.end(), [&](int a, int b) {\n        if (cell_deg[a] != cell_deg[b]) return cell_deg[a] > cell_deg[b];\n        return a < b;\n    });\n\n    for (int t = 0; t < T; ++t) {\n        // recompute current maximums\n        vector<int> cur_max(M, 0);\n        for (int i = 0; i < seed_count; ++i)\n            for (int j = 0; j < M; ++j)\n                if (seeds[i][j] > cur_max[j]) cur_max[j] = seeds[i][j];\n\n        // feature masks and scores\n        vector<uint16_t> mask(seed_count, 0);\n        vector<int> max_cnt(seed_count, 0);\n        vector<int> sum_val(seed_count, 0);\n        for (int i = 0; i < seed_count; ++i) {\n            uint16_t m = 0;\n            int cnt = 0;\n            for (int j = 0; j < M; ++j) {\n                if (seeds[i][j] == cur_max[j]) {\n                    m |= (1 << j);\n                    ++cnt;\n                }\n            }\n            mask[i] = m;\n            max_cnt[i] = cnt;\n            sum_val[i] = accumulate(seeds[i].begin(), seeds[i].end(), 0);\n        }\n\n        // select 36 seeds with greedy set cover for maximum features\n        vector<int> selected;\n        selected.reserve(36);\n        uint16_t uncovered = (1 << M) - 1;\n        vector<bool> used(seed_count, false);\n\n        // coverage phase\n        while (uncovered) {\n            int best_idx = -1;\n            int best_cover = -1;\n            int best_score = -1;\n            for (int i = 0; i < seed_count; ++i) {\n                if (used[i]) continue;\n                int cover = __builtin_popcount((unsigned int)(mask[i] & uncovered));\n                if (cover == 0) continue;\n                int score = max_cnt[i] * 1000 + sum_val[i];\n                if (cover > best_cover || (cover == best_cover && score > best_score)) {\n                    best_cover = cover;\n                    best_score = score;\n                    best_idx = i;\n                }\n            }\n            if (best_idx == -1) break; // should not happen\n            used[best_idx] = true;\n            selected.push_back(best_idx);\n            uncovered &= ~mask[best_idx];\n        }\n\n        // fill remaining with best score\n        vector<pair<int,int>> rest; // (score, idx)\n        for (int i = 0; i < seed_count; ++i) {\n            if (!used[i]) {\n                rest.push_back({max_cnt[i] * 1000 + sum_val[i], i});\n            }\n        }\n        sort(rest.begin(), rest.end(), greater<>());\n        for (auto &p : rest) {\n            if ((int)selected.size() >= 36) break;\n            selected.push_back(p.second);\n        }\n\n        // sort selected by score descending (for initial placement)\n        vector<pair<int,int>> ranked_sel;\n        for (int idx : selected) {\n            ranked_sel.push_back({max_cnt[idx] * 1000 + sum_val[idx], idx});\n        }\n        sort(ranked_sel.begin(), ranked_sel.end(), greater<>());\n        selected.clear();\n        for (auto &p : ranked_sel) selected.push_back(p.second);\n\n        // initial assignment: highest score to highest degree cells\n        int grid_seed[6][6];\n        for (int i = 0; i < N*N; ++i) {\n            int r = cell_order[i] / N;\n            int c = cell_order[i] % N;\n            grid_seed[r][c] = selected[i];\n        }\n\n        // score function for a pair of seeds\n        auto score2 = [&](int s1, int s2) -> int {\n            uint16_t m1 = mask[s1];\n            uint16_t m2 = mask[s2];\n            uint16_t both = m1 & m2;\n            uint16_t either = m1 ^ m2;\n            return 2 * __builtin_popcount((unsigned int)both) + __builtin_popcount((unsigned int)either);\n        };\n\n        auto total_score = [&]() -> int {\n            int total = 0;\n            for (auto &e : edges) {\n                int r1 = e.first / N, c1 = e.first % N;\n                int r2 = e.second / N, c2 = e.second % N;\n                total += score2(grid_seed[r1][c1], grid_seed[r2][c2]);\n            }\n            return total;\n        };\n\n        int cur_total = total_score();\n        uniform_int_distribution<int> cell_dist(0, N*N-1);\n\n        // hill climbing (greedy swaps)\n        const int MAX_ITER = 70000;\n        for (int it = 0; it < MAX_ITER; ++it) {\n            int c1 = cell_dist(rng);\n            int c2 = cell_dist(rng);\n            if (c1 == c2) continue;\n            int r1 = c1 / N, c1c = c1 % N;\n            int r2 = c2 / N, c2c = c2 % N;\n            swap(grid_seed[r1][c1c], grid_seed[r2][c2c]);\n            int new_total = total_score();\n            if (new_total > cur_total) {\n                cur_total = new_total;\n            } else {\n                swap(grid_seed[r1][c1c], grid_seed[r2][c2c]); // revert\n            }\n        }\n\n        // output grid\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                if (c) cout << ' ';\n                cout << grid_seed[r][c];\n            }\n            cout << '\\n';\n        }\n        cout.flush();\n\n        // read new seeds\n        for (int i = 0; i < seed_count; ++i) {\n            for (int j = 0; j < M; ++j) {\n                cin >> seeds[i][j];\n            }\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    int N, M, V;\n    cin >> N >> M >> V;\n    vector<string> s_str(N), t_str(N);\n    for (int i = 0; i < N; ++i) cin >> s_str[i];\n    for (int i = 0; i < N; ++i) cin >> t_str[i];\n    \n    vector<vector<bool>> s(N, vector<bool>(N, false));\n    vector<vector<bool>> t(N, vector<bool>(N, false));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (s_str[i][j] == '1') s[i][j] = true;\n            if (t_str[i][j] == '1') t[i][j] = true;\n        }\n    }\n    \n    // Design a star-shaped tree: root 0 with V-1 leaves\n    int Vp = V;\n    int C = Vp - 1;                   // number of leaves\n    vector<int> dirs(C), lens(C);\n    for (int i = 0; i < C; ++i) {\n        dirs[i] = i % 4;               // permanent direction: 0:right, 1:down, 2:left, 3:up\n        lens[i] = i + 1;               // different lengths\n    }\n    \n    // Output tree and initial root position\n    cout << Vp << \"\\n\";\n    for (int i = 0; i < C; ++i) {\n        cout << 0 << \" \" << lens[i] << \"\\n\";\n    }\n    cout << \"0 0\\n\";                   // root starts at (0,0)\n    \n    const int ddx[4] = {0, 1, 0, -1}; // row change per direction\n    const int ddy[4] = {1, 0, -1, 0}; // col change per direction\n    \n    vector<int> dx(C), dy(C);\n    for (int i = 0; i < C; ++i) {\n        dx[i] = ddx[dirs[i]] * lens[i];\n        dy[i] = ddy[dirs[i]] * lens[i];\n    }\n    \n    // Initial two turns to rotate leaves into their permanent directions\n    auto get_rot = [&](int leaf, int turn) -> char {\n        int target = dirs[leaf];\n        if (target == 0) return '.';\n        if (target == 1) return (turn == 0) ? 'R' : '.';\n        if (target == 2) return (turn == 0 || turn == 1) ? 'R' : '.';\n        if (target == 3) return (turn == 0) ? 'L' : '.';\n        return '.';\n    };\n    \n    string turn0(2 * Vp, '.'), turn1(2 * Vp, '.');\n    for (int i = 0; i < C; ++i) {\n        turn0[1 + i] = get_rot(i, 0);\n        turn1[1 + i] = get_rot(i, 1);\n    }\n    int turn_count = 2;\n    cout << turn0 << \"\\n\";\n    cout << turn1 << \"\\n\";\n    \n    vector<bool> occ(C, false);        // true if leaf i is holding a takoyaki\n    int rx = 0, ry = 0;                // current root position\n    \n    const int MAX_TURNS = 100000;\n    \n    // Output a single turn\n    auto do_turn = [&](char move_char, const string& rot_part, const string& act_part) {\n        string S(2 * Vp, '.');\n        S[0] = move_char;\n        for (int i = 0; i < C; ++i) S[1 + i] = rot_part[i];\n        for (int i = 0; i < Vp; ++i) S[Vp + i] = act_part[i];\n        cout << S << \"\\n\";\n        ++turn_count;\n    };\n    \n    // Compute possible actions at a given root position (initial state of the turn)\n    auto compute_actions = [&](int x, int y) -> string {\n        string act(Vp, '.');\n        for (int i = 0; i < C; ++i) {\n            int tx = x + dx[i];\n            int ty = y + dy[i];\n            if (tx < 0 || tx >= N || ty < 0 || ty >= N) continue;\n            if (!occ[i] && s[tx][ty] && !t[tx][ty]) {\n                act[i + 1] = 'P';\n            } else if (occ[i] && t[tx][ty] && !s[tx][ty]) {\n                act[i + 1] = 'P';\n            }\n        }\n        return act;\n    };\n    \n    // Apply actions sequentially (same order as the judge) and skip illegal ones\n    auto apply_actions = [&](int x, int y, const string& act) {\n        for (int i = 0; i < C; ++i) {\n            if (act[i + 1] != 'P') continue;\n            int tx = x + dx[i];\n            int ty = y + dy[i];\n            if (tx < 0 || tx >= N || ty < 0 || ty >= N) continue;\n            if (!occ[i] && s[tx][ty] && !t[tx][ty]) {\n                occ[i] = true;\n                s[tx][ty] = false;\n            } else if (occ[i] && t[tx][ty] && !s[tx][ty]) {\n                occ[i] = false;\n                s[tx][ty] = true;\n            }\n            // else action is invalid and will be ignored by the judge; we do nothing\n        }\n    };\n    \n    // Main loop\n    while (turn_count < MAX_TURNS) {\n        // Find best root position (maximise immediate actions, tie-break by distance)\n        int best_A = -1, best_x = -1, best_y = -1, min_dist = 1e9;\n        for (int nx = 0; nx < N; ++nx) {\n            for (int ny = 0; ny < N; ++ny) {\n                int A = 0;\n                for (int i = 0; i < C; ++i) {\n                    int tx = nx + dx[i];\n                    int ty = ny + dy[i];\n                    if (tx >= 0 && tx < N && ty >= 0 && ty < N) {\n                        if (!occ[i] && s[tx][ty] && !t[tx][ty]) ++A;\n                        else if (occ[i] && t[tx][ty] && !s[tx][ty]) ++A;\n                    }\n                }\n                if (A > best_A) {\n                    best_A = A;\n                    best_x = nx; best_y = ny;\n                    min_dist = abs(nx - rx) + abs(ny - ry);\n                } else if (A == best_A) {\n                    int d = abs(nx - rx) + abs(ny - ry);\n                    if (d < min_dist) {\n                        min_dist = d;\n                        best_x = nx; best_y = ny;\n                    }\n                }\n            }\n        }\n        if (best_A <= 0) break;   // no useful actions exist\n        \n        // Build a Manhattan path from current root to best root\n        vector<pair<int,int>> path;\n        int cur_x = rx, cur_y = ry;\n        while (cur_x != best_x) {\n            cur_x += (best_x > cur_x) ? 1 : -1;\n            path.emplace_back(cur_x, cur_y);\n        }\n        while (cur_y != best_y) {\n            cur_y += (best_y > cur_y) ? 1 : -1;\n            path.emplace_back(cur_x, cur_y);\n        }\n        \n        // If we are already at the best position, just perform the actions\n        if (path.empty()) {\n            string act_part = compute_actions(rx, ry);\n            if (turn_count < MAX_TURNS) {\n                do_turn('.', string(C, '.'), act_part);\n                apply_actions(rx, ry, act_part);\n            }\n            continue;\n        }\n        \n        // Execute the path step by step\n        cur_x = rx; cur_y = ry;\n        for (size_t k = 0; k < path.size(); ++k) {\n            if (turn_count >= MAX_TURNS) break;\n            int nx = path[k].first;\n            int ny = path[k].second;\n            char move_char = '.';\n            if (nx > cur_x) move_char = 'D';\n            else if (nx < cur_x) move_char = 'U';\n            else if (ny > cur_y) move_char = 'R';\n            else if (ny < cur_y) move_char = 'L';\n            \n            string rot_part(C, '.');\n            string act_part;\n            bool is_last = (k == path.size() - 1);\n            if (is_last) {\n                act_part = compute_actions(nx, ny);\n            } else {\n                act_part.assign(Vp, '.');\n            }\n            \n            do_turn(move_char, rot_part, act_part);\n            if (is_last) {\n                apply_actions(nx, ny, act_part);\n            }\n            cur_x = nx;\n            cur_y = ny;\n        }\n        rx = cur_x;\n        ry = cur_y;\n    }\n    \n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <unordered_map>\n#include <utility>\nusing namespace std;\n\nconst int S = 800;                     // cell size\nconst int W = 125;                     // grid width  (100000 / 800)\nconst int H = 125;                     // grid height\nconst int MAX_PERIMETER = 400000;\n\nstruct Edge {\n    int to, rev;\n    long long cap;\n};\n\nstruct Dinic {\n    int N;\n    vector<vector<Edge>> g;\n    vector<int> level, iter;\n\n    Dinic(int n) : N(n), g(n), level(n), iter(n) {}\n\n    void add_edge(int from, int to, long long cap) {\n        g[from].push_back({to, (int)g[to].size(), cap});\n        g[to].push_back({from, (int)g[from].size() - 1, 0});\n    }\n\n    void add_undirected(int u, int v, long long cap) {\n        add_edge(u, v, cap);\n        add_edge(v, u, cap);\n    }\n\n    bool bfs(int s, int t) {\n        fill(level.begin(), level.end(), -1);\n        queue<int> q;\n        level[s] = 0;\n        q.push(s);\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (auto &e : g[v]) {\n                if (e.cap > 0 && level[e.to] == -1) {\n                    level[e.to] = level[v] + 1;\n                    q.push(e.to);\n                }\n            }\n        }\n        return level[t] != -1;\n    }\n\n    long long dfs(int s, int t, long long f) {\n        vector<pair<int, long long>> st;\n        vector<int> prev(N, -1), prev_edge(N, -1);\n        st.push({s, f});\n        prev[s] = s;\n        while (!st.empty()) {\n            auto [v, flow] = st.top();\n            if (v == t) {\n                // augment\n                for (int u = t; u != s; u = prev[u]) {\n                    int ei = prev_edge[u];\n                    Edge &e = g[prev[u]][ei];\n                    e.cap -= flow;\n                    g[u][e.rev].cap += flow;\n                }\n                return flow;\n            }\n            bool found = false;\n            for (int &i = iter[v]; i < (int)g[v].size(); i++) {\n                Edge &e = g[v][i];\n                if (e.cap > 0 && level[v] + 1 == level[e.to]) {\n                    prev[e.to] = v;\n                    prev_edge[e.to] = i;\n                    st.push({e.to, min(flow, e.cap)});\n                    found = true;\n                    break;\n                }\n            }\n            if (!found) {\n                st.pop();\n            }\n        }\n        return 0;\n    }\n\n    long long max_flow(int s, int t) {\n        long long flow = 0;\n        while (bfs(s, t)) {\n            fill(iter.begin(), iter.end(), 0);\n            long long f;\n            while ((f = dfs(s, t, 1e18)) > 0) {\n                flow += f;\n            }\n        }\n        return flow;\n    }\n\n    vector<bool> get_source_set(int s) {\n        vector<bool> vis(N, false);\n        queue<int> q;\n        q.push(s);\n        vis[s] = true;\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (auto &e : g[v]) {\n                if (e.cap > 0 && !vis[e.to]) {\n                    vis[e.to] = true;\n                    q.push(e.to);\n                }\n            }\n        }\n        return vis;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    cin >> N;\n    vector<int> x(2*N), y(2*N);\n    for (int i = 0; i < 2*N; i++) cin >> x[i] >> y[i];\n    \n    // assign each point to a cell and compute cell weight (mackerels - sardines)\n    vector<vector<int>> weight(H, vector<int>(W, 0));\n    for (int i = 0; i < N; i++) {\n        int cx = min(x[i] / S, W - 1);\n        int cy = min(y[i] / S, H - 1);\n        weight[cy][cx]++;\n    }\n    for (int i = N; i < 2*N; i++) {\n        int cx = min(x[i] / S, W - 1);\n        int cy = min(y[i] / S, H - 1);\n        weight[cy][cx]--;\n    }\n    \n    // different trade-off parameters (lambda)\n    vector<int> lambdas = {0, 1, 3, 7, 15, 30, 60, 120, 250, 500};\n    \n    int best_score = -1;\n    vector<vector<bool>> best_inside(H, vector<bool>(W, false));\n    \n    const int dx[4] = {1, -1, 0, 0};\n    const int dy[4] = {0, 0, 1, -1};\n    \n    for (int lambda : lambdas) {\n        Dinic dinic(W * H + 2);\n        int source = W * H, sink = source + 1;\n        \n        // unary terms\n        for (int j = 0; j < H; j++) {\n            for (int i = 0; i < W; i++) {\n                int id = i + j * W;\n                int w = weight[j][i];\n                if (w > 0) dinic.add_edge(source, id, w);\n                else if (w < 0) dinic.add_edge(id, sink, -w);\n            }\n        }\n        \n        // pairwise terms (perimeter penalty)\n        for (int j = 0; j < H; j++) {\n            for (int i = 0; i < W; i++) {\n                int id = i + j * W;\n                if (i + 1 < W) dinic.add_undirected(id, id + 1, lambda);\n                if (j + 1 < H) dinic.add_undirected(id, id + W, lambda);\n            }\n        }\n        \n        dinic.max_flow(source, sink);\n        auto vis = dinic.get_source_set(source);\n        vector<vector<bool>> inside(H, vector<bool>(W, false));\n        for (int j = 0; j < H; j++)\n            for (int i = 0; i < W; i++)\n                inside[j][i] = vis[i + j * W];\n        \n        // find connected components of the inside set\n        vector<vector<int>> comp_id(H, vector<int>(W, -1));\n        int comp_cnt = 0;\n        for (int j = 0; j < H; j++) {\n            for (int i = 0; i < W; i++) {\n                if (inside[j][i] && comp_id[j][i] == -1) {\n                    queue<pair<int,int>> q;\n                    q.push({i, j});\n                    comp_id[j][i] = comp_cnt;\n                    while (!q.empty()) {\n                        auto [cx, cy] = q.front(); q.pop();\n                        for (int d = 0; d < 4; d++) {\n                            int nx = cx + dx[d], ny = cy + dy[d];\n                            if (nx >= 0 && nx < W && ny >= 0 && ny < H && inside[ny][nx] && comp_id[ny][nx] == -1) {\n                                comp_id[ny][nx] = comp_cnt;\n                                q.push({nx, ny});\n                            }\n                        }\n                    }\n                    comp_cnt++;\n                }\n            }\n        }\n        \n        // evaluate each component after filling holes\n        for (int c = 0; c < comp_cnt; c++) {\n            int min_i = W, max_i = -1, min_j = H, max_j = -1;\n            for (int j = 0; j < H; j++) {\n                for (int i = 0; i < W; i++) {\n                    if (comp_id[j][i] == c) {\n                        min_i = min(min_i, i); max_i = max(max_i, i);\n                        min_j = min(min_j, j); max_j = max(max_j, j);\n                    }\n                }\n            }\n            int lw = max_i - min_i + 3;\n            int lh = max_j - min_j + 3;\n            vector<vector<bool>> local(lh, vector<bool>(lw, false));\n            for (int j = min_j; j <= max_j; j++)\n                for (int i = min_i; i <= max_i; i++)\n                    if (comp_id[j][i] == c)\n                        local[j - min_j + 1][i - min_i + 1] = true;\n            \n            // flood fill the outside from the borders of the local grid\n            vector<vector<bool>> vis_local(lh, vector<bool>(lw, false));\n            queue<pair<int,int>> q;\n            for (int y = 0; y < lh; y++) {\n                if (!local[y][0]) { q.push({0, y}); vis_local[y][0] = true; }\n                if (!local[y][lw-1]) { q.push({lw-1, y}); vis_local[y][lw-1] = true; }\n            }\n            for (int x = 0; x < lw; x++) {\n                if (!local[0][x]) { q.push({x, 0}); vis_local[0][x] = true; }\n                if (!local[lh-1][x]) { q.push({x, lh-1}); vis_local[lh-1][x] = true; }\n            }\n            while (!q.empty()) {\n                auto [cx, cy] = q.front(); q.pop();\n                for (int d = 0; d < 4; d++) {\n                    int nx = cx + dx[d], ny = cy + dy[d];\n                    if (nx >= 0 && nx < lw && ny >= 0 && ny < lh && !vis_local[ny][nx] && !local[ny][nx]) {\n                        vis_local[ny][nx] = true;\n                        q.push({nx, ny});\n                    }\n                }\n            }\n            // fill holes (any outside cell not reached by the flood fill)\n            for (int y = 0; y < lh; y++)\n                for (int x = 0; x < lw; x++)\n                    if (!vis_local[y][x] && !local[y][x])\n                        local[y][x] = true;\n            \n            // test if a global cell belongs to the filled component\n            auto is_inside_local = [&](int i, int j) -> bool {\n                if (i < min_i || i > max_i || j < min_j || j > max_j) return false;\n                return local[j - min_j + 1][i - min_i + 1];\n            };\n            \n            long long cur_w = 0;\n            int cur_perim = 0;\n            for (int j = min_j; j <= max_j; j++) {\n                for (int i = min_i; i <= max_i; i++) {\n                    if (is_inside_local(i, j)) {\n                        cur_w += weight[j][i];\n                        if (!is_inside_local(i+1, j)) cur_perim++;\n                        if (!is_inside_local(i-1, j)) cur_perim++;\n                        if (!is_inside_local(i, j+1)) cur_perim++;\n                        if (!is_inside_local(i, j-1)) cur_perim++;\n                    }\n                }\n            }\n            \n            // check perimeter constraint\n            if ((long long)cur_perim * S <= MAX_PERIMETER) {\n                int score = max(0LL, cur_w + 1);\n                if (score > best_score) {\n                    best_score = score;\n                    best_inside.assign(H, vector<bool>(W, false));\n                    for (int j = min_j; j <= max_j; j++)\n                        for (int i = min_i; i <= max_i; i++)\n                            if (is_inside_local(i, j))\n                                best_inside[j][i] = true;\n                }\n            }\n        }\n    }\n    \n    // if no valid component found, fall back to a tiny polygon around a single mackerel\n    if (best_score <= 0) {\n        int best_px = x[0], best_py = y[0];\n        // try to find a mackerel whose 1x1 cell contains no sardine\n        for (int i = 0; i < N; i++) {\n            int px = x[i], py = y[i];\n            bool ok = true;\n            for (int j = N; j < 2*N; j++) {\n                if (x[j] >= px && x[j] <= px+1 && y[j] >= py && y[j] <= py+1) {\n                    ok = false;\n                    break;\n                }\n            }\n            if (ok) {\n                best_px = px; best_py = py;\n                break;\n            }\n        }\n        if (best_px == 100000) best_px = 99999;\n        if (best_py == 100000) best_py = 99999;\n        cout << \"4\\n\";\n        cout << best_px << \" \" << best_py << \"\\n\";\n        cout << best_px+1 << \" \" << best_py << \"\\n\";\n        cout << best_px+1 << \" \" << best_py+1 << \"\\n\";\n        cout << best_px << \" \" << best_py+1 << \"\\n\";\n        return 0;\n    }\n    \n    // trace the outer boundary of best_inside\n    struct Seg {\n        int x1, y1, x2, y2;\n    };\n    vector<Seg> segs;\n    for (int j = 0; j < H; j++) {\n        for (int i = 0; i < W; i++) {\n            if (!best_inside[j][i]) continue;\n            int x = i * S, y = j * S;\n            // top edge\n            if (j == 0 || !best_inside[j-1][i])\n                segs.push_back({x, y, x + S, y});\n            // bottom edge\n            if (j == H-1 || !best_inside[j+1][i])\n                segs.push_back({x, y + S, x + S, y + S});\n            // left edge\n            if (i == 0 || !best_inside[j][i-1])\n                segs.push_back({x, y, x, y + S});\n            // right edge\n            if (i == W-1 || !best_inside[j][i+1])\n                segs.push_back({x + S, y, x + S, y + S});\n        }\n    }\n    \n    // link segments via their endpoints\n    unordered_map<long long, vector<int>> vmap;\n    for (int idx = 0; idx < (int)segs.size(); idx++) {\n        long long k1 = (long long)segs[idx].x1 << 32 | segs[idx].y1;\n        long long k2 = (long long)segs[idx].x2 << 32 | segs[idx].y2;\n        vmap[k1].push_back(idx);\n        vmap[k2].push_back(idx);\n    }\n    \n    // trace the boundary loop\n    vector<pair<int,int>> poly;\n    int start_x = segs[0].x1, start_y = segs[0].y1;\n    poly.push_back({start_x, start_y});\n    int cur_x = segs[0].x2, cur_y = segs[0].y2;\n    poly.push_back({cur_x, cur_y});\n    int prev_seg = 0;\n    while (true) {\n        long long key = (long long)cur_x << 32 | cur_y;\n        int next_seg = -1;\n        for (int sid : vmap[key]) {\n            if (sid != prev_seg) {\n                next_seg = sid;\n                break;\n            }\n        }\n        if (next_seg == -1) break;  // should not happen\n        int nx, ny;\n        if (segs[next_seg].x1 == cur_x && segs[next_seg].y1 == cur_y) {\n            nx = segs[next_seg].x2;\n            ny = segs[next_seg].y2;\n        } else {\n            nx = segs[next_seg].x1;\n            ny = segs[next_seg].y1;\n        }\n        if (nx == start_x && ny == start_y) break;\n        poly.push_back({nx, ny});\n        cur_x = nx; cur_y = ny;\n        prev_seg = next_seg;\n    }\n    \n    // remove collinear vertices\n    vector<pair<int,int>> simple = poly;\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        for (size_t i = 0; i < simple.size(); i++) {\n            size_t prv = (i == 0) ? simple.size() - 1 : i - 1;\n            size_t nxt = (i + 1) % simple.size();\n            if (simple[prv].first == simple[i].first && simple[i].first == simple[nxt].first) {\n                simple.erase(simple.begin() + i);\n                changed = true;\n                break;\n            }\n            if (simple[prv].second == simple[i].second && simple[i].second == simple[nxt].second) {\n                simple.erase(simple.begin() + i);\n                changed = true;\n                break;\n            }\n        }\n    }\n    \n    // output\n    cout << simple.size() << \"\\n\";\n    for (auto [xx, yy] : simple)\n        cout << xx << \" \" << yy << \"\\n\";\n    \n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <string>\n#include <utility>\nusing namespace std;\n\nstruct PlacedRect {\n    int index;          // original index (0..N-1)\n    long long x, y;     // position\n    long long w, h;     // size after rotation\n    int rot;            // 0 or 1\n    char dir;           // 'U' or 'L'\n    int base;           // -1 or original index of reference\n};\n\nstruct State {\n    vector<PlacedRect> rects;\n    long long W, H;\n    long long sum_skipped;   // sum of (w+h) for skipped indices\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int N, T, sigma;\n    cin >> N >> T >> sigma;\n    vector<int> w_obs(N), h_obs(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> w_obs[i] >> h_obs[i];\n    }\n\n    // current estimates for true sizes (double for averaging)\n    vector<double> sum_w(N), sum_h(N);\n    vector<int> cnt(N);\n    for (int i = 0; i < N; ++i) {\n        sum_w[i] = w_obs[i];\n        sum_h[i] = h_obs[i];\n        cnt[i] = 1;\n    }\n\n    int turns_done = 0;\n\n    auto update_est = [&](int i, long long w_meas, long long h_meas) {\n        sum_w[i] += w_meas;\n        sum_h[i] += h_meas;\n        cnt[i]++;\n    };\n\n    // If enough turns, spend 2N turns to measure each rectangle twice.\n    if (T >= 2 * N + 10) {\n        for (int i = 0; i < N; ++i) {\n            // r = 0\n            cout << 1 << \"\\n\";\n            cout << i << \" 0 U -1\\n\" << flush;\n            long long Wp, Hp;\n            cin >> Wp >> Hp;\n            update_est(i, Wp, Hp);\n            ++turns_done;\n\n            // r = 1\n            cout << 1 << \"\\n\";\n            cout << i << \" 1 U -1\\n\" << flush;\n            cin >> Wp >> Hp;\n            update_est(i, Hp, Wp);  // swapped\n            ++turns_done;\n        }\n    }\n\n    // final integer estimates\n    vector<long long> ew(N), eh(N);\n    for (int i = 0; i < N; ++i) {\n        ew[i] = (long long)round(sum_w[i] / cnt[i]);\n        eh[i] = (long long)round(sum_h[i] / cnt[i]);\n    }\n\n    // suffix sums for the beam search heuristic\n    vector<long long> suffix_sum(N + 1, 0);\n    for (int i = N - 1; i >= 0; --i) suffix_sum[i] = suffix_sum[i + 1] + ew[i] + eh[i];\n\n    // Beam search for a good placement sequence\n    const int BEAM = 30;\n    vector<State> beam;\n    beam.push_back(State{ {}, 0LL, 0LL, 0LL });\n\n    for (int i = 0; i < N; ++i) {\n        vector<State> next_beams;\n        next_beams.reserve(BEAM * (5 + 4 * N)); // rough upper bound\n\n        for (const auto& s : beam) {\n            // option: skip rectangle i\n            {\n                State skip_s = s;\n                skip_s.sum_skipped += ew[i] + eh[i];\n                next_beams.push_back(move(skip_s));\n            }\n\n            long long w = ew[i];\n            long long h = eh[i];\n\n            for (int rot = 0; rot <= 1; ++rot) {\n                long long cur_w = rot ? h : w;\n                long long cur_h = rot ? w : h;\n\n                // U with base = -1\n                {\n                    long long x = 0, y = 0;\n                    for (const auto& pr : s.rects) {\n                        if (x + cur_w > pr.x && pr.x + pr.w > x)\n                            y = max(y, pr.y + pr.h);\n                    }\n                    State ns = s;\n                    ns.rects.push_back({i, x, y, cur_w, cur_h, rot, 'U', -1});\n                    ns.W = max(ns.W, x + cur_w);\n                    ns.H = max(ns.H, y + cur_h);\n                    next_beams.push_back(move(ns));\n                }\n\n                // L with base = -1\n                {\n                    long long y = 0, x = 0;\n                    for (const auto& pr : s.rects) {\n                        if (y + cur_h > pr.y && pr.y + pr.h > y)\n                            x = max(x, pr.x + pr.w);\n                    }\n                    State ns = s;\n                    ns.rects.push_back({i, x, y, cur_w, cur_h, rot, 'L', -1});\n                    ns.W = max(ns.W, x + cur_w);\n                    ns.H = max(ns.H, y + cur_h);\n                    next_beams.push_back(move(ns));\n                }\n\n                // attach to each already placed rectangle\n                for (const auto& pr : s.rects) {\n                    int base = pr.index;\n\n                    // U\n                    {\n                        long long x = pr.x + pr.w;\n                        long long y = 0;\n                        for (const auto& pr2 : s.rects) {\n                            if (x + cur_w > pr2.x && pr2.x + pr2.w > x)\n                                y = max(y, pr2.y + pr2.h);\n                        }\n                        State ns = s;\n                        ns.rects.push_back({i, x, y, cur_w, cur_h, rot, 'U', base});\n                        ns.W = max(ns.W, x + cur_w);\n                        ns.H = max(ns.H, y + cur_h);\n                        next_beams.push_back(move(ns));\n                    }\n\n                    // L\n                    {\n                        long long y = pr.y + pr.h;\n                        long long x = 0;\n                        for (const auto& pr2 : s.rects) {\n                            if (y + cur_h > pr2.y && pr2.y + pr2.h > y)\n                                x = max(x, pr2.x + pr2.w);\n                        }\n                        State ns = s;\n                        ns.rects.push_back({i, x, y, cur_w, cur_h, rot, 'L', base});\n                        ns.W = max(ns.W, x + cur_w);\n                        ns.H = max(ns.H, y + cur_h);\n                        next_beams.push_back(move(ns));\n                    }\n                }\n            }\n        }\n\n        // keep top BEAM states according to the heuristic\n        vector<pair<long long, int>> costs;\n        costs.reserve(next_beams.size());\n        for (int idx = 0; idx < (int)next_beams.size(); ++idx) {\n            const auto& ns = next_beams[idx];\n            long long cost = ns.W + ns.H + ns.sum_skipped + suffix_sum[i + 1];\n            costs.emplace_back(cost, idx);\n        }\n        sort(costs.begin(), costs.end());\n        beam.clear();\n        for (int j = 0; j < min(BEAM, (int)costs.size()); ++j)\n            beam.push_back(move(next_beams[costs[j].second]));\n    }\n\n    // select the absolute best state (final score = W+H+sum_skipped)\n    const State* best = &beam[0];\n    long long best_cost = best->W + best->H + best->sum_skipped;\n    for (const auto& s : beam) {\n        long long c = s.W + s.H + s.sum_skipped;\n        if (c < best_cost) {\n            best_cost = c;\n            best = &s;\n        }\n    }\n\n    int n = best->rects.size();\n    int rem = T - turns_done;\n    for (int t = 0; t < rem; ++t) {\n        cout << n << \"\\n\";\n        for (const auto& pr : best->rects)\n            cout << pr.index << \" \" << pr.rot << \" \" << pr.dir << \" \" << pr.base << \"\\n\";\n        cout << flush;\n        long long Wp, Hp;\n        cin >> Wp >> Hp;   // read and ignore the measurements\n    }\n\n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <stack>\n#include <ctime>\n#include <cmath>\n#include <cstdint>\n#include <random>\n\nusing namespace std;\n\n// fast random number generator\nuint32_t xor_state;\nvoid init_random() {\n    random_device rd;\n    xor_state = rd();\n    if(xor_state == 0) xor_state = 123456789;\n}\nuint32_t xorshift32() {\n    uint32_t x = xor_state;\n    x ^= x << 13;\n    x ^= x >> 17;\n    x ^= x << 5;\n    return xor_state = x;\n}\ninline double random_double() {\n    return (xorshift32() >> 8) / double(1 << 24);\n}\ninline int random_int(int n) {\n    return xorshift32() % n;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    init_random();\n\n    int N, M, H;\n    cin >> N >> M >> H;\n    vector<int> A(N);\n    for(int i=0; i<N; i++) cin >> A[i];\n    vector<vector<int>> adj(N);\n    for(int i=0; i<M; i++){\n        int u, v; cin >> u >> v;\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n    // skip coordinates\n    for(int i=0; i<N; i++){\n        int x, y; cin >> x >> y;\n    }\n\n    // state\n    vector<int> parent(N, -1);\n    vector<int> depth(N, 0);\n    vector<vector<int>> children(N);\n    vector<int> subtree_sum_A = A;\n    vector<int> subtree_max_depth(N, 0);\n    vector<int> root_of(N);\n    iota(root_of.begin(), root_of.end(), 0);\n\n    // greedy initialization (process vertices in descending A)\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int i, int j){ return A[i] > A[j]; });\n\n    for(int v : order){\n        if(parent[v] != -1) continue;\n        int best_u = -1;\n        int best_udepth = -1;\n        for(int u : adj[v]){\n            if(root_of[u] == v) continue;\n            int new_d = depth[u] + 1;\n            if(new_d + subtree_max_depth[v] <= H){\n                if(depth[u] > best_udepth){\n                    best_udepth = depth[u];\n                    best_u = u;\n                }\n            }\n        }\n        if(best_u != -1){\n            int delta = depth[best_u] + 1;\n            int new_root = root_of[best_u];\n            parent[v] = best_u;\n            children[best_u].push_back(v);\n            stack<int> st;\n            st.push(v);\n            while(!st.empty()){\n                int node = st.top(); st.pop();\n                depth[node] += delta;\n                root_of[node] = new_root;\n                for(int child : children[node]){\n                    st.push(child);\n                }\n            }\n            // update ancestors\n            vector<int> to_update;\n            int cur = best_u;\n            while(cur != -1){\n                to_update.push_back(cur);\n                cur = parent[cur];\n            }\n            sort(to_update.begin(), to_update.end(), [&](int a, int b){ return depth[a] > depth[b]; });\n            for(int node : to_update){\n                int sum = A[node];\n                int max_d = 0;\n                for(int child : children[node]){\n                    sum += subtree_sum_A[child];\n                    max_d = max(max_d, subtree_max_depth[child] + 1);\n                }\n                subtree_sum_A[node] = sum;\n                subtree_max_depth[node] = max_d;\n            }\n        }\n    }\n\n    // initial score\n    long long score = 0;\n    for(int i=0; i<N; i++){\n        score += (depth[i] + 1LL) * A[i];\n    }\n    long long best_score = score;\n    vector<int> best_parent = parent;\n\n    // helper functions for SA\n    auto is_descendant = [&](int anc, int desc) -> bool {\n        if(depth[desc] < depth[anc]) return false;\n        int cur = desc;\n        while(cur != -1 && depth[cur] > depth[anc]){\n            cur = parent[cur];\n        }\n        return cur == anc;\n    };\n\n    auto apply_move = [&](int v, int new_p, int delta) {\n        int old_p = parent[v];\n        int old_d = depth[v];\n        int new_d = (new_p == -1) ? 0 : depth[new_p] + 1;\n        int depth_delta = new_d - old_d;\n        // remove from old parent\n        if(old_p != -1){\n            auto it = find(children[old_p].begin(), children[old_p].end(), v);\n            if(it != children[old_p].end()) children[old_p].erase(it);\n        }\n        // add to new parent\n        if(new_p != -1){\n            children[new_p].push_back(v);\n        }\n        parent[v] = new_p;\n        // update depths in subtree of v\n        if(depth_delta != 0){\n            stack<int> st;\n            st.push(v);\n            while(!st.empty()){\n                int node = st.top(); st.pop();\n                depth[node] += depth_delta;\n                for(int child : children[node]){\n                    st.push(child);\n                }\n            }\n        }\n        // update subtree properties for affected ancestors\n        vector<int> to_update;\n        if(old_p != -1){\n            int cur = old_p;\n            while(cur != -1){\n                to_update.push_back(cur);\n                cur = parent[cur];\n            }\n        }\n        if(new_p != -1){\n            int cur = new_p;\n            while(cur != -1){\n                to_update.push_back(cur);\n                cur = parent[cur];\n            }\n        }\n        sort(to_update.begin(), to_update.end(), [&](int a, int b){ return depth[a] > depth[b]; });\n        to_update.erase(unique(to_update.begin(), to_update.end()), to_update.end());\n        for(int node : to_update){\n            int sum = A[node];\n            int max_d = 0;\n            for(int child : children[node]){\n                sum += subtree_sum_A[child];\n                max_d = max(max_d, subtree_max_depth[child] + 1);\n            }\n            subtree_sum_A[node] = sum;\n            subtree_max_depth[node] = max_d;\n        }\n    };\n\n    // simulated annealing\n    clock_t start_clock = clock();\n    double time_limit_sec = 1.95;\n    double T_start = 20000.0;\n    double T_end = 0.1;\n    double T = T_start;\n    int iter_count = 0;\n\n    while(true){\n        if(iter_count % 1000 == 0){\n            double elapsed = double(clock() - start_clock) / CLOCKS_PER_SEC;\n            if(elapsed >= time_limit_sec) break;\n            T = T_start * pow(T_end / T_start, elapsed / time_limit_sec);\n        }\n        iter_count++;\n        bool moved = false;\n        for(int attempt = 0; attempt < 5; attempt++){\n            int v = random_int(N);\n            int old_p = parent[v];\n            int u;\n            if(old_p != -1 && random_double() < 0.1){\n                u = -1;  // make root\n            } else {\n                if(adj[v].empty()) continue;\n                u = adj[v][random_int(adj[v].size())];\n            }\n            if(u == old_p) continue;\n            int new_d;\n            if(u == -1){\n                new_d = 0;\n            } else {\n                if(is_descendant(v, u) || is_descendant(u, v)) continue;\n                new_d = depth[u] + 1;\n                if(new_d + subtree_max_depth[v] > H) continue;\n            }\n            int delta = (new_d - depth[v]) * subtree_sum_A[v];\n            if(delta >= 0 || random_double() < exp(delta / T)){\n                apply_move(v, u, delta);\n                score += delta;\n                moved = true;\n                if(score > best_score){\n                    best_score = score;\n                    best_parent = parent;\n                }\n                break;\n            }\n        }\n    }\n\n    for(int i=0; i<N; i++){\n        cout << best_parent[i] << (i==N-1 ? \"\\n\" : \" \");\n    }\n\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <utility>\nusing namespace std;\n\nconst int N = 20;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n;\n    cin >> n; // N=20\n    vector<string> C(n);\n    for (int i = 0; i < n; ++i) cin >> C[i];\n    \n    // Locate Oni and Fuku\n    vector<pair<int,int>> oni;\n    bool fuku[N][N] = {false};\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (C[i][j] == 'x') oni.push_back({i,j});\n            else if (C[i][j] == 'o') fuku[i][j] = true;\n        }\n    }\n    int K = oni.size(); // 40\n    \n    // Compute safe intervals for each row/column\n    int L_max[N], R_min[N], U_max[N], D_min[N];\n    for (int i = 0; i < N; ++i) {\n        L_max[i] = N-1;\n        for (int j = 0; j < N; ++j) if (fuku[i][j]) { L_max[i] = j-1; break; }\n        R_min[i] = 0;\n        for (int j = N-1; j >= 0; --j) if (fuku[i][j]) { R_min[i] = j+1; break; }\n    }\n    for (int j = 0; j < N; ++j) {\n        U_max[j] = N-1;\n        for (int i = 0; i < N; ++i) if (fuku[i][j]) { U_max[j] = i-1; break; }\n        D_min[j] = 0;\n        for (int i = N-1; i >= 0; --i) if (fuku[i][j]) { D_min[j] = i+1; break; }\n    }\n    \n    // Allowed lines for each Oni\n    bool allowed_row[K], allowed_col[K];\n    vector<int> both_allowed;\n    for (int k = 0; k < K; ++k) {\n        int i = oni[k].first, j = oni[k].second;\n        allowed_row[k] = (j <= L_max[i]) || (j >= R_min[i]);\n        allowed_col[k] = (i <= U_max[j]) || (i >= D_min[j]);\n        if (allowed_row[k] && allowed_col[k]) both_allowed.push_back(k);\n    }\n    \n    // Initial greedy assignment\n    vector<int> row_cols[N], col_rows[N];\n    bool assign_row[K];\n    for (int k = 0; k < K; ++k) {\n        int i = oni[k].first, j = oni[k].second;\n        if (allowed_row[k] && allowed_col[k]) {\n            int c_row = 1e9, c_col = 1e9;\n            if (j <= L_max[i]) c_row = min(c_row, 2*(j+1));\n            if (j >= R_min[i]) c_row = min(c_row, 2*(N-j));\n            if (i <= U_max[j]) c_col = min(c_col, 2*(i+1));\n            if (i >= D_min[j]) c_col = min(c_col, 2*(N-i));\n            assign_row[k] = (c_row <= c_col);\n        } else if (allowed_row[k]) {\n            assign_row[k] = true;\n        } else {\n            assign_row[k] = false;\n        }\n    }\n    for (int k = 0; k < K; ++k) {\n        int i = oni[k].first, j = oni[k].second;\n        if (assign_row[k]) row_cols[i].push_back(j);\n        else col_rows[j].push_back(i);\n    }\n    for (int i = 0; i < N; ++i) sort(row_cols[i].begin(), row_cols[i].end());\n    for (int j = 0; j < N; ++j) sort(col_rows[j].begin(), col_rows[j].end());\n    \n    // Cost functions for a single row / column\n    auto cost_row = [&](int i) {\n        const auto& cols = row_cols[i];\n        if (cols.empty()) return 0;\n        int L_safe = L_max[i] + 1;\n        int R_safe = N - R_min[i];\n        int m = cols.size();\n        int suf[N+1] = {0};\n        for (int idx = m-1; idx >= 0; --idx)\n            suf[idx] = max(suf[idx+1], N - cols[idx]);\n        int best = 1e9;\n        for (int L_len = 0; L_len <= L_safe; ++L_len) {\n            int idx = lower_bound(cols.begin(), cols.end(), L_len) - cols.begin();\n            int R_len = suf[idx];\n            if (R_len <= R_safe) {\n                int cost = 2 * (L_len + R_len);\n                if (cost < best) best = cost;\n            }\n        }\n        return best;\n    };\n    \n    auto cost_col = [&](int j) {\n        const auto& rows = col_rows[j];\n        if (rows.empty()) return 0;\n        int U_safe = U_max[j] + 1;\n        int D_safe = N - D_min[j];\n        int m = rows.size();\n        int suf[N+1] = {0};\n        for (int idx = m-1; idx >= 0; --idx)\n            suf[idx] = max(suf[idx+1], N - rows[idx]);\n        int best = 1e9;\n        for (int U_len = 0; U_len <= U_safe; ++U_len) {\n            int idx = lower_bound(rows.begin(), rows.end(), U_len) - rows.begin();\n            int D_len = suf[idx];\n            if (D_len <= D_safe) {\n                int cost = 2 * (U_len + D_len);\n                if (cost < best) best = cost;\n            }\n        }\n        return best;\n    };\n    \n    int total_cost = 0;\n    for (int i = 0; i < N; ++i) total_cost += cost_row(i);\n    for (int j = 0; j < N; ++j) total_cost += cost_col(j);\n    \n    int best_cost = total_cost;\n    bool best_assign[K];\n    for (int k = 0; k < K; ++k) best_assign[k] = assign_row[k];\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> dist01(0.0, 1.0);\n    double temp = 10.0;\n    double cool = 0.999;\n    const int MAX_ITER = 10000;\n    \n    auto apply_flip = [&](int k) {\n        int i = oni[k].first, j = oni[k].second;\n        int old_row = cost_row(i);\n        int old_col = cost_col(j);\n        if (assign_row[k]) {\n            auto& rv = row_cols[i];\n            rv.erase(lower_bound(rv.begin(), rv.end(), j));\n            auto& cv = col_rows[j];\n            cv.insert(lower_bound(cv.begin(), cv.end(), i), i);\n            assign_row[k] = false;\n        } else {\n            auto& cv = col_rows[j];\n            cv.erase(lower_bound(cv.begin(), cv.end(), i));\n            auto& rv = row_cols[i];\n            rv.insert(lower_bound(rv.begin(), rv.end(), j), j);\n            assign_row[k] = true;\n        }\n        int new_row = cost_row(i);\n        int new_col = cost_col(j);\n        int delta = (new_row - old_row) + (new_col - old_col);\n        total_cost += delta;\n        return delta;\n    };\n    \n    // Simulated Annealing on the partition\n    if (!both_allowed.empty()) {\n        for (int iter = 0; iter < MAX_ITER; ++iter) {\n            int k = both_allowed[rng() % both_allowed.size()];\n            double delta = apply_flip(k);\n            if (delta <= 0 || dist01(rng) < exp(-delta / temp)) {\n                if (total_cost < best_cost) {\n                    best_cost = total_cost;\n                    for (int kk = 0; kk < K; ++kk) best_assign[kk] = assign_row[kk];\n                }\n            } else {\n                apply_flip(k); // revert\n            }\n            temp *= cool;\n        }\n    }\n    \n    // Restore best assignment\n    for (int i = 0; i < N; ++i) row_cols[i].clear();\n    for (int j = 0; j < N; ++j) col_rows[j].clear();\n    for (int k = 0; k < K; ++k) {\n        int i = oni[k].first, j = oni[k].second;\n        if (best_assign[k]) row_cols[i].push_back(j);\n        else col_rows[j].push_back(i);\n    }\n    for (int i = 0; i < N; ++i) sort(row_cols[i].begin(), row_cols[i].end());\n    for (int j = 0; j < N; ++j) sort(col_rows[j].begin(), col_rows[j].end());\n    total_cost = best_cost;\n    for (int k = 0; k < K; ++k) assign_row[k] = best_assign[k];\n    \n    // Hill-climb from best state to ensure local minimum\n    if (!both_allowed.empty()) {\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            vector<int> shuf = both_allowed;\n            shuffle(shuf.begin(), shuf.end(), rng);\n            for (int k : shuf) {\n                int old = total_cost;\n                apply_flip(k);\n                if (total_cost < old) {\n                    improved = true;\n                    if (total_cost < best_cost) {\n                        best_cost = total_cost;\n                        for (int kk = 0; kk < K; ++kk) best_assign[kk] = assign_row[kk];\n                    }\n                } else {\n                    apply_flip(k); // revert\n                }\n            }\n        }\n    }\n    \n    // Rebuild final state from best assignment\n    for (int i = 0; i < N; ++i) row_cols[i].clear();\n    for (int j = 0; j < N; ++j) col_rows[j].clear();\n    for (int k = 0; k < K; ++k) {\n        int i = oni[k].first, j = oni[k].second;\n        if (best_assign[k]) row_cols[i].push_back(j);\n        else col_rows[j].push_back(i);\n    }\n    for (int i = 0; i < N; ++i) sort(row_cols[i].begin(), row_cols[i].end());\n    for (int j = 0; j < N; ++j) sort(col_rows[j].begin(), col_rows[j].end());\n    \n    // Extract optimal push lengths\n    auto get_row_ops = [&](int i) -> pair<int,int> {\n        const auto& cols = row_cols[i];\n        if (cols.empty()) return {0,0};\n        int L_safe = L_max[i] + 1;\n        int R_safe = N - R_min[i];\n        int m = cols.size();\n        int suf[N+1] = {0};\n        for (int idx = m-1; idx >= 0; --idx) suf[idx] = max(suf[idx+1], N - cols[idx]);\n        int best_c = 1e9;\n        int best_L = 0, best_R = 0;\n        for (int L_len = 0; L_len <= L_safe; ++L_len) {\n            int idx = lower_bound(cols.begin(), cols.end(), L_len) - cols.begin();\n            int R_len = suf[idx];\n            if (R_len <= R_safe) {\n                int cst = 2*(L_len + R_len);\n                if (cst < best_c) { best_c = cst; best_L = L_len; best_R = R_len; }\n            }\n        }\n        return {best_L, best_R};\n    };\n    auto get_col_ops = [&](int j) -> pair<int,int> {\n        const auto& rows = col_rows[j];\n        if (rows.empty()) return {0,0};\n        int U_safe = U_max[j] + 1;\n        int D_safe = N - D_min[j];\n        int m = rows.size();\n        int suf[N+1] = {0};\n        for (int idx = m-1; idx >= 0; --idx) suf[idx] = max(suf[idx+1], N - rows[idx]);\n        int best_c = 1e9;\n        int best_U = 0, best_D = 0;\n        for (int U_len = 0; U_len <= U_safe; ++U_len) {\n            int idx = lower_bound(rows.begin(), rows.end(), U_len) - rows.begin();\n            int D_len = suf[idx];\n            if (D_len <= D_safe) {\n                int cst = 2*(U_len + D_len);\n                if (cst < best_c) { best_c = cst; best_U = U_len; best_D = D_len; }\n            }\n        }\n        return {best_U, best_D};\n    };\n    \n    vector<pair<char,int>> ops;\n    for (int i = 0; i < N; ++i) {\n        auto [L_len, R_len] = get_row_ops(i);\n        for (int t = 0; t < L_len; ++t) ops.push_back({'L', i});\n        for (int t = 0; t < L_len; ++t) ops.push_back({'R', i});\n        for (int t = 0; t < R_len; ++t) ops.push_back({'R', i});\n        for (int t = 0; t < R_len; ++t) ops.push_back({'L', i});\n    }\n    for (int j = 0; j < N; ++j) {\n        auto [U_len, D_len] = get_col_ops(j);\n        for (int t = 0; t < U_len; ++t) ops.push_back({'U', j});\n        for (int t = 0; t < U_len; ++t) ops.push_back({'D', j});\n        for (int t = 0; t < D_len; ++t) ops.push_back({'D', j});\n        for (int t = 0; t < D_len; ++t) ops.push_back({'U', j});\n    }\n    \n    // Output the sequence\n    for (const auto& [d, p] : ops) {\n        cout << d << \" \" << p << \"\\n\";\n    }\n    \n    return 0;\n}","ahc044":"#include <iostream>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n#include <cstring>\n#include <random>\nusing namespace std;\n\nconst int N = 100;\nconst int L = 500000;\nint T[N];\ndouble T_norm[N];\n\n// exact simulation (ground truth)\nint real_error(const int a[N], const int b[N]) {\n    int t[N] = {0};\n    int cur = 0;\n    t[0] = 1;\n    for (int step = 1; step < L; ++step) {\n        cur = (t[cur] & 1) ? a[cur] : b[cur];\n        t[cur]++;\n    }\n    int err = 0;\n    for (int i = 0; i < N; ++i) {\n        int diff = t[i] - T[i];\n        if (diff < 0) diff = -diff;\n        err += diff;\n    }\n    return err;\n}\n\n// fast surrogate: stationary distribution of the associated random walk\ndouble surrogate_error(const int a[N], const int b[N]) {\n    double pi[N], new_pi[N];\n    for (int i = 0; i < N; ++i) pi[i] = 1.0 / N;\n    const int max_iter = 100;\n    for (int iter = 0; iter < max_iter; ++iter) {\n        for (int i = 0; i < N; ++i) new_pi[i] = 0.0;\n        for (int i = 0; i < N; ++i) {\n            if (a[i] == b[i]) {\n                new_pi[a[i]] += pi[i];\n            } else {\n                new_pi[a[i]] += pi[i] * 0.5;\n                new_pi[b[i]] += pi[i] * 0.5;\n            }\n        }\n        for (int i = 0; i < N; ++i) pi[i] = new_pi[i];\n    }\n    double err = 0.0;\n    for (int i = 0; i < N; ++i) err += fabs(pi[i] * L - T[i]);\n    return err;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    int N_in, L_in;\n    cin >> N_in >> L_in;\n    for (int i = 0; i < N; ++i) {\n        cin >> T[i];\n        T_norm[i] = (double)T[i] / L;\n    }\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto rand_int = [&](int max) { return uniform_int_distribution<int>(0, max-1)(rng); };\n    auto rand_double = [&]() { return uniform_real_distribution<double>(0.0, 1.0)(rng); };\n    \n    int best_a[N], best_b[N];\n    int best_err;\n    \n    // start with a simple cycle\n    for (int i = 0; i < N; ++i) {\n        best_a[i] = (i + 1) % N;\n        best_b[i] = (i + 1) % N;\n    }\n    best_err = real_error(best_a, best_b);\n    \n    int cur_a[N], cur_b[N];\n    memcpy(cur_a, best_a, sizeof(cur_a));\n    memcpy(cur_b, best_b, sizeof(cur_b));\n    int cur_real_err = best_err;\n    double cur_surr_err = surrogate_error(cur_a, cur_b);\n    double best_surr_err = cur_surr_err;\n    \n    auto start = chrono::steady_clock::now();\n    double elapsed = 0.0;\n    const double time_limit_surr = 1.2;\n    const double time_limit_total = 1.95;\n    \n    // ---------- Stage 1: Surrogate SA ----------\n    double temp_surr = max(cur_surr_err * 0.2, 1.0);\n    double temp_surr_end = 0.1;\n    int iter = 0;\n    while (true) {\n        if (iter % 100 == 0) {\n            auto now = chrono::steady_clock::now();\n            elapsed = chrono::duration<double>(now - start).count();\n            if (elapsed > time_limit_surr) break;\n            double progress = elapsed / time_limit_surr;\n            temp_surr = max(cur_surr_err * 0.2, 1.0) * pow(temp_surr_end / max(cur_surr_err * 0.2, 1.0), progress);\n        }\n        int type = rand_int(10);\n        int i = rand_int(N);\n        int old_a = cur_a[i], old_b = cur_b[i];\n        if (type < 4) {\n            cur_a[i] = rand_int(N);\n        } else if (type < 8) {\n            cur_b[i] = rand_int(N);\n        } else if (type == 8) {\n            swap(cur_a[i], cur_b[i]);\n        } else {\n            cur_a[i] = rand_int(N);\n            cur_b[i] = rand_int(N);\n        }\n        double new_surr_err = surrogate_error(cur_a, cur_b);\n        double delta = new_surr_err - cur_surr_err;\n        bool accepted = false;\n        if (delta <= 0) {\n            accepted = true;\n        } else if (rand_double() < exp(-delta / temp_surr)) {\n            accepted = true;\n        }\n        if (accepted) {\n            cur_surr_err = new_surr_err;\n            if (cur_surr_err < best_surr_err) {\n                best_surr_err = cur_surr_err;\n                int real_err = real_error(cur_a, cur_b);\n                if (real_err < best_err) {\n                    best_err = real_err;\n                    memcpy(best_a, cur_a, sizeof(cur_a));\n                    memcpy(best_b, cur_b, sizeof(cur_b));\n                }\n            }\n        } else {\n            cur_a[i] = old_a;\n            cur_b[i] = old_b;\n        }\n        ++iter;\n    }\n    \n    // restore best found so far\n    memcpy(cur_a, best_a, sizeof(cur_a));\n    memcpy(cur_b, best_b, sizeof(cur_b));\n    cur_real_err = best_err;\n    \n    // ---------- Stage 2: Real SA for remaining time ----------\n    double temp_real = max(cur_real_err * 0.2, 1.0);\n    double temp_real_end = 0.1;\n    iter = 0;\n    while (true) {\n        if (iter % 10 == 0) {\n            auto now = chrono::steady_clock::now();\n            elapsed = chrono::duration<double>(now - start).count();\n            if (elapsed > time_limit_total) break;\n            double progress = max(0.0, min(1.0, (elapsed - time_limit_surr) / (time_limit_total - time_limit_surr)));\n            temp_real = max(cur_real_err * 0.2, 1.0) * pow(temp_real_end / max(cur_real_err * 0.2, 1.0), progress);\n        }\n        int type = rand_int(10);\n        int i = rand_int(N);\n        int old_a = cur_a[i], old_b = cur_b[i];\n        if (type < 4) {\n            cur_a[i] = rand_int(N);\n        } else if (type < 8) {\n            cur_b[i] = rand_int(N);\n        } else if (type == 8) {\n            swap(cur_a[i], cur_b[i]);\n        } else {\n            cur_a[i] = rand_int(N);\n            cur_b[i] = rand_int(N);\n        }\n        int new_err = real_error(cur_a, cur_b);\n        int delta = new_err - cur_real_err;\n        bool accepted = false;\n        if (delta <= 0) {\n            accepted = true;\n        } else if (rand_double() < exp(-delta / temp_real)) {\n            accepted = true;\n        }\n        if (accepted) {\n            cur_real_err = new_err;\n            if (new_err < best_err) {\n                best_err = new_err;\n                memcpy(best_a, cur_a, sizeof(cur_a));\n                memcpy(best_b, cur_b, sizeof(cur_b));\n            }\n        } else {\n            cur_a[i] = old_a;\n            cur_b[i] = old_b;\n        }\n        ++iter;\n        if (best_err == 0) break;\n    }\n    \n    for (int i = 0; i < N; ++i) {\n        cout << best_a[i] << \" \" << best_b[i] << \"\\n\";\n    }\n    \n    return 0;\n}","ahc045":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n#include <cstdint>\n\nusing namespace std;\n\nint N, M, Q, L;\nint q_used = 0;                      // number of queries performed\nvector<int> cx, cy;                  // estimated centers\n\n// query a subset, return MST edges (u, v) with u<v\nvector<pair<int, int>> query_subset(const vector<int>& C) {\n    if (q_used >= Q) return {};      // no more queries allowed\n    ++q_used;\n    int l = (int)C.size();\n    cout << \"? \" << l;\n    for (int c : C) cout << \" \" << c;\n    cout << endl;\n    vector<pair<int, int>> res(l - 1);\n    for (int i = 0; i < l - 1; ++i) {\n        cin >> res[i].first >> res[i].second;\n    }\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int W;\n    cin >> N >> M >> Q >> L >> W;\n    vector<int> G(M);\n    for (int i = 0; i < M; ++i) cin >> G[i];\n\n    vector<int> lx(N), rx(N), ly(N), ry(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n    }\n\n    // estimated centre of each city\n    cx.resize(N);\n    cy.resize(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    // Morton code for spatial ordering (15 bits per coordinate, enough for 0..10000)\n    auto morton = [&](int x, int y) -> uint64_t {\n        uint64_t z = 0;\n        for (int i = 14; i >= 0; --i) {\n            z = (z << 2) | ((((x >> i) & 1) << 1) | ((y >> i) & 1));\n        }\n        return z;\n    };\n    vector<uint64_t> mort(N);\n    for (int i = 0; i < N; ++i) {\n        mort[i] = morton(cx[i], cy[i]);\n    }\n\n    // global order of cities\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int i, int j) { return mort[i] < mort[j]; });\n\n    // split the ordered cities into groups\n    vector<vector<int>> groups(M);\n    int cur = 0;\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < G[i]; ++j) {\n            groups[i].push_back(order[cur++]);\n        }\n    }\n\n    // for each group we build a spanning tree\n    vector<vector<int>> group_cities(M);\n    vector<vector<pair<int, int>>> group_edges(M);\n\n    for (int k = 0; k < M; ++k) {\n        const auto& nodes = groups[k];\n        int sz = (int)nodes.size();\n        if (sz == 0) continue;\n        if (sz == 1) {\n            group_cities[k] = nodes;\n            continue;\n        }\n\n        vector<pair<int, int>> edges;\n        int pos = 0;\n        while (pos < sz) {\n            if (q_used >= Q) {\n                // budget exhausted \u2013 connect remaining cities linearly\n                for (int i = pos; i < sz; ++i) {\n                    edges.emplace_back(nodes[i - 1], nodes[i]);\n                }\n                break;\n            }\n            if (pos == 0) {\n                int l = min(L, sz - pos);\n                vector<int> C(nodes.begin(), nodes.begin() + l);\n                auto res = query_subset(C);\n                edges.insert(edges.end(), res.begin(), res.end());\n                pos += l;\n            } else {\n                int anchor = nodes[pos - 1];\n                int take = min(L - 1, sz - pos);\n                vector<int> C = {anchor};\n                C.insert(C.end(), nodes.begin() + pos, nodes.begin() + pos + take);\n                auto res = query_subset(C);\n                edges.insert(edges.end(), res.begin(), res.end());\n                pos += take;\n            }\n        }\n        group_cities[k] = nodes;\n        group_edges[k] = move(edges);\n    }\n\n    // output final answer\n    cout << \"!\" << endl;\n    for (int k = 0; k < M; ++k) {\n        const auto& cities = group_cities[k];\n        for (int i = 0; i < (int)cities.size(); ++i) {\n            if (i) cout << \" \";\n            cout << cities[i];\n        }\n        cout << endl;\n        for (const auto& e : group_edges[k]) {\n            cout << e.first << \" \" << e.second << endl;\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <string>\n\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int N, M;\n    cin >> N >> M;\n    vector<int> R(M), C(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> R[i] >> C[i];\n    }\n\n    int total = N * N;\n    int S = total;          // represents \"no block\"\n    int state_size = total + 1;\n    int MAX_STATE = total * state_size;\n\n    // precompute row and column for each cell\n    vector<int> pr(total), pc(total);\n    for (int i = 0; i < total; ++i) {\n        pr[i] = i / N;\n        pc[i] = i % N;\n    }\n\n    vector<int> vis(MAX_STATE, 0);\n    vector<int> ps(MAX_STATE);\n    vector<int> pa(MAX_STATE);\n    vector<int> q(MAX_STATE);\n    int tok = 0;\n\n    vector<int> total_actions;\n\n    // process each segment: start -> target1, target1 -> target2, ...\n    for (int seg = 0; seg < M - 1; ++seg) {\n        int start_pos = R[seg] * N + C[seg];\n        int target_pos = R[seg+1] * N + C[seg+1];\n\n        ++tok;\n        int head = 0, tail = 0;\n        int start_state = start_pos * state_size + S;\n        vis[start_state] = tok;\n        ps[start_state] = -1;\n        q[tail++] = start_state;\n        int goal_state = -1;\n\n        while (head < tail) {\n            int s = q[head++];\n            int pos = s / state_size;\n            int block = s % state_size;\n            if (pos == target_pos && block == S) {\n                goal_state = s;\n                break;\n            }\n            int r = pr[pos], c = pc[pos];\n\n            for (int d = 0; d < 4; ++d) {\n                // --- Move ---\n                int nr = r, nc = c;\n                if (d == 0) nr--;\n                else if (d == 1) nr++;\n                else if (d == 2) nc--;\n                else nc++;\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                    int npos = nr * N + nc;\n                    if (npos != block) {\n                        int nstate = npos * state_size + block;\n                        if (vis[nstate] != tok) {\n                            vis[nstate] = tok;\n                            ps[nstate] = s;\n                            pa[nstate] = 0 * 4 + d;  // Move\n                            q[tail++] = nstate;\n                        }\n                    }\n                }\n\n                // --- Slide ---\n                int slide_pos;\n                if (block == S) {\n                    if (d == 0) slide_pos = c;                     // (0, c)\n                    else if (d == 1) slide_pos = (N-1)*N + c;      // (N-1, c)\n                    else if (d == 2) slide_pos = r * N;            // (r, 0)\n                    else slide_pos = r * N + (N-1);                // (r, N-1)\n                } else {\n                    int br = block / N, bc = block % N;\n                    if (d == 0) {  // up\n                        if (bc == c && br < r) slide_pos = (br + 1) * N + c;\n                        else slide_pos = c;\n                    } else if (d == 1) {  // down\n                        if (bc == c && br > r) slide_pos = (br - 1) * N + c;\n                        else slide_pos = (N-1)*N + c;\n                    } else if (d == 2) {  // left\n                        if (br == r && bc < c) slide_pos = r * N + (bc + 1);\n                        else slide_pos = r * N;\n                    } else {  // right\n                        if (br == r && bc > c) slide_pos = r * N + (bc - 1);\n                        else slide_pos = r * N + (N-1);\n                    }\n                }\n                int nstate_s = slide_pos * state_size + block;\n                if (vis[nstate_s] != tok) {\n                    vis[nstate_s] = tok;\n                    ps[nstate_s] = s;\n                    pa[nstate_s] = 1 * 4 + d;  // Slide\n                    q[tail++] = nstate_s;\n                }\n\n                // --- Alter ---\n                int adj_r = r, adj_c = c;\n                if (d == 0) adj_r--;\n                else if (d == 1) adj_r++;\n                else if (d == 2) adj_c--;\n                else adj_c++;\n                if (adj_r >= 0 && adj_r < N && adj_c >= 0 && adj_c < N) {\n                    int adj_id = adj_r * N + adj_c;\n                    if (block == S) {\n                        // place block\n                        int nstate = pos * state_size + adj_id;\n                        if (vis[nstate] != tok) {\n                            vis[nstate] = tok;\n                            ps[nstate] = s;\n                            pa[nstate] = 2 * 4 + d;  // Alter (place)\n                            q[tail++] = nstate;\n                        }\n                    } else {\n                        if (adj_id == block) {\n                            // remove block\n                            int nstate = pos * state_size + S;\n                            if (vis[nstate] != tok) {\n                                vis[nstate] = tok;\n                                ps[nstate] = s;\n                                pa[nstate] = 2 * 4 + d;  // Alter (remove)\n                                q[tail++] = nstate;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        // reconstruct action sequence for this segment\n        vector<int> seg_actions;\n        for (int s = goal_state; s != start_state; s = ps[s]) {\n            seg_actions.push_back(pa[s]);\n        }\n        reverse(seg_actions.begin(), seg_actions.end());\n        total_actions.insert(total_actions.end(), seg_actions.begin(), seg_actions.end());\n    }\n\n    // cancel consecutive identical Alter actions (place/remove pairs that do nothing)\n    vector<int> opt_actions;\n    for (int aid : total_actions) {\n        if (!opt_actions.empty() && opt_actions.back() == aid && (aid / 4) == 2) {\n            opt_actions.pop_back();\n        } else {\n            opt_actions.push_back(aid);\n        }\n    }\n    total_actions = move(opt_actions);\n\n    const char act_chars[3] = {'M', 'S', 'A'};\n    const char dir_chars[4] = {'U', 'D', 'L', 'R'};\n    for (int aid : total_actions) {\n        cout << act_chars[aid / 4] << ' ' << dir_chars[aid % 4] << '\\n';\n    }\n\n    return 0;\n}"},"4":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\nusing namespace chrono;\n\nstruct XorShift {\n    uint32_t x, y, z, w;\n    XorShift(uint32_t seed = 123456789) : x(seed), y(362436069), z(521288629), w(88675123) {\n        for (int i = 0; i < 10; i++) next();\n    }\n    uint32_t next() {\n        uint32_t t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = w ^ (w >> 19) ^ t ^ (t >> 8);\n    }\n    int nextInt(int max) {\n        return next() % (max + 1);\n    }\n    double nextDouble() {\n        return (next() & 0xFFFFFF) / 16777216.0;\n    }\n};\n\nstruct Node {\n    int type;   // 0: leaf, 1: vertical, 2: horizontal\n    int leaf_id;\n    int k;\n    int left, right;\n    int parent;\n    int min_k, max_k;\n    int x1, y1, x2, y2;\n};\n\nint n;\nvector<int> x, y, r;\nvector<Node> nodes;\nint root;\nXorShift rng(system_clock::now().time_since_epoch().count());\n\ndouble leaf_score(long long area, int req) {\n    double rat = (area <= req) ? (double)area / req : (double)req / area;\n    return 2.0 * rat - rat * rat;\n}\n\ndouble evaluate(int idx, int x1, int y1, int x2, int y2) {\n    Node& node = nodes[idx];\n    node.x1 = x1; node.y1 = y1; node.x2 = x2; node.y2 = y2;\n    if (node.type == 0) {\n        long long area = (long long)(x2 - x1) * (y2 - y1);\n        return leaf_score(area, r[node.leaf_id]);\n    } else if (node.type == 1) {\n        int k = node.k;\n        return evaluate(node.left, x1, y1, k, y2) +\n               evaluate(node.right, k, y1, x2, y2);\n    } else {\n        int k = node.k;\n        return evaluate(node.left, x1, y1, x2, k) +\n               evaluate(node.right, x1, k, x2, y2);\n    }\n}\n\nvoid get_minmax(int idx, int& min_x, int& max_x, int& min_y, int& max_y) {\n    Node& node = nodes[idx];\n    if (node.type == 0) {\n        min_x = max_x = x[node.leaf_id];\n        min_y = max_y = y[node.leaf_id];\n    } else {\n        int lx_min, lx_max, ly_min, ly_max;\n        get_minmax(node.left, lx_min, lx_max, ly_min, ly_max);\n        int rx_min, rx_max, ry_min, ry_max;\n        get_minmax(node.right, rx_min, rx_max, ry_min, ry_max);\n        min_x = min(lx_min, rx_min);\n        max_x = max(lx_max, rx_max);\n        min_y = min(ly_min, ry_min);\n        max_y = max(ly_max, ry_max);\n    }\n}\n\nbool try_reorient(int idx) {\n    Node& node = nodes[idx];\n    if (node.type == 0) return false;\n    int lx_min, lx_max, ly_min, ly_max;\n    int rx_min, rx_max, ry_min, ry_max;\n    get_minmax(node.left, lx_min, lx_max, ly_min, ly_max);\n    get_minmax(node.right, rx_min, rx_max, ry_min, ry_max);\n\n    if (node.type == 1) { // vertical -> horizontal\n        if (ly_max < ry_min) {\n            node.type = 2;\n            node.min_k = ly_max + 1;\n            node.max_k = ry_min;\n            node.k = node.min_k + rng.nextInt(node.max_k - node.min_k);\n            return true;\n        }\n        if (ry_max < ly_min) {\n            swap(node.left, node.right);\n            node.type = 2;\n            node.min_k = ry_max + 1;\n            node.max_k = ly_min;\n            node.k = node.min_k + rng.nextInt(node.max_k - node.min_k);\n            return true;\n        }\n    } else { // horizontal -> vertical\n        if (lx_max < rx_min) {\n            node.type = 1;\n            node.min_k = lx_max + 1;\n            node.max_k = rx_min;\n            node.k = node.min_k + rng.nextInt(node.max_k - node.min_k);\n            return true;\n        }\n        if (rx_max < lx_min) {\n            swap(node.left, node.right);\n            node.type = 1;\n            node.min_k = rx_max + 1;\n            node.max_k = lx_min;\n            node.k = node.min_k + rng.nextInt(node.max_k - node.min_k);\n            return true;\n        }\n    }\n    return false;\n}\n\nvoid collect_leaves(int idx, vector<int>& leaves) {\n    Node& node = nodes[idx];\n    if (node.type == 0) {\n        leaves.push_back(node.leaf_id);\n    } else {\n        collect_leaves(node.left, leaves);\n        collect_leaves(node.right, leaves);\n    }\n}\n\nint build_greedy_tree(const vector<int>& pts, int x1, int y1, int x2, int y2, int parent) {\n    if (pts.size() == 1) {\n        int id = pts[0];\n        nodes.push_back({0, id, 0, -1, -1, parent, 0, 0, 0, 0, 0, 0});\n        return (int)nodes.size() - 1;\n    }\n    long long sumR = 0;\n    for (int id : pts) sumR += r[id];\n\n    struct Candidate { int orient; int k; vector<int> left, right; double err; };\n    vector<Candidate> cands;\n\n    // vertical cuts\n    vector<int> sorted = pts;\n    sort(sorted.begin(), sorted.end(), [&](int a, int b) { return x[a] < x[b]; });\n    long long left_sum = 0;\n    for (int i = 0; i < (int)sorted.size() - 1; i++) {\n        left_sum += r[sorted[i]];\n        double ideal = (double)left_sum / sumR;\n        int min_k = x[sorted[i]] + 1;\n        int max_k = x[sorted[i+1]];\n        if (min_k > max_k) continue;\n        int k = clamp((int)round(x1 + ideal * (x2 - x1)), min_k, max_k);\n        double actual = (double)(k - x1) / (x2 - x1);\n        double err = fabs(actual - ideal);\n        cands.push_back({1, k, \n            vector<int>(sorted.begin(), sorted.begin()+i+1),\n            vector<int>(sorted.begin()+i+1, sorted.end()), err});\n    }\n\n    // horizontal cuts\n    sort(sorted.begin(), sorted.end(), [&](int a, int b) { return y[a] < y[b]; });\n    left_sum = 0;\n    for (int i = 0; i < (int)sorted.size() - 1; i++) {\n        left_sum += r[sorted[i]];\n        double ideal = (double)left_sum / sumR;\n        int min_k = y[sorted[i]] + 1;\n        int max_k = y[sorted[i+1]];\n        if (min_k > max_k) continue;\n        int k = clamp((int)round(y1 + ideal * (y2 - y1)), min_k, max_k);\n        double actual = (double)(k - y1) / (y2 - y1);\n        double err = fabs(actual - ideal);\n        cands.push_back({2, k, \n            vector<int>(sorted.begin(), sorted.begin()+i+1),\n            vector<int>(sorted.begin()+i+1, sorted.end()), err});\n    }\n\n    double min_err = 1e9;\n    for (auto& c : cands) if (c.err < min_err) min_err = c.err;\n    vector<double> w(cands.size());\n    double sum_w = 0;\n    for (size_t i = 0; i < cands.size(); i++) {\n        w[i] = exp(-(cands[i].err - min_err) * 100.0);\n        sum_w += w[i];\n    }\n    double rv = rng.nextDouble() * sum_w;\n    int chosen = 0;\n    double cum = 0;\n    for (size_t i = 0; i < cands.size(); i++) {\n        cum += w[i];\n        if (cum >= rv) { chosen = i; break; }\n    }\n    Candidate& best = cands[chosen];\n\n    nodes.push_back({best.orient, -1, best.k, -1, -1, parent, 0, 0, 0, 0, 0, 0});\n    int idx = (int)nodes.size() - 1;\n\n    int lchild, rchild;\n    if (best.orient == 1) {\n        lchild = build_greedy_tree(best.left, x1, y1, best.k, y2, idx);\n        rchild = build_greedy_tree(best.right, best.k, y1, x2, y2, idx);\n        int max_x_left = 0, min_x_right = 10000;\n        for (int id : best.left) max_x_left = max(max_x_left, x[id]);\n        for (int id : best.right) min_x_right = min(min_x_right, x[id]);\n        nodes[idx].min_k = max_x_left + 1;\n        nodes[idx].max_k = min_x_right;\n    } else {\n        lchild = build_greedy_tree(best.left, x1, y1, x2, best.k, idx);\n        rchild = build_greedy_tree(best.right, x1, best.k, x2, y2, idx);\n        int max_y_bottom = 0, min_y_top = 10000;\n        for (int id : best.left) max_y_bottom = max(max_y_bottom, y[id]);\n        for (int id : best.right) min_y_top = min(min_y_top, y[id]);\n        nodes[idx].min_k = max_y_bottom + 1;\n        nodes[idx].max_k = min_y_top;\n    }\n    nodes[idx].left = lchild;\n    nodes[idx].right = rchild;\n    return idx;\n}\n\nint build_random_tree(const vector<int>& pts, int x1, int y1, int x2, int y2, int parent) {\n    if (pts.size() == 1) {\n        int id = pts[0];\n        nodes.push_back({0, id, 0, -1, -1, parent, 0, 0, 0, 0, 0, 0});\n        return (int)nodes.size() - 1;\n    }\n    vector<int> sorted_x = pts, sorted_y = pts;\n    sort(sorted_x.begin(), sorted_x.end(), [&](int a, int b) { return x[a] < x[b]; });\n    sort(sorted_y.begin(), sorted_y.end(), [&](int a, int b) { return y[a] < y[b]; });\n\n    vector<pair<int, vector<int>>> v_splits, h_splits;\n    for (int i = 0; i < (int)sorted_x.size() - 1; i++) {\n        int max_x = x[sorted_x[i]], min_x = x[sorted_x[i+1]];\n        if (max_x + 1 <= min_x) {\n            v_splits.push_back({i, {}});\n        }\n    }\n    for (int i = 0; i < (int)sorted_y.size() - 1; i++) {\n        int max_y = y[sorted_y[i]], min_y = y[sorted_y[i+1]];\n        if (max_y + 1 <= min_y) {\n            h_splits.push_back({i, {}});\n        }\n    }\n    if (v_splits.empty() && h_splits.empty()) {\n        // forced, should not happen often\n        // fallback: just split by middle\n        // we'll just do a greedy split\n        return build_greedy_tree(pts, x1, y1, x2, y2, parent);\n    }\n\n    int orient;\n    int split_idx;\n    if (v_splits.empty()) {\n        orient = 2;\n        split_idx = h_splits[rng.nextInt(h_splits.size()-1)].first;\n    } else if (h_splits.empty()) {\n        orient = 1;\n        split_idx = v_splits[rng.nextInt(v_splits.size()-1)].first;\n    } else {\n        if (rng.nextDouble() < 0.5) {\n            orient = 1;\n            split_idx = v_splits[rng.nextInt(v_splits.size()-1)].first;\n        } else {\n            orient = 2;\n            split_idx = h_splits[rng.nextInt(h_splits.size()-1)].first;\n        }\n    }\n\n    vector<int> left_pts, right_pts;\n    if (orient == 1) {\n        left_pts.assign(sorted_x.begin(), sorted_x.begin() + split_idx + 1);\n        right_pts.assign(sorted_x.begin() + split_idx + 1, sorted_x.end());\n    } else {\n        left_pts.assign(sorted_y.begin(), sorted_y.begin() + split_idx + 1);\n        right_pts.assign(sorted_y.begin() + split_idx + 1, sorted_y.end());\n    }\n\n    int min_k, max_k;\n    if (orient == 1) {\n        min_k = x[ sorted_x[split_idx] ] + 1;\n        max_k = x[ sorted_x[split_idx+1] ];\n    } else {\n        min_k = y[ sorted_y[split_idx] ] + 1;\n        max_k = y[ sorted_y[split_idx+1] ];\n    }\n    int k = min_k + rng.nextInt(max_k - min_k);\n\n    nodes.push_back({orient, -1, k, -1, -1, parent, min_k, max_k, 0,0,0,0});\n    int idx = (int)nodes.size() - 1;\n    int lchild, rchild;\n    if (orient == 1) {\n        lchild = build_random_tree(left_pts, x1, y1, k, y2, idx);\n        rchild = build_random_tree(right_pts, k, y1, x2, y2, idx);\n    } else {\n        lchild = build_random_tree(left_pts, x1, y1, x2, k, idx);\n        rchild = build_random_tree(right_pts, x1, k, x2, y2, idx);\n    }\n    nodes[idx].left = lchild;\n    nodes[idx].right = rchild;\n    return idx;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n;\n    x.resize(n); y.resize(n); r.resize(n);\n    for (int i = 0; i < n; i++) cin >> x[i] >> y[i] >> r[i];\n\n    double global_best_score = -1e9;\n    vector<Node> best_nodes;\n    int best_root = -1;\n    auto start_time = steady_clock::now();\n    auto time_left = [&]() { return duration<double>(steady_clock::now() - start_time).count() > 4.7; };\n\n    while (!time_left()) {\n        nodes.clear();\n        vector<int> all(n);\n        iota(all.begin(), all.end(), 0);\n        root = build_greedy_tree(all, 0, 0, 10000, 10000, -1);\n        double current = evaluate(root, 0, 0, 10000, 10000);\n        double best_restart = current;\n        vector<Node> best_restart_nodes = nodes;\n        int best_restart_root = root;\n\n        const int max_iter = 200000;\n        const double T_start = 1.0;\n        const double T_end = 1e-6;\n\n        for (int iter = 0; iter < max_iter; iter++) {\n            if (iter % 1000 == 0 && time_left()) break;\n            double progress = (double)iter / max_iter;\n            double T = T_start * pow(T_end / T_start, progress);\n\n            int rtype = rng.nextInt(99);\n            if (rtype < 5) { // local rebuild\n                int idx = -1;\n                {\n                    vector<int> tmp;\n                    function<void(int)> dfs = [&](int u) {\n                        if (nodes[u].type != 0) tmp.push_back(u);\n                        if (nodes[u].type != 0) {\n                            dfs(nodes[u].left);\n                            dfs(nodes[u].right);\n                        }\n                    };\n                    dfs(root);\n                    if (tmp.empty()) continue;\n                    idx = tmp[rng.nextInt(tmp.size() - 1)];\n                }\n                Node& cur = nodes[idx];\n                int px1 = cur.x1, py1 = cur.y1, px2 = cur.x2, py2 = cur.y2;\n                vector<int> leaves;\n                collect_leaves(idx, leaves);\n                int p = cur.parent;\n                bool is_left = false;\n                if (p != -1) is_left = (nodes[p].left == idx);\n\n                vector<Node> old_nodes = nodes;\n                int old_root = root;\n\n                int new_subroot;\n                if (rng.nextDouble() < 0.5)\n                    new_subroot = build_greedy_tree(leaves, px1, py1, px2, py2, p);\n                else\n                    new_subroot = build_random_tree(leaves, px1, py1, px2, py2, p);\n\n                if (p != -1) {\n                    if (is_left) nodes[p].left = new_subroot;\n                    else nodes[p].right = new_subroot;\n                } else {\n                    root = new_subroot;\n                }\n                double new_score = evaluate(root, 0, 0, 10000, 10000);\n                if (new_score > current || rng.nextDouble() < exp((new_score - current) / T)) {\n                    current = new_score;\n                    if (new_score > best_restart) {\n                        best_restart = new_score;\n                        best_restart_nodes = nodes;\n                        best_restart_root = root;\n                    }\n                } else {\n                    nodes = move(old_nodes);\n                    root = old_root;\n                    evaluate(root, 0, 0, 10000, 10000);\n                }\n            } else if (rtype < 25) { // reorient (20%)\n                bool done = false;\n                for (int attempt = 0; attempt < 5; attempt++) {\n                    vector<int> tmp;\n                    function<void(int)> dfs = [&](int u) {\n                        if (nodes[u].type != 0) tmp.push_back(u);\n                        if (nodes[u].type != 0) {\n                            dfs(nodes[u].left);\n                            dfs(nodes[u].right);\n                        }\n                    };\n                    dfs(root);\n                    if (tmp.empty()) break;\n                    int idx = tmp[rng.nextInt(tmp.size() - 1)];\n                    Node saved = nodes[idx];\n                    int saved_left = nodes[idx].left, saved_right = nodes[idx].right;\n                    if (!try_reorient(idx)) continue;\n                    double new_score = evaluate(root, 0, 0, 10000, 10000);\n                    if (new_score > current || rng.nextDouble() < exp((new_score - current) / T)) {\n                        current = new_score;\n                        if (new_score > best_restart) {\n                            best_restart = new_score;\n                            best_restart_nodes = nodes;\n                            best_restart_root = root;\n                        }\n                        done = true;\n                        break;\n                    } else {\n                        nodes[idx] = saved;\n                        nodes[idx].left = saved_left;\n                        nodes[idx].right = saved_right;\n                        evaluate(root, 0, 0, 10000, 10000);\n                    }\n                }\n                // if not done, it's a no-op\n            } else { // change cut coordinate (75%)\n                vector<int> tmp;\n                function<void(int)> dfs = [&](int u) {\n                    if (nodes[u].type != 0) tmp.push_back(u);\n                    if (nodes[u].type != 0) {\n                        dfs(nodes[u].left);\n                        dfs(nodes[u].right);\n                    }\n                };\n                dfs(root);\n                if (tmp.empty()) continue;\n                int idx = tmp[rng.nextInt(tmp.size() - 1)];\n                int old_k = nodes[idx].k;\n                int min_k = nodes[idx].min_k, max_k = nodes[idx].max_k;\n                if (min_k == max_k) continue;\n                int new_k = min_k + rng.nextInt(max_k - min_k);\n                if (new_k == old_k) continue;\n                nodes[idx].k = new_k;\n                double new_score = evaluate(root, 0, 0, 10000, 10000);\n                if (new_score > current || rng.nextDouble() < exp((new_score - current) / T)) {\n                    current = new_score;\n                    if (new_score > best_restart) {\n                        best_restart = new_score;\n                        best_restart_nodes = nodes;\n                        best_restart_root = root;\n                    }\n                } else {\n                    nodes[idx].k = old_k;\n                    evaluate(root, 0, 0, 10000, 10000);\n                }\n            }\n        } // SA loop\n\n        if (best_restart > global_best_score) {\n            global_best_score = best_restart;\n            best_nodes = best_restart_nodes;\n            best_root = best_restart_root;\n        }\n    }\n\n    // Final polishing on the global best\n    nodes = move(best_nodes);\n    root = best_root;\n    evaluate(root, 0, 0, 10000, 10000);\n    vector<int> internal_nodes;\n    {\n        function<void(int)> dfs = [&](int u) {\n            if (nodes[u].type != 0) internal_nodes.push_back(u);\n            if (nodes[u].type != 0) {\n                dfs(nodes[u].left);\n                dfs(nodes[u].right);\n            }\n        };\n        dfs(root);\n    }\n    double current_score = evaluate(root, 0, 0, 10000, 10000);\n    for (int idx : internal_nodes) {\n        if (nodes[idx].min_k >= nodes[idx].max_k) continue;\n        int old_k = nodes[idx].k;\n        double best_local = current_score;\n        int best_k = old_k;\n        for (int k = nodes[idx].min_k; k <= nodes[idx].max_k; k++) {\n            if (k == old_k) continue;\n            nodes[idx].k = k;\n            double sc = evaluate(root, 0, 0, 10000, 10000);\n            if (sc > best_local) {\n                best_local = sc;\n                best_k = k;\n            }\n        }\n        if (best_k != old_k) {\n            nodes[idx].k = best_k;\n            current_score = best_local;\n        } else {\n            nodes[idx].k = old_k;\n            evaluate(root, 0, 0, 10000, 10000);\n        }\n    }\n\n    // Output\n    evaluate(root, 0, 0, 10000, 10000);\n    vector<array<int,4>> ans(n);\n    function<void(int)> collect = [&](int u) {\n        Node& nd = nodes[u];\n        if (nd.type == 0) {\n            ans[nd.leaf_id] = {nd.x1, nd.y1, nd.x2, nd.y2};\n        } else {\n            collect(nd.left);\n            collect(nd.right);\n        }\n    };\n    collect(root);\n    for (auto [a,b,c,d] : ans) cout << a << \" \" << b << \" \" << c << \" \" << d << \"\\n\";\n\n    return 0;\n}","ahc002":"#include <iostream>\n#include <vector>\n#include <bitset>\n#include <queue>\n#include <algorithm>\n#include <chrono>\n#include <numeric>\n#include <unordered_map>\n#include <string>\nusing namespace std;\n\nconstexpr int N = 50;\nconstexpr int MAX_TILES = 2500;\n\nstruct State {\n    int parent_id;\n    unsigned short current_tile;\n    int score;\n    bitset<MAX_TILES> visited;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj;\n    cin >> si >> sj;\n\n    vector t(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> t[i][j];\n\n    vector p(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> p[i][j];\n\n    // --- Compute tiles ---\n    int M = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (t[i][j] > M) M = t[i][j];\n    M += 1;\n\n    vector<vector<pair<int,int>>> tile_sq(M);\n    vector<int> tile_weight(M, 0);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int id = t[i][j];\n            tile_sq[id].push_back({i, j});\n            tile_weight[id] += p[i][j];\n        }\n    }\n\n    // --- Adjacency and exit squares ---\n    const int dirs[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};\n    vector<vector<int>> adj(M);\n    vector<unordered_map<int, pair<int,int>>> exit_sq(M);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = t[i][j];\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + dirs[d][0], nj = j + dirs[d][1];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                int v = t[ni][nj];\n                if (u != v) {\n                    adj[u].push_back(v);\n                    if (exit_sq[u].find(v) == exit_sq[u].end()) {\n                        exit_sq[u][v] = {i, j};\n                    }\n                }\n            }\n        }\n    }\n    for (int i = 0; i < M; ++i) {\n        sort(adj[i].begin(), adj[i].end());\n        adj[i].erase(unique(adj[i].begin(), adj[i].end()), adj[i].end());\n    }\n\n    // --- Beam search ---\n    int start_tile = t[si][sj];\n    vector<State> states;\n    states.reserve(2000000);\n    State init;\n    init.parent_id = -1;\n    init.current_tile = start_tile;\n    init.visited.reset();\n    init.visited.set(start_tile);\n    init.score = tile_weight[start_tile];\n    states.push_back(init);\n    vector<int> cur = {0};\n    int best_id = 0;\n\n    const int BEAM_WIDTH = 700;\n    auto start_time = chrono::steady_clock::now();\n\n    while (!cur.empty()) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - start_time).count() > 1950) break;\n        if (states.size() > 2000000) break;\n\n        vector<int> nxt_cand;\n        nxt_cand.reserve(cur.size() * 4);\n        for (int id : cur) {\n            const State& st = states[id];\n            unsigned short u = st.current_tile;\n            for (unsigned short v : adj[u]) {\n                if (!st.visited[v]) {\n                    State ns = st;\n                    ns.visited.set(v);\n                    ns.score += tile_weight[v];\n                    ns.current_tile = v;\n                    ns.parent_id = id;\n                    nxt_cand.push_back(states.size());\n                    states.push_back(move(ns));\n                    if (states.back().score > states[best_id].score) {\n                        best_id = states.size() - 1;\n                    }\n                }\n            }\n        }\n        if (nxt_cand.empty()) break;\n\n        if ((int)nxt_cand.size() > BEAM_WIDTH) {\n            // Heuristic: current score + sum of weights of tiles within 2 steps\n            vector<long long> vals(nxt_cand.size());\n            for (size_t i = 0; i < nxt_cand.size(); ++i) {\n                int sid = nxt_cand[i];\n                const State& s = states[sid];\n                long long h = s.score;\n                vector<bool> vis_local(M, false);\n                queue<int> q;\n                q.push(s.current_tile);\n                vis_local[s.current_tile] = true;\n                for (int d = 0; d < 2; ++d) {\n                    int qsz = q.size();\n                    if (qsz == 0) break;\n                    for (int k = 0; k < qsz; ++k) {\n                        int uu = q.front(); q.pop();\n                        for (int vv : adj[uu]) {\n                            if (!s.visited[vv] && !vis_local[vv]) {\n                                vis_local[vv] = true;\n                                h += tile_weight[vv];\n                                q.push(vv);\n                            }\n                        }\n                    }\n                }\n                vals[i] = h;\n            }\n            vector<int> idx(nxt_cand.size());\n            iota(idx.begin(), idx.end(), 0);\n            sort(idx.begin(), idx.end(), [&](int i, int j) { return vals[i] > vals[j]; });\n            cur.clear();\n            cur.reserve(BEAM_WIDTH);\n            for (int i = 0; i < BEAM_WIDTH; ++i) {\n                cur.push_back(nxt_cand[idx[i]]);\n            }\n        } else {\n            cur = move(nxt_cand);\n        }\n    }\n\n    // --- Reconstruct tile sequence ---\n    vector<unsigned short> tile_seq;\n    for (int id = best_id; id != -1; id = states[id].parent_id) {\n        tile_seq.push_back(states[id].current_tile);\n    }\n    reverse(tile_seq.begin(), tile_seq.end());\n\n    // --- Generate path string ---\n    string ans;\n    int x = si, y = sj;\n    vector vis(N, vector<bool>(N, false));\n    vis[x][y] = true;\n\n    auto get_move = [&](int x1, int y1, int x2, int y2) -> string {\n        if (x2 == x1 - 1) return \"U\";\n        if (x2 == x1 + 1) return \"D\";\n        if (y2 == y1 - 1) return \"L\";\n        if (y2 == y1 + 1) return \"R\";\n        return \"\";\n    };\n\n    for (size_t idx = 0; idx < tile_seq.size(); ++idx) {\n        unsigned short t = tile_seq[idx];\n        auto& sqs = tile_sq[t];\n        // Visit all squares inside the current tile\n        if (sqs.size() == 2) {\n            auto [r0, c0] = sqs[0];\n            auto [r1, c1] = sqs[1];\n            bool v0 = vis[r0][c0], v1 = vis[r1][c1];\n            if (!v0 || !v1) {\n                auto [ur, uc] = v0 ? sqs[1] : sqs[0];\n                ans += get_move(x, y, ur, uc);\n                x = ur; y = uc;\n                vis[x][y] = true;\n            }\n        }\n        // If not the last tile, move to exit square and then to the next tile\n        if (idx != tile_seq.size() - 1) {\n            unsigned short nxt = tile_seq[idx + 1];\n            auto [ex, ey] = exit_sq[t][nxt];\n            if (x != ex || y != ey) {\n                ans += get_move(x, y, ex, ey);\n                x = ex; y = ey;\n                vis[x][y] = true;\n            }\n            int nx = -1, ny = -1;\n            for (int d = 0; d < 4; ++d) {\n                int ni = x + dirs[d][0], nj = y + dirs[d][1];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N && t[ni][nj] == nxt) {\n                    nx = ni; ny = nj;\n                    break;\n                }\n            }\n            if (nx != -1) {\n                ans += get_move(x, y, nx, ny);\n                x = nx; y = ny;\n                vis[x][y] = true;\n            } else {\n                break; // should not happen\n            }\n        }\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int N = 30;\nconstexpr int H_EDGES = N * (N - 1);   // 870\nconstexpr int V_EDGES = (N - 1) * N;   // 870\nconstexpr int E = H_EDGES + V_EDGES;   // 1740\n\nint edge_idx_horiz(int i, int j) { return i * (N - 1) + j; }\nint edge_idx_vert(int i, int j) { return H_EDGES + i * N + j; }\n\nstring dijkstra(int si, int sj, int ti, int tj,\n                const vector<double>& w_plan,\n                const vector<int>& cnt,\n                double alpha_explore,\n                mt19937& rng,\n                vector<int>& path_edges) {\n    int start = si * N + sj;\n    int goal = ti * N + tj;\n\n    vector<double> dist(N * N, 1e18);\n    vector<int> parent(N * N, -1);\n    vector<int> parent_edge(N * N, -1);\n    dist[start] = 0;\n\n    using P = pair<double, int>;\n    priority_queue<P, vector<P>, greater<P>> pq;\n    pq.push({0, start});\n\n    uniform_real_distribution<double> noise(-0.5, 0.5);\n\n    static vector<vector<pair<int, int>>> adj;\n    if (adj.empty()) {\n        adj.resize(N * N);\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (j < N - 1) {\n                    int u = i * N + j, v = i * N + j + 1;\n                    int e = edge_idx_horiz(i, j);\n                    adj[u].push_back({v, e});\n                    adj[v].push_back({u, e});\n                }\n                if (i < N - 1) {\n                    int u = i * N + j, v = (i + 1) * N + j;\n                    int e = edge_idx_vert(i, j);\n                    adj[u].push_back({v, e});\n                    adj[v].push_back({u, e});\n                }\n            }\n        }\n    }\n\n    while (!pq.empty()) {\n        auto [d, u] = pq.top(); pq.pop();\n        if (d != dist[u]) continue;\n        if (u == goal) break;\n        for (auto [v, e] : adj[u]) {\n            double w_used = w_plan[e] - alpha_explore / sqrt(cnt[e] + 1.0);\n            if (w_used < 1.0) w_used = 1.0;\n            double nd = d + w_used + noise(rng) * 0.1;\n            if (nd < dist[v]) {\n                dist[v] = nd;\n                parent[v] = u;\n                parent_edge[v] = e;\n                pq.push({nd, v});\n            }\n        }\n    }\n\n    path_edges.clear();\n    vector<int> nodes;\n    for (int cur = goal; cur != start; cur = parent[cur]) {\n        nodes.push_back(cur);\n        path_edges.push_back(parent_edge[cur]);\n    }\n    nodes.push_back(start);\n    reverse(nodes.begin(), nodes.end());\n    reverse(path_edges.begin(), path_edges.end());\n\n    string moves;\n    for (size_t i = 0; i + 1 < nodes.size(); ++i) {\n        int u = nodes[i], v = nodes[i + 1];\n        int ui = u / N, uj = u % N;\n        int vi = v / N, vj = v % N;\n        if (vi == ui - 1) moves += 'U';\n        else if (vi == ui + 1) moves += 'D';\n        else if (vj == uj - 1) moves += 'L';\n        else moves += 'R';\n    }\n    return moves;\n}\n\n// Hard segmentation: replace w with two-constant model if it reduces weighted SSE significantly\nvoid hard_segment_rows(vector<double>& w, const vector<int>& cnt) {\n    for (int i = 0; i < N; ++i) {\n        vector<double> vals(N - 1);\n        vector<double> weight(N - 1);\n        double total_weight = 0.0, total_wsum = 0.0, total_wsum2 = 0.0;\n        for (int j = 0; j < N - 1; ++j) {\n            int e = edge_idx_horiz(i, j);\n            vals[j] = w[e];\n            double wgt = cnt[e] + 1.0;\n            weight[j] = wgt;\n            total_weight += wgt;\n            total_wsum += wgt * vals[j];\n            total_wsum2 += wgt * vals[j] * vals[j];\n        }\n\n        double mean_all = total_wsum / total_weight;\n        double base_sse = total_wsum2 - 2.0 * mean_all * total_wsum + mean_all * mean_all * total_weight;\n        double best_sse = base_sse;\n        int best_x = -1;\n        double best_meanL = mean_all, best_meanR = mean_all;\n\n        double wsum_left = 0.0, wsum2_left = 0.0, wgt_left = 0.0;\n        for (int x = 1; x < N - 1; ++x) {\n            int j = x - 1;\n            double wgt = weight[j];\n            double v = vals[j];\n            wsum_left += wgt * v;\n            wsum2_left += wgt * v * v;\n            wgt_left += wgt;\n\n            double meanL = wsum_left / wgt_left;\n            double wgt_right = total_weight - wgt_left;\n            double wsum_right = total_wsum - wsum_left;\n            double meanR = wsum_right / wgt_right;\n            double wsum2_right = total_wsum2 - wsum2_left;\n\n            double sseL = wsum2_left - 2.0 * meanL * wsum_left + meanL * meanL * wgt_left;\n            double sseR = wsum2_right - 2.0 * meanR * wsum_right + meanR * meanR * wgt_right;\n            double sse = sseL + sseR;\n\n            if (sse < best_sse) {\n                best_sse = sse;\n                best_x = x;\n                best_meanL = meanL;\n                best_meanR = meanR;\n            }\n        }\n\n        if (best_sse < base_sse * 0.95) {\n            for (int j = 0; j < N - 1; ++j) {\n                int e = edge_idx_horiz(i, j);\n                w[e] = (j < best_x) ? best_meanL : best_meanR;\n            }\n        } else {\n            for (int j = 0; j < N - 1; ++j) {\n                int e = edge_idx_horiz(i, j);\n                w[e] = mean_all;\n            }\n        }\n    }\n}\n\nvoid hard_segment_cols(vector<double>& w, const vector<int>& cnt) {\n    for (int j = 0; j < N; ++j) {\n        vector<double> vals(N - 1);\n        vector<double> weight(N - 1);\n        double total_weight = 0.0, total_wsum = 0.0, total_wsum2 = 0.0;\n        for (int i = 0; i < N - 1; ++i) {\n            int e = edge_idx_vert(i, j);\n            vals[i] = w[e];\n            double wgt = cnt[e] + 1.0;\n            weight[i] = wgt;\n            total_weight += wgt;\n            total_wsum += wgt * vals[i];\n            total_wsum2 += wgt * vals[i] * vals[i];\n        }\n\n        double mean_all = total_wsum / total_weight;\n        double base_sse = total_wsum2 - 2.0 * mean_all * total_wsum + mean_all * mean_all * total_weight;\n        double best_sse = base_sse;\n        int best_x = -1;\n        double best_meanL = mean_all, best_meanR = mean_all;\n\n        double wsum_left = 0.0, wsum2_left = 0.0, wgt_left = 0.0;\n        for (int x = 1; x < N - 1; ++x) {\n            int i = x - 1;\n            double wgt = weight[i];\n            double v = vals[i];\n            wsum_left += wgt * v;\n            wsum2_left += wgt * v * v;\n            wgt_left += wgt;\n\n            double meanL = wsum_left / wgt_left;\n            double wgt_right = total_weight - wgt_left;\n            double wsum_right = total_wsum - wsum_left;\n            double meanR = wsum_right / wgt_right;\n            double wsum2_right = total_wsum2 - wsum2_left;\n\n            double sseL = wsum2_left - 2.0 * meanL * wsum_left + meanL * meanL * wgt_left;\n            double sseR = wsum2_right - 2.0 * meanR * wsum_right + meanR * meanR * wgt_right;\n            double sse = sseL + sseR;\n\n            if (sse < best_sse) {\n                best_sse = sse;\n                best_x = x;\n                best_meanL = meanL;\n                best_meanR = meanR;\n            }\n        }\n\n        if (best_sse < base_sse * 0.95) {\n            for (int i = 0; i < N - 1; ++i) {\n                int e = edge_idx_vert(i, j);\n                w[e] = (i < best_x) ? best_meanL : best_meanR;\n            }\n        } else {\n            for (int i = 0; i < N - 1; ++i) {\n                int e = edge_idx_vert(i, j);\n                w[e] = mean_all;\n            }\n        }\n    }\n}\n\n// Soft segmentation: gently pull edges toward inferred block means\nvoid soft_segment_rows(vector<double>& w, const vector<int>& cnt, double lr_soft) {\n    for (int i = 0; i < N; ++i) {\n        int total_cnt = 0;\n        for (int j = 0; j < N - 1; ++j) total_cnt += cnt[edge_idx_horiz(i, j)];\n        if (total_cnt < 20) continue;   // not enough data\n\n        vector<double> vals(N - 1);\n        vector<double> weight(N - 1);\n        double total_weight = 0.0, total_wsum = 0.0, total_wsum2 = 0.0;\n        for (int j = 0; j < N - 1; ++j) {\n            int e = edge_idx_horiz(i, j);\n            vals[j] = w[e];\n            double wgt = cnt[e] + 1.0;\n            weight[j] = wgt;\n            total_weight += wgt;\n            total_wsum += wgt * vals[j];\n            total_wsum2 += wgt * vals[j] * vals[j];\n        }\n\n        double mean_all = total_wsum / total_weight;\n        double base_sse = total_wsum2 - 2.0 * mean_all * total_wsum + mean_all * mean_all * total_weight;\n        double best_sse = base_sse;\n        int best_x = -1;\n        double best_meanL = mean_all, best_meanR = mean_all;\n\n        double wsum_left = 0.0, wsum2_left = 0.0, wgt_left = 0.0;\n        for (int x = 1; x < N - 1; ++x) {\n            int j = x - 1;\n            double wgt = weight[j];\n            double v = vals[j];\n            wsum_left += wgt * v;\n            wsum2_left += wgt * v * v;\n            wgt_left += wgt;\n\n            double meanL = wsum_left / wgt_left;\n            double wgt_right = total_weight - wgt_left;\n            double wsum_right = total_wsum - wsum_left;\n            double meanR = wsum_right / wgt_right;\n            double wsum2_right = total_wsum2 - wsum2_left;\n\n            double sseL = wsum2_left - 2.0 * meanL * wsum_left + meanL * meanL * wgt_left;\n            double sseR = wsum2_right - 2.0 * meanR * wsum_right + meanR * meanR * wgt_right;\n            double sse = sseL + sseR;\n\n            if (sse < best_sse) {\n                best_sse = sse;\n                best_x = x;\n                best_meanL = meanL;\n                best_meanR = meanR;\n            }\n        }\n\n        double split_meanL = (best_x == -1) ? mean_all : best_meanL;\n        double split_meanR = (best_x == -1) ? mean_all : best_meanR;\n        int x_split = (best_x == -1) ? N - 1 : best_x;\n\n        for (int j = 0; j < N - 1; ++j) {\n            int e = edge_idx_horiz(i, j);\n            double target = (j < x_split) ? split_meanL : split_meanR;\n            w[e] += lr_soft * (target - w[e]);\n        }\n    }\n}\n\nvoid soft_segment_cols(vector<double>& w, const vector<int>& cnt, double lr_soft) {\n    for (int j = 0; j < N; ++j) {\n        int total_cnt = 0;\n        for (int i = 0; i < N - 1; ++i) total_cnt += cnt[edge_idx_vert(i, j)];\n        if (total_cnt < 20) continue;\n\n        vector<double> vals(N - 1);\n        vector<double> weight(N - 1);\n        double total_weight = 0.0, total_wsum = 0.0, total_wsum2 = 0.0;\n        for (int i = 0; i < N - 1; ++i) {\n            int e = edge_idx_vert(i, j);\n            vals[i] = w[e];\n            double wgt = cnt[e] + 1.0;\n            weight[i] = wgt;\n            total_weight += wgt;\n            total_wsum += wgt * vals[i];\n            total_wsum2 += wgt * vals[i] * vals[i];\n        }\n\n        double mean_all = total_wsum / total_weight;\n        double base_sse = total_wsum2 - 2.0 * mean_all * total_wsum + mean_all * mean_all * total_weight;\n        double best_sse = base_sse;\n        int best_x = -1;\n        double best_meanL = mean_all, best_meanR = mean_all;\n\n        double wsum_left = 0.0, wsum2_left = 0.0, wgt_left = 0.0;\n        for (int x = 1; x < N - 1; ++x) {\n            int i = x - 1;\n            double wgt = weight[i];\n            double v = vals[i];\n            wsum_left += wgt * v;\n            wsum2_left += wgt * v * v;\n            wgt_left += wgt;\n\n            double meanL = wsum_left / wgt_left;\n            double wgt_right = total_weight - wgt_left;\n            double wsum_right = total_wsum - wsum_left;\n            double meanR = wsum_right / wgt_right;\n            double wsum2_right = total_wsum2 - wsum2_left;\n\n            double sseL = wsum2_left - 2.0 * meanL * wsum_left + meanL * meanL * wgt_left;\n            double sseR = wsum2_right - 2.0 * meanR * wsum_right + meanR * meanR * wgt_right;\n            double sse = sseL + sseR;\n\n            if (sse < best_sse) {\n                best_sse = sse;\n                best_x = x;\n                best_meanL = meanL;\n                best_meanR = meanR;\n            }\n        }\n\n        double split_meanL = (best_x == -1) ? mean_all : best_meanL;\n        double split_meanR = (best_x == -1) ? mean_all : best_meanR;\n        int y_split = (best_x == -1) ? N - 1 : best_x;\n\n        for (int i = 0; i < N - 1; ++i) {\n            int e = edge_idx_vert(i, j);\n            double target = (i < y_split) ? split_meanL : split_meanR;\n            w[e] += lr_soft * (target - w[e]);\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    vector<double> w(E, 5000.0);\n    vector<double> w_plan = w;\n    vector<int> cnt(E, 0);\n    vector<double> row_h_mean(N, 5000.0);\n    vector<double> col_v_mean(N, 5000.0);\n\n    mt19937 rng(12345);\n\n    double alpha_explore = 2000.0;\n    double base_lr = 800.0;\n    double reg_coeff = 0.001;      // slightly increased from 0.0005\n    double rho = 0.05;\n\n    auto clamp_w = [](double v) { return max(1000.0, min(9000.0, v)); };\n\n    auto recompute_means = [&]() {\n        for (int i = 0; i < N; ++i) {\n            double s = 0;\n            for (int j = 0; j < N - 1; ++j) s += w[edge_idx_horiz(i, j)];\n            row_h_mean[i] = s / (N - 1);\n        }\n        for (int j = 0; j < N; ++j) {\n            double s = 0;\n            for (int i = 0; i < N - 1; ++i) s += w[edge_idx_vert(i, j)];\n            col_v_mean[j] = s / (N - 1);\n        }\n    };\n\n    for (int k = 0; k < 1000; ++k) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n\n        vector<int> path_edges;\n        string moves = dijkstra(si, sj, ti, tj, w_plan, cnt, alpha_explore, rng, path_edges);\n        cout << moves << endl;  // flush\n\n        int obs;\n        cin >> obs;\n\n        double pred = 0;\n        for (int e : path_edges) pred += w[e];\n\n        double lr_decay = 1.0 / (1.0 + k * 0.005);\n        double lr_abs = base_lr / (pred + 1.0) * lr_decay;\n\n        for (int e : path_edges) {\n            double grad = pred - obs;\n            double mean = (e < H_EDGES) ? row_h_mean[e / (N - 1)] : col_v_mean[(e - H_EDGES) % N];\n            double reg = w[e] - mean;\n            w[e] -= lr_abs * grad + reg_coeff * reg;\n            w[e] = clamp_w(w[e]);\n            cnt[e]++;\n        }\n\n        recompute_means();\n\n        // Soft segmentation: gently push towards piecewise constant structure\n        if (k >= 30) {\n            double lr_soft = min(0.12, 0.00012 * (k - 30));  // ramps up slowly\n            soft_segment_rows(w, cnt, lr_soft);\n            soft_segment_cols(w, cnt, lr_soft);\n            // reclamp just in case\n            for (int e = 0; e < E; ++e) w[e] = clamp_w(w[e]);\n            recompute_means();\n        }\n\n        // Update planning weights with exponential moving average\n        for (int e = 0; e < E; ++e)\n            w_plan[e] = (1 - rho) * w_plan[e] + rho * w[e];\n\n        // Exploration decay\n        alpha_explore = max(0.0, alpha_explore - 2.0);\n\n        // Periodic hard reset using the estimated segment structure\n        if ((k + 1) % 100 == 0 && k >= 99) {\n            hard_segment_rows(w, cnt);\n            hard_segment_cols(w, cnt);\n            recompute_means();\n            for (int e = 0; e < E; ++e) {\n                w[e] = clamp_w(w[e]);\n                w_plan[e] = w[e];   // fully adopt the cleaned model\n            }\n        }\n    }\n\n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n#include <cstring>\n#include <chrono>\n\nusing namespace std;\nusing namespace std::chrono;\n\nconstexpr int N = 20;               // grid size\nconstexpr int LETTERS = 8;\nconst char letters[LETTERS] = {'A','B','C','D','E','F','G','H'};\n\n// ---- random number generator ----\nstruct XorShift {\n    uint32_t x;\n    XorShift(uint32_t seed) : x(seed) {}\n    uint32_t next() {\n        x ^= x << 13;\n        x ^= x >> 17;\n        x ^= x << 5;\n        return x;\n    }\n    int nextInt(int max) {        // [0, max)\n        return next() % max;\n    }\n    double nextDouble() {         // [0, 1)\n        return (next() >> 8) * 0x1p-24;\n    }\n};\n\n// ---- global problem data ----\nint M;\nvector<string> strs;\nvector<int> len;\n\n// ---- incremental match structures ----\nvector<int> h_match;   // [i*N*N + r*N + start]\nvector<int> v_match;   // [i*N*N + c*N + start]\nvector<int> h_count;   // [i*N + r]   how many starts in row r give full match\nvector<int> v_count;   // [i*N + c]\nvector<int> s_count;   // [i]         number of occurrences of string i in grid\nint c_total = 0;       // number of fully matched strings\nint d_total = 0;       // number of '.' cells\nchar grid[N][N];\n\n// ---- score (normalised to [0,2]) ----\ndouble norm_score(int c, int d) {\n    if (c < M) return (double)c / M;                 // max < 1\n    return (2.0 * N * N) / (2.0 * N * N - d);        // max 2 when d=N*N\n}\n\n// ---- rebuild all incremental structures from scratch ----\nvoid rebuild_all() {\n    h_match.assign(M * N * N, 0);\n    v_match.assign(M * N * N, 0);\n    h_count.assign(M * N, 0);\n    v_count.assign(M * N, 0);\n    s_count.assign(M, 0);\n    c_total = 0;\n    d_total = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (grid[i][j] == '.') ++d_total;\n\n    for (int i = 0; i < M; ++i) {\n        int L = len[i];\n        const string& s = strs[i];\n        // horizontal\n        for (int r = 0; r < N; ++r) {\n            for (int start = 0; start < N; ++start) {\n                int cnt = 0;\n                for (int pos = 0; pos < L; ++pos)\n                    if (grid[r][(start+pos)%N] == s[pos]) ++cnt;\n                h_match[i*N*N + r*N + start] = cnt;\n                if (cnt == L) {\n                    ++h_count[i*N + r];\n                    ++s_count[i];\n                }\n            }\n        }\n        // vertical\n        for (int c = 0; c < N; ++c) {\n            for (int start = 0; start < N; ++start) {\n                int cnt = 0;\n                for (int pos = 0; pos < L; ++pos)\n                    if (grid[(start+pos)%N][c] == s[pos]) ++cnt;\n                v_match[i*N*N + c*N + start] = cnt;\n                if (cnt == L) {\n                    ++v_count[i*N + c];\n                    ++s_count[i];\n                }\n            }\n        }\n        if (s_count[i] > 0) ++c_total;\n    }\n}\n\n// ---- change one cell, update all incremental data ----\nvoid set_cell(int r, int c, char nc) {\n    char oc = grid[r][c];\n    if (oc == nc) return;\n\n    // dots counter\n    if (oc == '.') --d_total;\n    if (nc == '.') ++d_total;\n\n    for (int i = 0; i < M; ++i) {\n        int L = len[i];\n        const string& s = strs[i];\n\n        // ----- horizontal -----\n        int h_base = i * N * N + r * N;\n        int h_cnt_base = i * N + r;\n        for (int off = 0; off < L; ++off) {\n            int start = (c - off + N) % N;\n            int idx = h_base + start;\n            bool oc_eq = (oc == s[off]);\n            bool nc_eq = (nc == s[off]);\n            if (oc_eq == nc_eq) continue;\n            if (oc_eq) {\n                --h_match[idx];\n                if (h_match[idx] == L-1) {\n                    --h_count[h_cnt_base];\n                    --s_count[i];\n                    if (s_count[i] == 0) --c_total;\n                }\n            } else {\n                ++h_match[idx];\n                if (h_match[idx] == L) {\n                    ++h_count[h_cnt_base];\n                    ++s_count[i];\n                    if (s_count[i] == 1) ++c_total;\n                }\n            }\n        }\n\n        // ----- vertical -----\n        int v_base = i * N * N + c * N;\n        int v_cnt_base = i * N + c;\n        for (int off = 0; off < L; ++off) {\n            int start = (r - off + N) % N;\n            int idx = v_base + start;\n            bool oc_eq = (oc == s[off]);\n            bool nc_eq = (nc == s[off]);\n            if (oc_eq == nc_eq) continue;\n            if (oc_eq) {\n                --v_match[idx];\n                if (v_match[idx] == L-1) {\n                    --v_count[v_cnt_base];\n                    --s_count[i];\n                    if (s_count[i] == 0) --c_total;\n                }\n            } else {\n                ++v_match[idx];\n                if (v_match[idx] == L) {\n                    ++v_count[v_cnt_base];\n                    ++s_count[i];\n                    if (s_count[i] == 1) ++c_total;\n                }\n            }\n        }\n    }\n    grid[r][c] = nc;\n}\n\n// ---- brute force count of matched strings (used during greedy) ----\nint count_matched(const char g[N][N]) {\n    int cnt = 0;\n    for (int i = 0; i < M; ++i) {\n        const string& s = strs[i];\n        int L = len[i];\n        bool found = false;\n        for (int r = 0; r < N && !found; ++r) {\n            for (int start = 0; start < N && !found; ++start) {\n                bool ok = true;\n                for (int pos = 0; pos < L; ++pos)\n                    if (g[r][(start+pos)%N] != s[pos]) { ok = false; break; }\n                if (ok) found = true;\n            }\n        }\n        for (int c = 0; c < N && !found; ++c) {\n            for (int start = 0; start < N && !found; ++start) {\n                bool ok = true;\n                for (int pos = 0; pos < L; ++pos)\n                    if (g[(start+pos)%N][c] != s[pos]) { ok = false; break; }\n                if (ok) found = true;\n            }\n        }\n        if (found) ++cnt;\n    }\n    return cnt;\n}\n\n// ---- greedy construction with random orders ----\nvoid greedy_construction(char best_grid[N][N], int& best_c, XorShift& rng,\n                         double time_limit, steady_clock::time_point start_time) {\n    auto get_time = [&]() {\n        return duration<double>(steady_clock::now() - start_time).count();\n    };\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n\n    char cur[N][N];\n    best_c = -1;\n    int best_d = 0;\n\n    struct Placement {\n        int ori;      // 0 horizontal, 1 vertical\n        int rc;       // row or column index\n        int start;\n        int overlap;\n    };\n    vector<Placement> valid;\n    valid.reserve(800);\n\n    while (get_time() < time_limit) {\n        memset(cur, '.', sizeof(cur));\n        // randomise order\n        for (int i = M-1; i > 0; --i) swap(order[i], order[rng.nextInt(i+1)]);\n\n        for (int idx : order) {\n            const string& s = strs[idx];\n            int L = len[idx];\n            valid.clear();\n\n            // horizontal\n            for (int r = 0; r < N; ++r) {\n                for (int start = 0; start < N; ++start) {\n                    int overlap = 0;\n                    bool ok = true;\n                    for (int pos = 0; pos < L; ++pos) {\n                        int col = (start + pos) % N;\n                        char cell = cur[r][col];\n                        if (cell != '.' && cell != s[pos]) { ok = false; break; }\n                        if (cell != '.') ++overlap;\n                    }\n                    if (ok) valid.push_back({0, r, start, overlap});\n                }\n            }\n            // vertical\n            for (int c = 0; c < N; ++c) {\n                for (int start = 0; start < N; ++start) {\n                    int overlap = 0;\n                    bool ok = true;\n                    for (int pos = 0; pos < L; ++pos) {\n                        int row = (start + pos) % N;\n                        char cell = cur[row][c];\n                        if (cell != '.' && cell != s[pos]) { ok = false; break; }\n                        if (cell != '.') ++overlap;\n                    }\n                    if (ok) valid.push_back({1, c, start, overlap});\n                }\n            }\n\n            if (valid.empty()) continue;\n            // prefer placements with highest overlap\n            int max_overlap = -1;\n            for (auto& p : valid) if (p.overlap > max_overlap) max_overlap = p.overlap;\n            vector<Placement*> candidates;\n            for (auto& p : valid) if (p.overlap == max_overlap) candidates.push_back(&p);\n            Placement& chosen = *candidates[rng.nextInt(candidates.size())];\n\n            if (chosen.ori == 0) {\n                int r = chosen.rc, st = chosen.start;\n                for (int pos = 0; pos < L; ++pos) cur[r][(st+pos)%N] = s[pos];\n            } else {\n                int c = chosen.rc, st = chosen.start;\n                for (int pos = 0; pos < L; ++pos) cur[(st+pos)%N][c] = s[pos];\n            }\n        }\n\n        int actual_c = count_matched(cur);\n        int actual_d = 0;\n        for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) if (cur[i][j] == '.') ++actual_d;\n        if (actual_c > best_c || (actual_c == best_c && actual_d > best_d)) {\n            best_c = actual_c;\n            best_d = actual_d;\n            memcpy(best_grid, cur, sizeof(cur));\n            if (best_c == M) break;   // all strings are already matched\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false); cin.tie(0);\n    auto start_time = steady_clock::now();\n    auto get_time = [&]() {\n        return duration<double>(steady_clock::now() - start_time).count();\n    };\n\n    // ----- read input -----\n    int dummy_n;\n    cin >> dummy_n >> M;\n    // dummy_n is always 20, we ignore it\n    strs.resize(M);\n    len.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> strs[i];\n        len[i] = strs[i].size();\n    }\n\n    // ----- random generator -----\n    auto seed = steady_clock::now().time_since_epoch().count();\n    XorShift rng((uint32_t)(seed & 0xFFFFFFFF));\n\n    // ----- greedy phase -----\n    double greedy_time = 0.4;\n    char best_grid[N][N];\n    int greedy_c;\n    greedy_construction(best_grid, greedy_c, rng, greedy_time, start_time);\n\n    // ----- prepare for SA -----\n    memcpy(grid, best_grid, sizeof(grid));\n    rebuild_all();                        // initialise incremental data\n\n    double best_norm = norm_score(c_total, d_total);\n    char best_sa_grid[N][N];\n    memcpy(best_sa_grid, grid, sizeof(grid));\n\n    // ----- simulated annealing -----\n    double sa_start = get_time();\n    double sa_limit = 2.8;               // leave time for final dot optimisation\n    double T_start = 0.2;\n    double T_end   = 0.0002;\n    int sa_steps = 0;\n\n    while (get_time() < sa_limit) {\n        double elapsed = get_time() - sa_start;\n        double progress = elapsed / (sa_limit - sa_start);   // roughly [0,1]\n        double T = T_start * pow(T_end / T_start, progress);\n\n        int r = rng.nextInt(N);\n        int c = rng.nextInt(N);\n        char cur_char = grid[r][c];\n        char nxt_char;\n        if (rng.nextInt(9) == 0) nxt_char = '.';\n        else nxt_char = letters[rng.nextInt(LETTERS)];\n        if (nxt_char == cur_char) continue;\n\n        double old_norm = norm_score(c_total, d_total);\n        set_cell(r, c, nxt_char);\n        double new_norm = norm_score(c_total, d_total);\n        double delta = new_norm - old_norm;\n\n        if (delta >= 0) {\n            // improvement\n            if (new_norm > best_norm) {\n                best_norm = new_norm;\n                memcpy(best_sa_grid, grid, sizeof(grid));\n            }\n        } else {\n            double prob = exp(delta / T);\n            if (rng.nextDouble() < prob) {\n                // keep change\n            } else {\n                set_cell(r, c, cur_char);   // revert\n            }\n        }\n        ++sa_steps;\n    }\n    // restore best solution found during SA\n    memcpy(grid, best_sa_grid, sizeof(grid));\n    rebuild_all();\n\n    // ----- final dot maximisation (only when all strings are matched) -----\n    if (c_total == M) {\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    if (grid[r][c] == '.') continue;\n                    char old = grid[r][c];\n                    set_cell(r, c, '.');\n                    if (c_total == M) {\n                        changed = true;\n                    } else {\n                        set_cell(r, c, old);\n                    }\n                }\n            }\n        }\n        // update best grid\n        memcpy(best_sa_grid, grid, sizeof(grid));\n    }\n\n    // ----- output -----\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) cout << best_sa_grid[i][j];\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int INF = 1e9;\n\n// Dial's algorithm for directed graph with small integer weights (5..9)\nvoid dial_shortest_path(int src,\n                        const vector<vector<pair<int, int>>> &adj,\n                        vector<int> &dist,\n                        vector<int> &prev) {\n    int n = (int)adj.size();\n    dist.assign(n, INF);\n    prev.assign(n, -1);\n    dist[src] = 0;\n    vector<queue<int>> buckets(10);\n    buckets[0].push(src);\n    int cur_d = 0, max_d = 0;\n    while (cur_d <= max_d) {\n        int idx = cur_d % 10;\n        if (!buckets[idx].empty()) {\n            int u = buckets[idx].front();\n            buckets[idx].pop();\n            if (dist[u] < cur_d) continue;\n            for (auto &p : adj[u]) {\n                int v = p.first, w = p.second;\n                int nd = cur_d + w;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    prev[v] = u;\n                    buckets[nd % 10].push(v);\n                    if (nd > max_d) max_d = nd;\n                }\n            }\n        } else {\n            cur_d++;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int N, si, sj;\n    cin >> N >> si >> sj;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n\n    // map cells to IDs\n    vector<vector<int>> id(N, vector<int>(N, -1));\n    vector<pair<int, int>> cells;\n    vector<int> cell_cost;\n    int r = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (grid[i][j] != '#') {\n                id[i][j] = r++;\n                cells.push_back({i, j});\n                cell_cost.push_back(grid[i][j] - '0');\n            }\n\n    // adjacency (directed, cost = weight of target cell)\n    vector<vector<pair<int, int>>> adj(r);\n    const int di[4] = {-1, 1, 0, 0};\n    const int dj[4] = {0, 0, -1, 1};\n    for (int u = 0; u < r; ++u) {\n        int i = cells[u].first, j = cells[u].second;\n        for (int d = 0; d < 4; ++d) {\n            int ni = i + di[d], nj = j + dj[d];\n            if (ni >= 0 && ni < N && nj >= 0 && nj < N && id[ni][nj] != -1) {\n                int v = id[ni][nj];\n                adj[u].push_back({v, cell_cost[v]});\n            }\n        }\n    }\n\n    // horizontal segments\n    vector<int> h_id(r, -1);\n    int H = 0;\n    vector<int> h_ep1, h_ep2;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N;) {\n            if (id[i][j] != -1) {\n                int st = j;\n                while (j < N && id[i][j] != -1) ++j;\n                int en = j - 1;\n                int u1 = id[i][st];\n                int u2 = id[i][en];\n                h_ep1.push_back(u1);\n                h_ep2.push_back(u2);\n                for (int jj = st; jj <= en; ++jj) h_id[id[i][jj]] = H;\n                ++H;\n            } else {\n                ++j;\n            }\n        }\n    }\n\n    // vertical segments\n    vector<int> v_id(r, -1);\n    int V = 0;\n    vector<int> v_ep1, v_ep2;\n    for (int j = 0; j < N; ++j) {\n        for (int i = 0; i < N;) {\n            if (id[i][j] != -1) {\n                int st = i;\n                while (i < N && id[i][j] != -1) ++i;\n                int en = i - 1;\n                int u1 = id[st][j];\n                int u2 = id[en][j];\n                v_ep1.push_back(u1);\n                v_ep2.push_back(u2);\n                for (int ii = st; ii <= en; ++ii) v_id[id[ii][j]] = V;\n                ++V;\n            } else {\n                ++i;\n            }\n        }\n    }\n\n    int S = H + V; // total segments\n\n    // candidate waypoints: start cell + all segment endpoints\n    int start_cell = id[si][sj];\n    set<int> cand_set;\n    cand_set.insert(start_cell);\n    for (int u : h_ep1) cand_set.insert(u);\n    for (int u : h_ep2) cand_set.insert(u);\n    for (int u : v_ep1) cand_set.insert(u);\n    for (int u : v_ep2) cand_set.insert(u);\n    vector<int> P(cand_set.begin(), cand_set.end());\n    int P_sz = (int)P.size();\n\n    // which segments does each candidate cover\n    vector<vector<int>> seg_cover(P_sz);\n    for (int i = 0; i < P_sz; ++i) {\n        int u = P[i];\n        seg_cover[i].push_back(h_id[u]);\n        seg_cover[i].push_back(v_id[u]);\n    }\n\n    // Dijkstra from start (to use as tie\u2011breaker in set cover)\n    vector<int> dist_start, prev_dummy;\n    dial_shortest_path(start_cell, adj, dist_start, prev_dummy);\n\n    int start_idx = -1;\n    for (int i = 0; i < P_sz; ++i)\n        if (P[i] == start_cell) {\n            start_idx = i;\n            break;\n        }\n\n    // greedy set cover (tie\u2011break by distance from start)\n    vector<bool> cov_seg(S, false);\n    cov_seg[h_id[start_cell]] = true;\n    cov_seg[v_id[start_cell]] = true;\n    int uncovered = 0;\n    for (bool b : cov_seg) if (!b) ++uncovered;\n\n    vector<int> selected;\n    selected.push_back(start_idx);\n    vector<bool> in_selected(P_sz, false);\n    in_selected[start_idx] = true;\n\n    while (uncovered > 0) {\n        int best_gain = 0, best_idx = -1, best_dist = INF;\n        for (int i = 0; i < P_sz; ++i) {\n            if (in_selected[i]) continue;\n            int gain = 0;\n            for (int seg : seg_cover[i])\n                if (!cov_seg[seg]) ++gain;\n            if (gain == 0) continue;\n            int d = dist_start[P[i]];\n            if (gain > best_gain || (gain == best_gain && d < best_dist)) {\n                best_gain = gain;\n                best_dist = d;\n                best_idx = i;\n            }\n        }\n        if (best_idx == -1) break;\n        selected.push_back(best_idx);\n        in_selected[best_idx] = true;\n        for (int seg : seg_cover[best_idx]) {\n            if (!cov_seg[seg]) {\n                cov_seg[seg] = true;\n                --uncovered;\n            }\n        }\n    }\n\n    // remove redundant waypoints (simple coverage check)\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        for (size_t i = 0; i < selected.size(); ++i) {\n            if (selected[i] == start_idx) continue;\n            vector<bool> cov(S, false);\n            for (size_t j = 0; j < selected.size(); ++j)\n                if (i != j)\n                    for (int seg : seg_cover[selected[j]]) cov[seg] = true;\n            bool needed = false;\n            for (int seg : seg_cover[selected[i]])\n                if (!cov[seg]) { needed = true; break; }\n            if (!needed) {\n                selected.erase(selected.begin() + i);\n                changed = true;\n                break;\n            }\n        }\n    }\n\n    // final waypoint list\n    vector<int> W;\n    for (int idx : selected) W.push_back(P[idx]);\n    int K = (int)W.size();\n\n    // ensure start is at index 0\n    auto it_start = find(W.begin(), W.end(), start_cell);\n    if (it_start != W.end()) swap(W[0], *it_start);\n\n    if (K == 1) {\n        cout << \"\" << '\\n';\n        return 0;\n    }\n\n    // distance matrix between waypoints\n    vector<vector<int>> D(K, vector<int>(K, 0));\n    for (int i = 0; i < K; ++i) {\n        vector<int> dist, prv;\n        dial_shortest_path(W[i], adj, dist, prv);\n        for (int j = 0; j < K; ++j) D[i][j] = dist[W[j]];\n    }\n\n    // initial tour: cheapest insertion\n    vector<int> tour(K);\n    vector<bool> in_tour(K, false);\n    tour[0] = 0;\n    in_tour[0] = true;\n    for (int t = 1; t < K; ++t) {\n        int best_node = -1, best_pos = -1, best_inc = INF;\n        for (int v = 1; v < K; ++v) {\n            if (in_tour[v]) continue;\n            for (int i = 0; i < t; ++i) {\n                int u = tour[i];\n                int w = tour[(i + 1) % t];\n                int inc = D[u][v] + D[v][w] - D[u][w];\n                if (inc < best_inc) {\n                    best_inc = inc;\n                    best_node = v;\n                    best_pos = i + 1;\n                }\n            }\n        }\n        for (int i = t; i > best_pos; --i) tour[i] = tour[i - 1];\n        tour[best_pos] = best_node;\n        in_tour[best_node] = true;\n    }\n\n    // Or-opt local search (relocation) \u2013 limited to moderate K\n    if (K <= 400) {\n        int cur_cost = 0;\n        for (int i = 0; i < K; ++i) cur_cost += D[tour[i]][tour[(i + 1) % K]];\n        while (true) {\n            int best_delta = 0;\n            int best_i = -1, best_j = -1;\n            for (int i = 1; i < K; ++i) { // never move start\n                int prev = (i - 1 + K) % K;\n                int next = (i + 1) % K;\n                int node = tour[i];\n                for (int j = 0; j < K; ++j) {\n                    if (j == i || j == i - 1) continue;\n                    int nextj = (j + 1) % K;\n                    int delta =\n                        -D[tour[prev]][node] - D[node][tour[next]]\n                        -D[tour[j]][tour[nextj]]\n                        +D[tour[prev]][tour[next]]\n                        +D[tour[j]][node] + D[node][tour[nextj]];\n                    if (delta < best_delta) {\n                        best_delta = delta;\n                        best_i = i;\n                        best_j = j;\n                    }\n                }\n            }\n            if (best_delta >= 0) break;\n            int node = tour[best_i];\n            if (best_j > best_i) {\n                tour.erase(tour.begin() + best_i);\n                tour.insert(tour.begin() + best_j, node);\n            } else {\n                tour.erase(tour.begin() + best_i);\n                tour.insert(tour.begin() + best_j + 1, node);\n            }\n            cur_cost += best_delta;\n        }\n    }\n\n    // produce final output string\n    string ans;\n    ans.reserve(1'000'000);\n    for (int step = 0; step < K; ++step) {\n        int u = W[tour[step]];\n        int v = W[tour[(step + 1) % K]];\n        vector<int> dist, prv;\n        dial_shortest_path(u, adj, dist, prv);\n        vector<int> path;\n        for (int cur = v; cur != u; cur = prv[cur]) path.push_back(cur);\n        path.push_back(u);\n        reverse(path.begin(), path.end());\n        for (size_t i = 0; i + 1 < path.size(); ++i) {\n            int ci = cells[path[i]].first, cj = cells[path[i]].second;\n            int ni = cells[path[i + 1]].first, nj = cells[path[i + 1]].second;\n            if (ni < ci) ans.push_back('U');\n            else if (ni > ci) ans.push_back('D');\n            else if (nj < cj) ans.push_back('L');\n            else ans.push_back('R');\n        }\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <set>\n#include <climits>\n#include <cmath>\nusing namespace std;\n\nstruct Obs {\n    int task;\n    int L;\n    int U;\n};\n\nint N, M, K, R;\nvector<vector<int>> d;           // task difficulties\nvector<vector<int>> out_edges;   // dependents of each task\nvector<int> indegree;            // original indegree\nvector<int> height;              // longest path to sink (including itself)\nint max_height;\n\nvector<int> task_status;         // 0: not started, 1: in progress, 2: completed\nvector<int> req_remaining;       // number of unfinished prerequisites\nvector<int> worker_task;         // which task worker is doing (-1 = free)\nvector<int> worker_start;        // day the worker started current task\nvector<vector<Obs>> obs;         // observations per worker\nvector<vector<int>> LB, UB;      // skill bounds per worker\n\n// update skill bounds for worker j using all observations\nvoid update_bounds(int j) {\n    vector<int> &lb = LB[j];\n    vector<int> &ub = UB[j];\n    fill(lb.begin(), lb.end(), 0);\n    fill(ub.begin(), ub.end(), 200);\n\n    bool changed = true;\n    int iter = 0;\n    while (changed && iter < 10) {\n        changed = false;\n        iter++;\n        for (const auto &ob : obs[j]) {\n            int ti = ob.task;\n            int L = ob.L;\n            int U = ob.U;\n            // Update lower bounds using upper bound U\n            for (int k = 0; k < K; k++) {\n                int new_lb = max(lb[k], d[ti][k] - U);\n                if (new_lb > ub[k]) new_lb = ub[k]; // keep consistent\n                if (new_lb > lb[k]) {\n                    lb[k] = new_lb;\n                    changed = true;\n                }\n            }\n            // Precompute S_others_max (max possible deficit from other skills)\n            vector<int> S_others_max(K, 0);\n            for (int k = 0; k < K; k++) {\n                int sum = 0;\n                for (int k2 = 0; k2 < K; k2++) {\n                    if (k2 == k) continue;\n                    sum += max(0, d[ti][k2] - lb[k2]);\n                }\n                S_others_max[k] = sum;\n            }\n            // Update upper bounds using lower bound L\n            for (int k = 0; k < K; k++) {\n                if (L > S_others_max[k]) {\n                    int new_ub = d[ti][k] - (L - S_others_max[k]);\n                    if (new_ub < lb[k]) new_ub = lb[k]; // keep consistent\n                    if (new_ub < ub[k]) {\n                        ub[k] = new_ub;\n                        changed = true;\n                    }\n                }\n            }\n        }\n    }\n}\n\n// estimate days needed for worker w to finish task idx\nint estimate_t(int worker, int task) {\n    double r = 0.0;\n    if (max_height > 1) {\n        r = (double)(height[task] - 1) / (max_height - 1);\n    }\n    int w_val = 0;\n    for (int k = 0; k < K; k++) {\n        double s_blend = LB[worker][k] + (UB[worker][k] - LB[worker][k]) * (1.0 - r);\n        int s_int = (int)round(s_blend);\n        int def = d[task][k] - s_int;\n        if (def > 0) w_val += def;\n    }\n    return (w_val == 0) ? 1 : w_val;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> M >> K >> R;\n    d.resize(N, vector<int>(K));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < K; j++) {\n            cin >> d[i][j];\n        }\n    }\n    out_edges.resize(N);\n    indegree.assign(N, 0);\n    for (int i = 0; i < R; i++) {\n        int u, v;\n        cin >> u >> v;\n        u--; v--;\n        out_edges[u].push_back(v);\n        indegree[v]++;\n    }\n    \n    // Compute height = length of longest path to a sink (inclusive)\n    height.resize(N);\n    max_height = 0;\n    for (int i = N - 1; i >= 0; i--) {\n        int best = 0;\n        for (int v : out_edges[i]) {\n            best = max(best, height[v]);\n        }\n        height[i] = best + 1;\n        max_height = max(max_height, height[i]);\n    }\n    \n    // Initialize state\n    task_status.assign(N, 0);\n    req_remaining = indegree;\n    worker_task.assign(M, -1);\n    worker_start.assign(M, -1);\n    obs.resize(M);\n    LB.assign(M, vector<int>(K, 0));\n    UB.assign(M, vector<int>(K, 200));\n    \n    int day = 1;\n    int completed = 0;\n    \n    while (true) {\n        vector<int> free_workers;\n        for (int j = 0; j < M; j++) {\n            if (worker_task[j] == -1) free_workers.push_back(j);\n        }\n        vector<int> ready_tasks;\n        for (int i = 0; i < N; i++) {\n            if (task_status[i] == 0 && req_remaining[i] == 0) {\n                ready_tasks.push_back(i);\n            }\n        }\n        \n        // Sort by height descending (critical first)\n        sort(ready_tasks.begin(), ready_tasks.end(), [&](int a, int b) {\n            return height[a] > height[b];\n        });\n        \n        // Only consider a limited number of highest priority tasks\n        int max_consider = max((int)free_workers.size() * 3, 40);\n        if ((int)ready_tasks.size() > max_consider) {\n            ready_tasks.resize(max_consider);\n        }\n        \n        vector<pair<int,int>> assignments;\n        set<int> used;\n        for (int task : ready_tasks) {\n            int best_w = -1;\n            int best_t = INT_MAX;\n            for (int w : free_workers) {\n                if (used.count(w)) continue;\n                int t_est = estimate_t(w, task);\n                if (t_est < best_t) {\n                    best_t = t_est;\n                    best_w = w;\n                }\n            }\n            if (best_w != -1) {\n                assignments.push_back({best_w, task});\n                used.insert(best_w);\n                if (used.size() == free_workers.size()) break;\n            }\n        }\n        \n        // Output assignments\n        cout << assignments.size();\n        for (auto &p : assignments) {\n            cout << \" \" << p.first + 1 << \" \" << p.second + 1;\n        }\n        cout << \"\\n\";\n        cout.flush();\n        \n        // Update state for newly started tasks\n        for (auto &p : assignments) {\n            int w = p.first;\n            int task = p.second;\n            worker_task[w] = task;\n            worker_start[w] = day;\n            task_status[task] = 1;\n        }\n        \n        // Read completions\n        int n;\n        cin >> n;\n        if (n == -1) {\n            break;\n        }\n        vector<int> finished_workers(n);\n        for (int i = 0; i < n; i++) {\n            cin >> finished_workers[i];\n            finished_workers[i]--;\n        }\n        \n        // Process each completion\n        for (int w : finished_workers) {\n            int task = worker_task[w];\n            int start = worker_start[w];\n            int t_actual = day - start + 1;\n            int L, U;\n            if (t_actual == 1) {\n                L = 0;\n                U = 4;\n            } else {\n                L = max(1, t_actual - 3);\n                U = t_actual + 3;\n            }\n            obs[w].push_back({task, L, U});\n            \n            task_status[task] = 2;\n            completed++;\n            for (int v : out_edges[task]) {\n                req_remaining[v]--;\n            }\n            worker_task[w] = -1;\n            worker_start[w] = -1;\n        }\n        \n        // Update skill bounds for workers who finished a task\n        for (int w : finished_workers) {\n            update_bounds(w);\n        }\n        \n        day++;\n        if (day > 2000) {\n            break;\n        }\n    }\n    \n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct InsertResult {\n    int cost, i, j;\n};\n\nint main() {\n    auto start = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration_cast<chrono::milliseconds>(\n                   chrono::steady_clock::now() - start)\n            .count();\n    };\n\n    // ---------- input ----------\n    const int N = 1000;\n    vector<int> ax(N), ay(N), cx(N), cy(N);\n    for (int i = 0; i < N; ++i)\n        cin >> ax[i] >> ay[i] >> cx[i] >> cy[i];\n\n    // ---------- coordinate mapping ----------\n    vector<int> X(2 * N + 1), Y(2 * N + 1);\n    X[0] = 400; Y[0] = 400;\n    for (int i = 0; i < N; ++i) {\n        X[2 * i + 1] = ax[i]; Y[2 * i + 1] = ay[i];\n        X[2 * i + 2] = cx[i]; Y[2 * i + 2] = cy[i];\n    }\n    int V = 2 * N + 1;\n\n    // ---------- precompute all distances ----------\n    vector<int> D(V * V);\n    for (int i = 0; i < V; ++i)\n        for (int j = 0; j < V; ++j)\n            D[i * V + j] = abs(X[i] - X[j]) + abs(Y[i] - Y[j]);\n\n    auto dist = [&](int u, int v) { return D[u * V + v]; };\n\n    // ---------- route cost ----------\n    auto calc_total = [&](const vector<int>& s) {\n        if (s.empty()) return 0;\n        int tot = dist(0, s[0]);\n        for (size_t i = 0; i + 1 < s.size(); ++i)\n            tot += dist(s[i], s[i + 1]);\n        tot += dist(s.back(), 0);\n        return tot;\n    };\n\n    // ---------- evaluate insertion of order o into sequence s ----------\n    auto eval_ins = [&](const vector<int>& s, int o) -> InsertResult {\n        int L = s.size();\n        int P = 2 * o + 1, D = 2 * o + 2;\n        int best_cost = INT_MAX, best_i = -1, best_j = -1;\n        for (int i = 0; i <= L; ++i) {\n            int prev_i = (i == 0 ? 0 : s[i - 1]);\n            int next_i = (i == L ? 0 : s[i]);\n            int base_i = dist(prev_i, next_i);\n            // consecutive P and D\n            int cost_pd = dist(prev_i, P) + dist(P, D) + dist(D, next_i) - base_i;\n            if (cost_pd < best_cost) {\n                best_cost = cost_pd;\n                best_i = best_j = i;\n            }\n            int inc_P = dist(prev_i, P) + dist(P, next_i) - base_i;\n            for (int j = i + 1; j <= L; ++j) {\n                int prev_j = s[j - 1];\n                int next_j = (j == L ? 0 : s[j]);\n                int inc_D = dist(prev_j, D) + dist(D, next_j) - dist(prev_j, next_j);\n                int cost = inc_P + inc_D;\n                if (cost < best_cost) {\n                    best_cost = cost;\n                    best_i = i;\n                    best_j = j;\n                }\n            }\n        }\n        return {best_cost, best_i, best_j};\n    };\n\n    // ---------- apply insertion to sequence ----------\n    auto apply_ins = [&](vector<int>& s, int o, int i, int j) {\n        int P = 2 * o + 1, D = 2 * o + 2;\n        vector<int> ns;\n        ns.reserve(s.size() + 2);\n        for (int pos = 0; pos <= (int)s.size(); ++pos) {\n            if (pos == i && pos == j) {\n                ns.push_back(P);\n                ns.push_back(D);\n            } else {\n                if (pos == i) ns.push_back(P);\n                if (pos == j) ns.push_back(D);\n            }\n            if (pos < (int)s.size()) ns.push_back(s[pos]);\n        }\n        s = move(ns);\n    };\n\n    auto remove_order_seq = [&](vector<int>& s, int o) {\n        int P = 2 * o + 1, D = 2 * o + 2;\n        s.erase(remove(s.begin(), s.end(), P), s.end());\n        s.erase(remove(s.begin(), s.end(), D), s.end());\n    };\n\n    // ---------- state ----------\n    vector<int> seq;\n    vector<bool> sel_flag(N, false);\n    vector<int> sel_orders;\n    int T = 0;\n\n    // ---------- initial construction (farthest insertion) ----------\n    for (int step = 0; step < 50; ++step) {\n        int best_o = -1, best_cost = -1;\n        InsertResult best_res;\n        for (int o = 0; o < N; ++o) {\n            if (sel_flag[o]) continue;\n            auto res = eval_ins(seq, o);\n            if (res.cost > best_cost) {\n                best_cost = res.cost;\n                best_o = o;\n                best_res = res;\n            }\n        }\n        apply_ins(seq, best_o, best_res.i, best_res.j);\n        sel_flag[best_o] = true;\n        sel_orders.push_back(best_o);\n    }\n    T = calc_total(seq);\n\n    // ---------- local search to improve the route ----------\n    auto improve_route = [&]() {\n        bool improved = true;\n        int pass = 0;\n        while (improved && pass < 10 && elapsed() < 1950) {\n            improved = false;\n            // 1) re\u2011insert whole order\n            for (int o : sel_orders) {\n                vector<int> temp_s = seq;\n                remove_order_seq(temp_s, o);\n                int T_wo = calc_total(temp_s);\n                auto res = eval_ins(temp_s, o);\n                int delta = T_wo + res.cost - T;\n                if (delta < 0) {\n                    seq = move(temp_s);\n                    apply_ins(seq, o, res.i, res.j);\n                    T = T_wo + res.cost;\n                    improved = true;\n                    break;\n                }\n            }\n            if (improved) continue;\n\n            // 2) relocate a single node (preserving precedence)\n            int L = seq.size();\n            for (int idx = 0; idx < L; ++idx) {\n                int node = seq[idx];\n                int o = (node - 1) / 2;\n                bool pickup = (node % 2 == 1);\n                int other_node = pickup ? node + 1 : node - 1;\n                int other_idx = -1;\n                for (int k = 0; k < L; ++k)\n                    if (seq[k] == other_node) { other_idx = k; break; }\n                vector<int> temp_s = seq;\n                temp_s.erase(temp_s.begin() + idx);\n                int other_temp = other_idx > idx ? other_idx - 1 : other_idx;\n                int best_delta = 0, best_pos = -1;\n                for (int pos = 0; pos <= (int)temp_s.size(); ++pos) {\n                    if (pickup && pos > other_temp) continue;\n                    if (!pickup && pos <= other_temp) continue;\n                    int prv = (pos == 0 ? 0 : temp_s[pos - 1]);\n                    int nxt = (pos == (int)temp_s.size() ? 0 : temp_s[pos]);\n                    int delta = dist(prv, node) + dist(node, nxt) - dist(prv, nxt);\n                    if (delta < best_delta) {\n                        best_delta = delta;\n                        best_pos = pos;\n                    }\n                }\n                if (best_delta < 0) {\n                    temp_s.insert(temp_s.begin() + best_pos, node);\n                    seq = move(temp_s);\n                    T += best_delta;\n                    improved = true;\n                    break;\n                }\n            }\n            if (improved) continue;\n\n            // 3) 2\u2011opt (reverse segment) with precedence check\n            vector<int> pos(2 * N + 1, -1);\n            for (int i = 0; i < L; ++i) pos[seq[i]] = i;\n            int best_delta = 0, best_i = -1, best_j = -1;\n            for (int i = 0; i < L; ++i) {\n                for (int j = i + 1; j < L; ++j) {\n                    bool feasible = true;\n                    for (int o : sel_orders) {\n                        int p = pos[2 * o + 1], d = pos[2 * o + 2];\n                        if (p >= i && p <= j && d >= i && d <= j) {\n                            feasible = false;\n                            break;\n                        }\n                    }\n                    if (!feasible) continue;\n                    int prev_i = (i == 0 ? 0 : seq[i - 1]);\n                    int next_j = (j == L - 1 ? 0 : seq[j + 1]);\n                    int delta = dist(prev_i, seq[j]) + dist(seq[i], next_j) -\n                                dist(prev_i, seq[i]) - dist(seq[j], next_j);\n                    if (delta < best_delta) {\n                        best_delta = delta;\n                        best_i = i;\n                        best_j = j;\n                    }\n                }\n            }\n            if (best_delta < 0) {\n                reverse(seq.begin() + best_i, seq.begin() + best_j + 1);\n                T += best_delta;\n                improved = true;\n            }\n            ++pass;\n        }\n    };\n\n    improve_route();\n\n    // ---------- simulated annealing ----------\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> rnd_idx(0, 49);\n    uniform_int_distribution<int> rnd_order(0, N - 1);\n    uniform_real_distribution<double> rnd_prob(0.0, 1.0);\n\n    auto best_seq = seq;\n    auto best_flag = sel_flag;\n    auto best_sel = sel_orders;\n    int best_T = T;\n\n    while (elapsed() < 1900) {\n        double temp = 300.0 * (1.0 - elapsed() / 2000.0) + 0.1;\n\n        int idx = rnd_idx(rng);\n        int o_sel = sel_orders[idx];\n        int o_unsel;\n        do { o_unsel = rnd_order(rng); } while (sel_flag[o_unsel]);\n\n        vector<int> temp_s = seq;\n        remove_order_seq(temp_s, o_sel);\n        int T_wo = calc_total(temp_s);\n        auto res = eval_ins(temp_s, o_unsel);\n        int delta = T_wo + res.cost - T;\n\n        if (delta < 0 || exp(-delta / temp) > rnd_prob(rng)) {\n            seq = move(temp_s);\n            apply_ins(seq, o_unsel, res.i, res.j);\n            T = T_wo + res.cost;\n            sel_flag[o_sel] = false;\n            sel_flag[o_unsel] = true;\n            sel_orders[idx] = o_unsel;\n\n            if (T < best_T) {\n                best_T = T;\n                best_seq = seq;\n                best_flag = sel_flag;\n                best_sel = sel_orders;\n            }\n        }\n    }\n\n    // ---------- final polish ----------\n    seq = best_seq; sel_flag = best_flag; sel_orders = best_sel; T = best_T;\n    best_T = T;\n    while (elapsed() < 1950) {\n        improve_route();\n        if (T < best_T) {\n            best_T = T;\n            best_seq = seq;\n            best_flag = sel_flag;\n            best_sel = sel_orders;\n        } else break;\n    }\n\n    // ---------- output ----------\n    sort(sel_orders.begin(), sel_orders.end());\n    cout << 50;\n    for (int o : sel_orders) cout << \" \" << o + 1;\n    cout << \"\\n\";\n    cout << seq.size() + 2;\n    cout << \" 400 400\";\n    for (int node : seq)\n        cout << \" \" << X[node] << \" \" << Y[node];\n    cout << \" 400 400\" << endl;\n\n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n#include <tuple>\n#include <climits>\n#include <cstdint>\n\nusing namespace std;\n\nstruct DSU {\n    vector<int> parent, sz;\n    int comps;\n    DSU(int n) : parent(n), sz(n, 1), comps(n) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    DSU(const DSU& other) : parent(other.parent), sz(other.sz), comps(other.comps) {}\n    int find(int x) {\n        while (parent[x] != x) {\n            parent[x] = parent[parent[x]];\n            x = parent[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        parent[b] = a;\n        sz[a] += sz[b];\n        --comps;\n        return true;\n    }\n    bool same(int a, int b) { return find(a) == find(b); }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\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) cin >> x[i] >> y[i];\n    \n    // Read edge endpoints\n    vector<int> U(M), V(M);\n    for (int i = 0; i < M; ++i) cin >> U[i] >> V[i];\n    \n    // Euclidean distances rounded\n    vector<int> d(M);\n    for (int i = 0; i < M; ++i) {\n        double dx = x[U[i]] - x[V[i]];\n        double dy = y[U[i]] - y[V[i]];\n        d[i] = (int)round(sqrt(dx*dx + dy*dy));\n    }\n    \n    // XorShift random generator\n    uint32_t xs[4] = {123456789, 362436069, 521288629, 88675123};\n    auto xorshift = [&]() -> uint32_t {\n        uint32_t t = xs[0] ^ (xs[0] << 11);\n        xs[0] = xs[1];\n        xs[1] = xs[2];\n        xs[2] = xs[3];\n        xs[3] = xs[3] ^ (xs[3] >> 19) ^ t ^ (t >> 8);\n        return xs[3];\n    };\n    \n    // Monte Carlo simulation: how often each edge belongs to the MST\n    const int num_sim = 1500;\n    vector<int> mst_count(M, 0);\n    for (int sim = 0; sim < num_sim; ++sim) {\n        vector<tuple<int,int,int,int>> sim_edges; // (l, u, v, idx)\n        sim_edges.reserve(M);\n        for (int i = 0; i < M; ++i) {\n            int range = 2 * d[i] + 1;\n            int l = d[i] + int(xorshift() % range);\n            sim_edges.emplace_back(l, U[i], V[i], i);\n        }\n        sort(sim_edges.begin(), sim_edges.end());\n        DSU dsu_sim(N);\n        for (auto [l, u, v, idx] : sim_edges) {\n            if (dsu_sim.unite(u, v)) {\n                mst_count[idx]++;\n            }\n        }\n    }\n    \n    vector<double> prob(M);\n    for (int i = 0; i < M; ++i) {\n        prob[i] = (double)mst_count[i] / num_sim;\n    }\n    \n    // Pre-sort edge indices by their lower bound (d) for fast minimax alternative\n    vector<int> sorted_idx(M);\n    iota(sorted_idx.begin(), sorted_idx.end(), 0);\n    sort(sorted_idx.begin(), sorted_idx.end(), [&](int a, int b) {\n        return d[a] < d[b];\n    });\n    \n    DSU dsu(N);\n    vector<pair<int,int>> accepted; // not strictly needed, but helps debugging\n    \n    for (int i = 0; i < M; ++i) {\n        int l_i;\n        cin >> l_i;\n        int u = U[i], v = V[i];\n        \n        // Already connected -> reject\n        if (dsu.same(u, v)) {\n            cout << 0 << endl;\n            continue;\n        }\n        \n        // Very cheap edge -> accept immediately\n        if (l_i <= d[i] * 1.2) {\n            dsu.unite(u, v);\n            accepted.emplace_back(u, v);\n            cout << 1 << endl;\n            continue;\n        }\n        \n        int ru = dsu.find(u);\n        int rv = dsu.find(v);\n        \n        // Build a DSU from current accepted edges and run Kruskal on future edges (sorted by d)\n        DSU tmp(dsu);\n        int alternative_d = -1;\n        for (int idx : sorted_idx) {\n            if (idx <= i) continue;  // already decided\n            if (tmp.same(U[idx], V[idx])) continue;\n            tmp.unite(U[idx], V[idx]);\n            if (tmp.same(ru, rv)) {\n                alternative_d = d[idx];\n                break;\n            }\n        }\n        \n        // If even the whole future cannot connect these components, we must accept now\n        if (alternative_d == -1) {\n            dsu.unite(u, v);\n            accepted.emplace_back(u, v);\n            cout << 1 << endl;\n            continue;\n        }\n        \n        double progress = (double)i / M;\n        int comps = dsu.comps;\n        int R = M - i - 1;\n        double urgency = (R > 0) ? (double)(comps - 1) / R : 1.0;\n        \n        // l_ratio = l_i / d[i], normally in [1, 3]\n        double l_ratio = (double)l_i / d[i];\n        double factor = (2.0 + prob[i] + 0.5 * progress + 0.5 * urgency) * (2.0 / l_ratio);\n        // Truncate factor at 3.0 because the future edge true length cannot exceed 3*d\n        double threshold = alternative_d * min(3.0, factor);\n        \n        if (l_i <= threshold) {\n            dsu.unite(u, v);\n            accepted.emplace_back(u, v);\n            cout << 1 << endl;\n        } else {\n            cout << 0 << endl;\n        }\n    }\n    \n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst long long INF_CAP = 1e9;\n\nstruct Dinic {\n    struct Edge {\n        int to, rev;\n        long long cap;\n    };\n    vector<vector<Edge>> g;\n    vector<int> level, iter;\n    Dinic(int n) : g(n), level(n), iter(n) {}\n    void add_edge(int from, int to, long long cap) {\n        Edge a = {to, (int)g[to].size(), cap};\n        Edge b = {from, (int)g[from].size(), 0};\n        g[from].push_back(a);\n        g[to].push_back(b);\n    }\n    void bfs(int s) {\n        fill(level.begin(), level.end(), -1);\n        queue<int> q;\n        level[s] = 0;\n        q.push(s);\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (auto &e : g[v]) {\n                if (e.cap > 0 && level[e.to] < 0) {\n                    level[e.to] = level[v] + 1;\n                    q.push(e.to);\n                }\n            }\n        }\n    }\n    long long dfs(int v, int t, long long f) {\n        if (v == t) return f;\n        for (int &i = iter[v]; i < (int)g[v].size(); ++i) {\n            Edge &e = g[v][i];\n            if (e.cap > 0 && level[v] < level[e.to]) {\n                long long d = dfs(e.to, t, min(f, e.cap));\n                if (d > 0) {\n                    e.cap -= d;\n                    g[e.to][e.rev].cap += d;\n                    return d;\n                }\n            }\n        }\n        return 0;\n    }\n    long long max_flow(int s, int t) {\n        long long flow = 0;\n        while (true) {\n            bfs(s);\n            if (level[t] < 0) return flow;\n            fill(iter.begin(), iter.end(), 0);\n            long long f;\n            while ((f = dfs(s, t, 1LL << 60)) > 0) flow += f;\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int dx[4] = {-1, 1, 0, 0};\n    const int dy[4] = {0, 0, -1, 1};\n    const char moveC[4] = {'U', 'D', 'L', 'R'};\n    const char buildC[4] = {'u', 'd', 'l', 'r'};\n\n    int N;\n    cin >> N;\n    vector<int> px(N), py(N), pt(N);\n    for (int i = 0; i < N; ++i) cin >> px[i] >> py[i] >> pt[i];\n    int M;\n    cin >> M;\n    vector<int> hx(M), hy(M);\n    for (int i = 0; i < M; ++i) cin >> hx[i] >> hy[i];\n\n    int grid[32][32];\n    memset(grid, 0, sizeof(grid)); // 0 = passable, 1 = impassable\n\n    // Min-cut computation\n    auto compute_min_cut = [&]() -> set<pair<int, int>> {\n        int id[32][32];\n        memset(id, -1, sizeof(id));\n        vector<pair<int, int>> cells;\n        for (int i = 1; i <= 30; ++i)\n            for (int j = 1; j <= 30; ++j)\n                if (grid[i][j] == 0) {\n                    id[i][j] = (int)cells.size();\n                    cells.push_back({i, j});\n                }\n        int V = (int)cells.size();\n        int src = 2 * V, sink = 2 * V + 1;\n        Dinic dinic(2 * V + 2);\n\n        for (auto [x, y] : cells) {\n            int u = id[x][y];\n            bool has_human = false, has_pet = false, adj_pet = false;\n            for (int i = 0; i < M; ++i)\n                if (hx[i] == x && hy[i] == y) has_human = true;\n            for (int i = 0; i < N; ++i)\n                if (px[i] == x && py[i] == y) has_pet = true;\n            if (!has_pet) {\n                for (int d = 0; d < 4; ++d) {\n                    int nx = x + dx[d], ny = y + dy[d];\n                    if (nx >= 1 && nx <= 30 && ny >= 1 && ny <= 30) {\n                        for (int i = 0; i < N; ++i)\n                            if (px[i] == nx && py[i] == ny) adj_pet = true;\n                    }\n                }\n            }\n            bool buildable = !has_human && !has_pet && !adj_pet;\n            long long cap = buildable ? 1 : INF_CAP;\n            dinic.add_edge(2 * u, 2 * u + 1, cap);\n        }\n\n        for (int u = 0; u < V; ++u) {\n            auto [x, y] = cells[u];\n            for (int d = 0; d < 4; ++d) {\n                int nx = x + dx[d], ny = y + dy[d];\n                if (nx >= 1 && nx <= 30 && ny >= 1 && ny <= 30 && id[nx][ny] != -1) {\n                    int v = id[nx][ny];\n                    // Infinite capacity for adjacency\n                    dinic.add_edge(2 * u + 1, 2 * v, INF_CAP);\n                }\n            }\n        }\n\n        for (int i = 0; i < M; ++i) {\n            int u = id[hx[i]][hy[i]];\n            if (u != -1) dinic.add_edge(src, 2 * u, INF_CAP);\n        }\n        for (int i = 0; i < N; ++i) {\n            int u = id[px[i]][py[i]];\n            if (u != -1) dinic.add_edge(2 * u + 1, sink, INF_CAP);\n        }\n\n        long long flow = dinic.max_flow(src, sink);\n        set<pair<int, int>> cut;\n        if (flow < INF_CAP / 2) {\n            vector<bool> visited(2 * V + 2, false);\n            queue<int> q;\n            visited[src] = true;\n            q.push(src);\n            while (!q.empty()) {\n                int v = q.front(); q.pop();\n                for (auto &e : dinic.g[v]) {\n                    if (e.cap > 0 && !visited[e.to]) {\n                        visited[e.to] = true;\n                        q.push(e.to);\n                    }\n                }\n            }\n            for (int u = 0; u < V; ++u) {\n                if (visited[2 * u] && !visited[2 * u + 1]) {\n                    cut.insert(cells[u]);\n                }\n            }\n        }\n        return cut;\n    };\n\n    auto buildable_now = [&](int x, int y) -> bool {\n        if (grid[x][y] != 0) return false;\n        for (int i = 0; i < M; ++i) if (hx[i] == x && hy[i] == y) return false;\n        for (int i = 0; i < N; ++i) if (px[i] == x && py[i] == y) return false;\n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (nx >= 1 && nx <= 30 && ny >= 1 && ny <= 30) {\n                for (int i = 0; i < N; ++i)\n                    if (px[i] == nx && py[i] == ny) return false;\n            }\n        }\n        return true;\n    };\n\n    // BFS distance map from given sources\n    auto bfs_dist = [&](const vector<pair<int, int>> &sources, const set<pair<int, int>> &avoid) {\n        vector<vector<int>> dist(31, vector<int>(31, -1));\n        queue<pair<int, int>> q;\n        for (auto [x, y] : sources) {\n            if (grid[x][y] == 0 && !avoid.count({x, y})) {\n                dist[x][y] = 0;\n                q.push({x, y});\n            }\n        }\n        while (!q.empty()) {\n            auto [x, y] = q.front(); q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int nx = x + dx[d], ny = y + dy[d];\n                if (nx >= 1 && nx <= 30 && ny >= 1 && ny <= 30 &&\n                    grid[nx][ny] == 0 && !avoid.count({nx, ny}) && dist[nx][ny] == -1) {\n                    dist[nx][ny] = dist[x][y] + 1;\n                    q.push({nx, ny});\n                }\n            }\n        }\n        return dist;\n    };\n\n    set<pair<int, int>> target_walls = compute_min_cut();\n    map<pair<int, int>, int> urgency;\n\n    auto update_urgency = [&]() {\n        urgency.clear();\n        if (target_walls.empty()) return;\n        vector<pair<int, int>> pet_pos;\n        for (int i = 0; i < N; ++i) pet_pos.push_back({px[i], py[i]});\n        set<pair<int, int>> empty_avoid;\n        auto dist = bfs_dist(pet_pos, empty_avoid);\n        for (auto w : target_walls) {\n            int d = dist[w.first][w.second];\n            urgency[w] = (d == -1 ? 1000000 : d);\n        }\n    };\n    update_urgency();\n\n    for (int turn = 0; turn < 300; ++turn) {\n        // recompute min-cut periodically or when out of walls\n        if (turn > 0 && (turn % 20 == 0 || target_walls.empty())) {\n            target_walls = compute_min_cut();\n            update_urgency();\n        }\n\n        // compute pet distances for fallback (without any avoided squares)\n        vector<pair<int, int>> pet_pos;\n        for (int i = 0; i < N; ++i) pet_pos.push_back({px[i], py[i]});\n        set<pair<int, int>> empty_avoid;\n        auto dist_pet = bfs_dist(pet_pos, empty_avoid);\n\n        set<pair<int, int>> built_this_turn;\n        string actions(M, '.');\n\n        for (int i = 0; i < M; ++i) {\n            // 1. Build an adjacent target wall if possible\n            bool built = false;\n            for (int d = 0; d < 4; ++d) {\n                int wx = hx[i] + dx[d], wy = hy[i] + dy[d];\n                if (wx >= 1 && wx <= 30 && wy >= 1 && wy <= 30 && grid[wx][wy] == 0) {\n                    if (target_walls.count({wx, wy}) && !built_this_turn.count({wx, wy}) && buildable_now(wx, wy)) {\n                        actions[i] = buildC[d];\n                        built_this_turn.insert({wx, wy});\n                        target_walls.erase({wx, wy});\n                        urgency.erase({wx, wy});\n                        built = true;\n                        break;\n                    }\n                }\n            }\n            if (built) continue;\n\n            // 2. Move towards a target wall\n            // BFS from this human avoiding already built walls this turn\n            auto dist_h = bfs_dist({{hx[i], hy[i]}}, built_this_turn);\n            vector<vector<pair<int, int>>> parent(31, vector<pair<int, int>>(31, {-1, -1}));\n            queue<tuple<int, int, int, int>> bfs_q; // (x,y,px,py)\n            // Re-run BFS to record parent (we can reuse dist_h but need parent)\n            // Let's just run a dedicated BFS with parent tracking.\n            {\n                vector<vector<int>> dist2(31, vector<int>(31, -1));\n                queue<pair<int, int>> q;\n                dist2[hx[i]][hy[i]] = 0;\n                q.push({hx[i], hy[i]});\n                while (!q.empty()) {\n                    auto [x, y] = q.front(); q.pop();\n                    for (int d = 0; d < 4; ++d) {\n                        int nx = x + dx[d], ny = y + dy[d];\n                        if (nx >= 1 && nx <= 30 && ny >= 1 && ny <= 30 &&\n                            grid[nx][ny] == 0 && !built_this_turn.count({nx, ny}) && dist2[nx][ny] == -1) {\n                            dist2[nx][ny] = dist2[x][y] + 1;\n                            parent[nx][ny] = {x, y};\n                            q.push({nx, ny});\n                        }\n                    }\n                }\n                // update dist_h to this more accurate one\n                dist_h = dist2;\n            }\n\n            int best_dist = 1e9, best_urg = 1e9;\n            pair<int, int> best_wall = {-1, -1}, best_gate = {-1, -1};\n            for (auto w : target_walls) {\n                if (built_this_turn.count(w)) continue;\n                int wx = w.first, wy = w.second;\n                for (int d = 0; d < 4; ++d) {\n                    int gx = wx + dx[d], gy = wy + dy[d];\n                    if (gx >= 1 && gx <= 30 && gy >= 1 && gy <= 30 && grid[gx][gy] == 0 &&\n                        !built_this_turn.count({gx, gy})) {\n                        int dg = dist_h[gx][gy];\n                        if (dg >= 1 && dg < best_dist) {\n                            best_dist = dg;\n                            best_urg = urgency[w];\n                            best_wall = w;\n                            best_gate = {gx, gy};\n                        } else if (dg >= 1 && dg == best_dist && urgency[w] < best_urg) {\n                            best_urg = urgency[w];\n                            best_wall = w;\n                            best_gate = {gx, gy};\n                        }\n                    }\n                }\n            }\n\n            if (best_wall.first != -1) {\n                int cx = best_gate.first, cy = best_gate.second;\n                // trace back to the cell right after the human\n                while (parent[cx][cy] != make_pair(hx[i], hy[i])) {\n                    auto p = parent[cx][cy];\n                    if (p.first == -1) break; // safety\n                    cx = p.first;\n                    cy = p.second;\n                }\n                char dir;\n                if (cx < hx[i]) dir = 'U';\n                else if (cx > hx[i]) dir = 'D';\n                else if (cy < hy[i]) dir = 'L';\n                else dir = 'R';\n                actions[i] = dir;\n                // We do not update hx here; actions applied simultaneously later.\n                // We just record the action.\n                continue;\n            }\n\n            // 3. Fallback: move away from pets\n            int cur_d = dist_pet[hx[i]][hy[i]];\n            int best_d = cur_d;\n            int best_nx = -1, best_ny = -1;\n            for (int d = 0; d < 4; ++d) {\n                int nx = hx[i] + dx[d], ny = hy[i] + dy[d];\n                if (nx >= 1 && nx <= 30 && ny >= 1 && ny <= 30 &&\n                    grid[nx][ny] == 0 && !built_this_turn.count({nx, ny})) {\n                    if (dist_pet[nx][ny] > best_d) {\n                        best_d = dist_pet[nx][ny];\n                        best_nx = nx;\n                        best_ny = ny;\n                    }\n                }\n            }\n            if (best_nx != -1) {\n                char dir;\n                if (best_nx < hx[i]) dir = 'U';\n                else if (best_nx > hx[i]) dir = 'D';\n                else if (best_ny < hy[i]) dir = 'L';\n                else dir = 'R';\n                actions[i] = dir;\n                continue;\n            }\n\n            // 4. Last resort: build any adjacent wall\n            for (int d = 0; d < 4; ++d) {\n                int nx = hx[i] + dx[d], ny = hy[i] + dy[d];\n                if (nx >= 1 && nx <= 30 && ny >= 1 && ny <= 30 &&\n                    grid[nx][ny] == 0 && !built_this_turn.count({nx, ny}) && buildable_now(nx, ny)) {\n                    actions[i] = buildC[d];\n                    built_this_turn.insert({nx, ny});\n                    break;\n                }\n            }\n        }\n\n        cout << actions << endl;\n\n        // Apply actions\n        for (int i = 0; i < M; ++i) {\n            char c = actions[i];\n            if (c == 'u') grid[hx[i] - 1][hy[i]] = 1;\n            else if (c == 'd') grid[hx[i] + 1][hy[i]] = 1;\n            else if (c == 'l') grid[hx[i]][hy[i] - 1] = 1;\n            else if (c == 'r') grid[hx[i]][hy[i] + 1] = 1;\n            else if (c == 'U') hx[i]--;\n            else if (c == 'D') hx[i]++;\n            else if (c == 'L') hy[i]--;\n            else if (c == 'R') hy[i]++;\n        }\n\n        // Read pet movements\n        for (int i = 0; i < N; ++i) {\n            string s;\n            cin >> s;\n            if (s == \".\") continue;\n            for (char c : s) {\n                if (c == 'U') px[i]--;\n                else if (c == 'D') px[i]++;\n                else if (c == 'L') py[i]--;\n                else if (c == 'R') py[i]++;\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <iostream>\n#include <string>\n#include <vector>\n#include <array>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <numeric>\n#include <queue>\n#include <cmath>\n#include <set>\n\nusing namespace std;\n\nconst int L = 200;\nconst int H = 20, W = 20;\nconst int N = H * W;\n\nint start_id, target_id;\ndouble p;\nint next_cell[4][N];\ndouble p_stay[4][N], p_move[4][N];\nchar dir_chars[4] = {'U', 'D', 'L', 'R'};\ndouble reward[L];\n\n// Optimal adaptive DP for beam search heuristic\ndouble V_opt[L + 1][N];\n\n// forward/backward arrays for coordinate ascent\nvector<array<double, N>> F, V;\nvector<double> base_reward_prefix;\n\ndouble evaluate(const string &s) {\n    array<double, N> prob;\n    prob.fill(0.0);\n    prob[start_id] = 1.0;\n    vector<int> active = {start_id};\n    double er = 0.0;\n    for (int t = 0; t < L; ++t) {\n        if (active.empty()) break;\n        char c = s[t];\n        int d;\n        if (c == 'U') d = 0;\n        else if (c == 'D') d = 1;\n        else if (c == 'L') d = 2;\n        else d = 3;\n        array<double, N> next_prob;\n        next_prob.fill(0.0);\n        array<bool, N> next_mark;\n        next_mark.fill(false);\n        for (int i : active) {\n            double pr = prob[i];\n            double stay = p_stay[d][i];\n            double move = p_move[d][i];\n            next_prob[i] += pr * stay;\n            next_mark[i] = true;\n            if (move > 0.0) {\n                int nxt = next_cell[d][i];\n                if (nxt == target_id) {\n                    er += pr * move * reward[t];\n                } else {\n                    next_prob[nxt] += pr * move;\n                    next_mark[nxt] = true;\n                }\n            }\n        }\n        prob.fill(0.0);\n        active.clear();\n        for (int i = 0; i < N; ++i) {\n            if (next_mark[i]) {\n                prob[i] = next_prob[i];\n                active.push_back(i);\n            }\n        }\n    }\n    return er;\n}\n\nint main() {\n    auto start_time = chrono::steady_clock::now();\n    auto time_ms = [&]() {\n        return chrono::duration_cast<chrono::milliseconds>(\n            chrono::steady_clock::now() - start_time).count();\n    };\n\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj, ti, tj;\n    cin >> si >> sj >> ti >> tj >> p;\n    start_id = si * W + sj;\n    target_id = ti * W + tj;\n\n    vector<string> h(20), v(20);\n    for (int i = 0; i < 20; ++i) cin >> h[i];\n    for (int i = 0; i < 19; ++i) cin >> v[i]; // v has 19 rows of length 20\n\n    for (int t = 0; t < L; ++t) reward[t] = 401.0 - (t + 1);\n\n    // precompute walls and transition probabilities\n    int di[4] = {-1, 1, 0, 0};\n    int dj[4] = {0, 0, -1, 1};\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = i * W + j;\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + di[d];\n                int nj = j + dj[d];\n                bool wall = true;\n                if (ni >= 0 && ni < H && nj >= 0 && nj < W) {\n                    if (d == 0) {        // U\n                        if (v[i - 1][j] == '0') wall = false;\n                    } else if (d == 1) { // D\n                        if (v[i][j] == '0') wall = false;\n                    } else if (d == 2) { // L\n                        if (h[i][j - 1] == '0') wall = false;\n                    } else {             // R\n                        if (h[i][j] == '0') wall = false;\n                    }\n                }\n                if (!wall) {\n                    next_cell[d][id] = ni * W + nj;\n                } else {\n                    next_cell[d][id] = id;\n                }\n                p_stay[d][id] = wall ? 1.0 : p;\n                p_move[d][id] = wall ? 0.0 : (1.0 - p);\n            }\n        }\n    }\n\n    // Optimal adaptive DP (upper bound for beam search)\n    for (int i = 0; i < N; ++i) V_opt[0][i] = 0.0;\n    for (int r = 1; r <= L; ++r) {\n        double target_rew = 200.0 + r;\n        for (int i = 0; i < N; ++i) {\n            if (i == target_id) {\n                V_opt[r][i] = 0.0;\n                continue;\n            }\n            double best = 0.0;\n            for (int d = 0; d < 4; ++d) {\n                double stay = p_stay[d][i];\n                double move = p_move[d][i];\n                double val;\n                if (move == 0.0) {\n                    val = V_opt[r - 1][i];\n                } else {\n                    int nxt = next_cell[d][i];\n                    double move_val = (nxt == target_id) ? target_rew : V_opt[r - 1][nxt];\n                    val = stay * V_opt[r - 1][i] + move * move_val;\n                }\n                if (val > best) best = val;\n            }\n            V_opt[r][i] = best;\n        }\n    }\n\n    // ---------- Beam search ----------\n    const int K = 200;\n    vector<array<double, N>> beam_prob;\n    vector<string> beam_str;\n    vector<double> beam_er;\n\n    {\n        array<double, N> prob;\n        prob.fill(0.0);\n        prob[start_id] = 1.0;\n        beam_prob.push_back(prob);\n        beam_str.push_back(\"\");\n        beam_er.push_back(0.0);\n    }\n\n    for (int step = 0; step < L; ++step) {\n        vector<array<double, N>> next_prob_vec;\n        vector<string> next_str;\n        vector<double> next_er;\n        vector<double> next_score;\n\n        for (int idx = 0; idx < (int)beam_prob.size(); ++idx) {\n            const auto &prob = beam_prob[idx];\n            const string &s = beam_str[idx];\n            double er = beam_er[idx];\n\n            for (int d = 0; d < 4; ++d) {\n                array<double, N> ns_prob;\n                ns_prob.fill(0.0);\n                double ns_er = er;\n                for (int i = 0; i < N; ++i) {\n                    double pr = prob[i];\n                    if (pr == 0.0) continue;\n                    double stay = p_stay[d][i];\n                    double move = p_move[d][i];\n                    ns_prob[i] += pr * stay;\n                    if (move > 0.0) {\n                        int nxt = next_cell[d][i];\n                        if (nxt == target_id) {\n                            ns_er += pr * move * reward[step];\n                        } else {\n                            ns_prob[nxt] += pr * move;\n                        }\n                    }\n                }\n                int R = L - (step + 1);\n                double future = 0.0;\n                for (int i = 0; i < N; ++i) future += ns_prob[i] * V_opt[R][i];\n                double score = ns_er + future;\n\n                next_prob_vec.push_back(move(ns_prob));\n                next_str.push_back(s + dir_chars[d]);\n                next_er.push_back(ns_er);\n                next_score.push_back(score);\n            }\n        }\n\n        if (next_score.size() > K) {\n            vector<int> indices(next_score.size());\n            iota(indices.begin(), indices.end(), 0);\n            nth_element(indices.begin(), indices.begin() + K, indices.end(),\n                        [&](int a, int b) { return next_score[a] > next_score[b]; });\n            beam_prob.clear(); beam_str.clear(); beam_er.clear();\n            for (int i = 0; i < K; ++i) {\n                int id = indices[i];\n                beam_prob.push_back(move(next_prob_vec[id]));\n                beam_str.push_back(move(next_str[id]));\n                beam_er.push_back(next_er[id]);\n            }\n        } else {\n            beam_prob = move(next_prob_vec);\n            beam_str = move(next_str);\n            beam_er = move(next_er);\n        }\n    }\n\n    // collect distinct best strings from beam\n    vector<pair<double, string>> candidates;\n    {\n        vector<int> order(beam_er.size());\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) { return beam_er[a] > beam_er[b]; });\n        set<string> seen;\n        for (int idx : order) {\n            if (seen.insert(beam_str[idx]).second) {\n                candidates.emplace_back(beam_er[idx], beam_str[idx]);\n                if (candidates.size() >= 5) break;\n            }\n        }\n    }\n\n    // add deterministic shortest path repeated as fallback\n    {\n        vector<int> prev(N, -1);\n        vector<char> prev_move(N);\n        queue<int> q;\n        q.push(start_id);\n        prev[start_id] = start_id;\n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            if (u == target_id) break;\n            for (int d = 0; d < 4; ++d) {\n                if (p_stay[d][u] < 1.0) { // not wall\n                    int v = next_cell[d][u];\n                    if (prev[v] == -1) {\n                        prev[v] = u;\n                        prev_move[v] = dir_chars[d];\n                        q.push(v);\n                    }\n                }\n            }\n        }\n        string path;\n        for (int v = target_id; v != start_id; v = prev[v])\n            path += prev_move[v];\n        reverse(path.begin(), path.end());\n        string repeated;\n        while (repeated.size() < L) repeated += path;\n        repeated.resize(L);\n        double val = evaluate(repeated);\n        candidates.emplace_back(val, repeated);\n    }\n\n    // keep up to 5 distinct best\n    sort(candidates.begin(), candidates.end(),\n         [](const auto &a, const auto &b) { return a.first > b.first; });\n    set<string> unique_cands;\n    vector<string> start_strings;\n    for (auto &[val, s] : candidates) {\n        if (unique_cands.insert(s).second) {\n            start_strings.push_back(s);\n            if (start_strings.size() >= 5) break;\n        }\n    }\n\n    // ---------- Coordinate ascent ----------\n    F.resize(L + 1);\n    V.resize(L + 1);\n    base_reward_prefix.resize(L + 1);\n\n    auto char_to_dir = [](char c) -> int {\n        if (c == 'U') return 0;\n        if (c == 'D') return 1;\n        if (c == 'L') return 2;\n        return 3;\n    };\n\n    auto compute_forward = [&](const string &s) -> double {\n        F[0].fill(0.0);\n        F[0][start_id] = 1.0;\n        fill(base_reward_prefix.begin(), base_reward_prefix.end(), 0.0);\n        double total_er = 0.0;\n        for (int t = 0; t < L; ++t) {\n            int d = char_to_dir(s[t]);\n            double step_reward = 0.0;\n            auto &cur = F[t];\n            auto &nxt = F[t + 1];\n            nxt.fill(0.0);\n            for (int i = 0; i < N; ++i) {\n                double pr = cur[i];\n                if (pr == 0.0) continue;\n                double stay = p_stay[d][i];\n                double move = p_move[d][i];\n                nxt[i] += pr * stay;\n                if (move > 0.0) {\n                    int nc = next_cell[d][i];\n                    if (nc == target_id) {\n                        step_reward += pr * move * reward[t];\n                    } else {\n                        nxt[nc] += pr * move;\n                    }\n                }\n            }\n            base_reward_prefix[t + 1] = base_reward_prefix[t] + step_reward;\n            total_er += step_reward;\n        }\n        return total_er;\n    };\n\n    auto compute_backward = [&](const string &s) {\n        V[L].fill(0.0);\n        for (int t = L - 1; t >= 0; --t) {\n            int d = char_to_dir(s[t]);\n            auto &cur = V[t];\n            auto &nxt = V[t + 1];\n            for (int i = 0; i < N; ++i) {\n                double stay = p_stay[d][i];\n                double move = p_move[d][i];\n                double val = stay * nxt[i];\n                if (move > 0.0) {\n                    int nc = next_cell[d][i];\n                    if (nc == target_id) {\n                        val += move * reward[t];\n                    } else {\n                        val += move * nxt[nc];\n                    }\n                }\n                cur[i] = val;\n            }\n        }\n    };\n\n    double best_overall_er = -1e9;\n    string best_overall_str;\n\n    for (string &cur_str : start_strings) {\n        if (time_ms() > 1900) break;\n\n        // coordinate ascent\n        while (true) {\n            if (time_ms() > 1900) break;\n            double total_er = compute_forward(cur_str);\n            compute_backward(cur_str);\n\n            double best_improvement = -1e-12;\n            int best_pos = -1, best_dir = -1;\n            double best_new_total = total_er;\n\n            vector<int> cur_dirs(L);\n            for (int t = 0; t < L; ++t) cur_dirs[t] = char_to_dir(cur_str[t]);\n\n            for (int pos = 0; pos < L; ++pos) {\n                double base_val = base_reward_prefix[pos];\n                const auto &f = F[pos];\n                const auto &v_next = V[pos + 1];\n\n                for (int d = 0; d < 4; ++d) {\n                    if (d == cur_dirs[pos]) continue;\n                    double sum = base_val;\n                    for (int i = 0; i < N; ++i) {\n                        double pr = f[i];\n                        if (pr == 0.0) continue;\n                        double stay = p_stay[d][i];\n                        double move = p_move[d][i];\n                        double contrib = stay * v_next[i];\n                        if (move > 0.0) {\n                            int nxt = next_cell[d][i];\n                            if (nxt == target_id) {\n                                contrib += move * reward[pos];\n                            } else {\n                                contrib += move * v_next[nxt];\n                            }\n                        }\n                        sum += pr * contrib;\n                    }\n                    double improvement = sum - total_er;\n                    if (improvement > best_improvement) {\n                        best_improvement = improvement;\n                        best_pos = pos;\n                        best_dir = d;\n                        best_new_total = sum;\n                    }\n                }\n            }\n            if (best_improvement <= 1e-12) break;\n            cur_str[best_pos] = dir_chars[best_dir];\n        }\n        double final_er = evaluate(cur_str);\n        if (final_er > best_overall_er) {\n            best_overall_er = final_er;\n            best_overall_str = cur_str;\n        }\n    }\n\n    // ---------- Simulated Annealing (if time remains) ----------\n    if (time_ms() < 1850) {\n        mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n        uniform_real_distribution<double> real(0.0, 1.0);\n        uniform_int_distribution<int> pos_dis(0, L - 1);\n        uniform_int_distribution<int> dir_dis(0, 3);\n\n        string cur = best_overall_str;\n        double cur_val = best_overall_er;\n        string best_cur = cur;\n        double best_val = cur_val;\n        double T = 0.5;\n        double alpha = 0.999;\n\n        while (time_ms() < 1950) {\n            string nxt = cur;\n            int op = (int)(real(rng) * 100);\n            if (op < 60) {\n                int pos = pos_dis(rng);\n                char old = nxt[pos];\n                char nc = dir_chars[dir_dis(rng)];\n                while (nc == old) nc = dir_chars[dir_dis(rng)];\n                nxt[pos] = nc;\n            } else if (op < 80) {\n                int a = pos_dis(rng), b = pos_dis(rng);\n                swap(nxt[a], nxt[b]);\n            } else {\n                int a = pos_dis(rng), b = pos_dis(rng);\n                if (a > b) swap(a, b);\n                reverse(nxt.begin() + a, nxt.begin() + b + 1);\n            }\n            double nxt_val = evaluate(nxt);\n            double diff = nxt_val - cur_val;\n            if (diff > 0 || exp(diff / T) > real(rng)) {\n                cur = nxt;\n                cur_val = nxt_val;\n                if (cur_val > best_val) {\n                    best_val = cur_val;\n                    best_cur = cur;\n                }\n            }\n            T *= alpha;\n        }\n        best_overall_str = best_cur;\n    }\n\n    cout << best_overall_str << \"\\n\";\n    return 0;\n}","ahc010":"#include <iostream>\n#include <string>\n#include <cstring>\n#include <chrono>\n#include <cstdint>\n#include <vector>\n#include <cmath>\n\nusing namespace std;\n\n// fast xorshift random generator\nuint64_t xor64_state = 123456789ULL;\nuint64_t xor64() {\n    xor64_state ^= xor64_state << 13;\n    xor64_state ^= xor64_state >> 7;\n    xor64_state ^= xor64_state << 17;\n    return xor64_state;\n}\nint rand_int(int n) {\n    return xor64() % n;\n}\ndouble rand_double() {\n    return (xor64() >> 11) * (1.0 / (1ULL << 53));\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    xor64_state = chrono::steady_clock::now().time_since_epoch().count();\n\n    // read initial tiles\n    int init_tiles[900];\n    for (int i = 0; i < 30; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < 30; ++j) {\n            init_tiles[i * 30 + j] = s[j] - '0';\n        }\n    }\n\n    // rotation mapping: rotate[t][r] = tile type after r CCW rotations\n    const int rot1[8] = {1, 2, 3, 0, 5, 4, 7, 6};\n    int rotate[8][4];\n    for (int t = 0; t < 8; ++t) {\n        rotate[t][0] = t;\n        for (int r = 1; r < 4; ++r) {\n            rotate[t][r] = rot1[rotate[t][r-1]];\n        }\n    }\n\n    // neighbor index table (flat array)\n    int neig[3600];\n    for (int i = 0; i < 30; ++i) {\n        for (int j = 0; j < 30; ++j) {\n            int idx = i * 30 + j;\n            int base = idx * 4;\n            neig[base+0] = (j > 0) ? idx - 1 : -1;\n            neig[base+1] = (i > 0) ? idx - 30 : -1;\n            neig[base+2] = (j < 29) ? idx + 1 : -1;\n            neig[base+3] = (i < 29) ? idx + 30 : -1;\n        }\n    }\n\n    // transition table: to[t][d] = next direction inside tile, -1 if none\n    const int to[8][4] = {\n        {1, 0, -1, -1},\n        {3, -1, -1, 0},\n        {-1, -1, 3, 2},\n        {-1, 2, 1, -1},\n        {1, 0, 3, 2},\n        {3, 2, 1, 0},\n        {2, -1, 0, -1},\n        {-1, 3, -1, 1}\n    };\n\n    // evaluation function: returns L1 * L2\n    static int vis[3600] = {0};\n    static int vis_id = 0;\n    auto evaluate = [&](const int* cur) -> int {\n        ++vis_id;\n        int max1 = 0, max2 = 0;\n        for (int i = 0; i < 900; ++i) {\n            int t = cur[i];\n            int base = i * 4;\n            for (int d = 0; d < 4; ++d) {\n                int idx = base + d;\n                if (vis[idx] == vis_id) continue;\n                int d0 = to[t][d];\n                if (d0 < 0) continue;\n                int si = i, sd = d;\n                int ci = i, cd = d;\n                int len = 0;\n                while (true) {\n                    vis[ci * 4 + cd] = vis_id;\n                    int d2 = to[cur[ci]][cd];\n                    if (d2 < 0) { len = -1; break; }\n                    int ni = neig[ci * 4 + d2];\n                    if (ni < 0) { len = -1; break; }\n                    ++len;\n                    ci = ni;\n                    cd = (d2 + 2) & 3;\n                    if (ci == si && cd == sd) break;\n                    if (len > 4000) { len = -1; break; } // safety\n                }\n                if (len > 0) {\n                    if (len > max1) {\n                        max2 = max1;\n                        max1 = len;\n                    } else if (len > max2) {\n                        max2 = len;\n                    }\n                }\n            }\n        }\n        if (max2 == 0) return 0;\n        return max1 * max2;\n    };\n\n    // hill climbing on a state (in-place, returns new score)\n    auto hill_climb = [&](int* cur, int* rot, int init_score) -> int {\n        int score = init_score;\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            for (int i = 0; i < 900; ++i) {\n                int orig_rot = rot[i];\n                int orig_type = cur[i];\n                int best_local_score = score;\n                int best_r = orig_rot;\n                for (int r = 0; r < 4; ++r) {\n                    if (r == orig_rot) continue;\n                    int new_type = rotate[init_tiles[i]][r];\n                    cur[i] = new_type;\n                    rot[i] = r;\n                    int new_score = evaluate(cur);\n                    if (new_score > best_local_score) {\n                        best_local_score = new_score;\n                        best_r = r;\n                    }\n                }\n                if (best_r != orig_rot) {\n                    cur[i] = rotate[init_tiles[i]][best_r];\n                    rot[i] = best_r;\n                    score = best_local_score;\n                    improved = true;\n                } else {\n                    cur[i] = orig_type;\n                    rot[i] = orig_rot;\n                }\n            }\n        }\n        return score;\n    };\n\n    int best_rot[900];\n    int best_score = -1;\n    auto start_time = chrono::steady_clock::now();\n\n    // greedy initial state: maximize local connections with already processed neighbors\n    {\n        int cur[900];\n        int rot[900];\n        for (int i = 0; i < 30; ++i) {\n            for (int j = 0; j < 30; ++j) {\n                int idx = i * 30 + j;\n                int best_r = 0;\n                int best_conn = -1;\n                for (int r = 0; r < 4; ++r) {\n                    int t = rotate[init_tiles[idx]][r];\n                    int conn = 0;\n                    if (j > 0) {\n                        int lt = cur[idx - 1];\n                        if (to[t][0] != -1 && to[lt][2] != -1) ++conn;\n                    }\n                    if (i > 0) {\n                        int ut = cur[idx - 30];\n                        if (to[t][1] != -1 && to[ut][3] != -1) ++conn;\n                    }\n                    if (conn > best_conn) {\n                        best_conn = conn;\n                        best_r = r;\n                    }\n                }\n                rot[idx] = best_r;\n                cur[idx] = rotate[init_tiles[idx]][best_r];\n            }\n        }\n        int gscore = evaluate(cur);\n        int improved = hill_climb(cur, rot, gscore);\n        if (improved > best_score) {\n            best_score = improved;\n            memcpy(best_rot, rot, sizeof(rot));\n        }\n    }\n\n    // restart loop (if time permits)\n    while (true) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n        if (elapsed >= 1.8) break;\n\n        int cur[900];\n        int rot[900];\n        for (int i = 0; i < 900; ++i) {\n            rot[i] = rand_int(4);\n            cur[i] = rotate[init_tiles[i]][rot[i]];\n        }\n\n        int cur_score = evaluate(cur);\n        int restart_best_score = cur_score;\n        int restart_best_rot[900];\n        memcpy(restart_best_rot, rot, sizeof(rot));\n\n        double T = 250.0;\n        double alpha = 0.998;\n        const int inner_steps = 30;\n        while (T > 0.15) {\n            for (int sub = 0; sub < inner_steps; ++sub) {\n                int idx = rand_int(900);\n                int delta = (rand_int(3) + 1) & 3;\n                int old_rot = rot[idx];\n                if (delta == 0) continue;\n                int new_rot = (old_rot + delta) & 3;\n                int old_type = cur[idx];\n                int new_type = rotate[init_tiles[idx]][new_rot];\n                if (new_type == old_type) continue;\n\n                cur[idx] = new_type;\n                rot[idx] = new_rot;\n                int new_score = evaluate(cur);\n                int diff = new_score - cur_score;\n                if (diff >= 0 || rand_double() < exp(diff / T)) {\n                    cur_score = new_score;\n                    if (new_score > restart_best_score) {\n                        restart_best_score = new_score;\n                        memcpy(restart_best_rot, rot, sizeof(rot));\n                    }\n                } else {\n                    cur[idx] = old_type;\n                    rot[idx] = old_rot;\n                }\n            }\n            T *= alpha;\n            double el = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n            if (el >= 1.8) break;\n        }\n\n        // hill climb on the best found during this restart\n        memcpy(rot, restart_best_rot, sizeof(rot));\n        for (int i = 0; i < 900; ++i) cur[i] = rotate[init_tiles[i]][rot[i]];\n        int final_score = hill_climb(cur, rot, restart_best_score);\n\n        if (final_score > best_score) {\n            best_score = final_score;\n            memcpy(best_rot, rot, sizeof(rot));\n        }\n    }\n\n    // final polish on the globally best solution (if time remains)\n    {\n        int cur[900];\n        for (int i = 0; i < 900; ++i) cur[i] = rotate[init_tiles[i]][best_rot[i]];\n        int cur_score = evaluate(cur);\n        int improved = hill_climb(cur, best_rot, cur_score);\n        if (improved > best_score) best_score = improved;\n    }\n\n    // output 900 rotation digits\n    for (int i = 0; i < 900; ++i) cout << best_rot[i];\n    cout << endl;\n\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\nusing uint64 = unsigned long long;\nusing uint16 = unsigned short;\n\nconst int MAXN = 10;\nconst int MAXV = MAXN * MAXN; // 100\n\nint N, T, V;\nint EMPTY_ID;\n\n// Directions: 0:left, 1:up, 2:right, 3:down\nint dir_bit[4] = {1, 2, 4, 8};\nint opp_dir[4] = {2, 3, 0, 1};\nint drow[4] = {0, -1, 0, 1};\nint dcol[4] = {-1, 0, 1, 0};\nchar move_chars[4] = {'L', 'U', 'R', 'D'};\nunordered_map<char, char> opp_char_map = {{'L','R'},{'R','L'},{'U','D'},{'D','U'}};\n\nint tile_has[16][4];\nuint16 mask_has[4], mask_no[4];\n\nvoid precompute_tile_masks() {\n    for (int t=0; t<16; ++t) {\n        for (int d=0; d<4; ++d) {\n            tile_has[t][d] = (t & dir_bit[d]) ? 1 : 0;\n        }\n    }\n    for (int d=0; d<4; ++d) {\n        uint16 m_has = 0;\n        for (int t=0; t<16; ++t) if (tile_has[t][d]) m_has |= (1<<t);\n        mask_has[d] = m_has;\n        mask_no[d] = (~m_has) & 0xFFFF;\n    }\n}\n\n// ---------- CSP (target board reconstruction) ----------\nuint16 dom[MAXN][MAXN];\nint csp_board[MAXN][MAXN];\nbool assigned[MAXN][MAXN];\nint csp_tile_counts[16];\n\nbool dfs_csp(int assigned_cnt) {\n    if (assigned_cnt == V) return true;\n    int best_i=-1, best_j=-1, best_pop=999;\n    for (int i=0; i<N; ++i) {\n        for (int j=0; j<N; ++j) {\n            if (!assigned[i][j]) {\n                int pop = __builtin_popcount(dom[i][j]);\n                if (pop < best_pop) {\n                    best_pop = pop;\n                    best_i = i; best_j = j;\n                }\n            }\n        }\n    }\n    if (best_pop == 0) return false;\n    int i=best_i, j=best_j;\n    uint16 cur_dom = dom[i][j];\n    for (int t=0; t<16; ++t) {\n        if (!(cur_dom & (1<<t))) continue;\n        if (csp_tile_counts[t] == 0) continue;\n        bool ok = true;\n        for (int d=0; d<4; ++d) {\n            int ni = i + drow[d], nj = j + dcol[d];\n            if (ni<0 || ni>=N || nj<0 || nj>=N) continue;\n            if (assigned[ni][nj]) {\n                int nt = csp_board[ni][nj];\n                if (tile_has[t][d] != tile_has[nt][opp_dir[d]]) {\n                    ok = false; break;\n                }\n            }\n        }\n        if (!ok) continue;\n        csp_tile_counts[t]--;\n        assigned[i][j] = true;\n        csp_board[i][j] = t;\n        vector<tuple<int,int,uint16>> saved;\n        for (int d=0; d<4; ++d) {\n            int ni = i + drow[d], nj = j + dcol[d];\n            if (ni<0 || ni>=N || nj<0 || nj>=N) continue;\n            if (!assigned[ni][nj]) {\n                uint16 old = dom[ni][nj];\n                uint16 new_dom;\n                if (tile_has[t][d]) {\n                    new_dom = old & mask_has[opp_dir[d]];\n                } else {\n                    new_dom = old & mask_no[opp_dir[d]];\n                }\n                if (new_dom == 0) { ok = false; break; }\n                if (new_dom != old) {\n                    dom[ni][nj] = new_dom;\n                    saved.push_back({ni,nj,old});\n                }\n            }\n        }\n        if (ok) {\n            if (dfs_csp(assigned_cnt+1)) return true;\n        }\n        for (auto& s : saved) {\n            dom[get<0>(s)][get<1>(s)] = get<2>(s);\n        }\n        assigned[i][j] = false;\n        csp_board[i][j] = -1;\n        csp_tile_counts[t]++;\n    }\n    return false;\n}\n\n// ---------- Hungarian algorithm ----------\nvector<int> hungarian(const vector<vector<int>>& cost) {\n    int n = cost.size();\n    if (n == 0) return {};\n    vector<int> u(n+1, 0), v(n+1, 0), p(n+1, 0), way(n+1, 0);\n    const int INF = 1e9;\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) {\n                if (!used[j]) {\n                    int cur = cost[i0-1][j-1] - u[i0] - v[j];\n                    if (cur < minv[j]) { minv[j] = cur; way[j] = j0; }\n                    if (minv[j] < delta) { delta = minv[j]; 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    vector<int> assignment(n, -1);\n    for (int j=1; j<=n; ++j) {\n        if (p[j] > 0) {\n            assignment[p[j]-1] = j-1;\n        }\n    }\n    return assignment;\n}\n\n// ---------- Node for beam search ----------\nstruct Node {\n    uint8_t board[MAXV];\n    int empty;\n    int h;\n    uint64 hash;\n    int parent;\n    char move;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> T;\n    V = N * N;\n    EMPTY_ID = V - 1; // empty tile gets this ID\n\n    precompute_tile_masks();\n\n    vector<string> grid(N);\n    for (int i=0; i<N; ++i) cin >> grid[i];\n\n    int init_type[MAXN][MAXN];\n    int tile_counts[16] = {0};\n    for (int i=0; i<N; ++i) {\n        for (int j=0; j<N; ++j) {\n            char c = grid[i][j];\n            int t = (c >= '0' && c <= '9') ? (c - '0') : (c - 'a' + 10);\n            init_type[i][j] = t;\n            tile_counts[t]++;\n        }\n    }\n\n    // ---------- target board CSP ----------\n    for (int i=0; i<N; ++i) for (int j=0; j<N; ++j) {\n        uint16 mask = 0xFFFF;\n        if (i == 0) mask &= mask_no[1];      // no up\n        if (i == N-1) mask &= mask_no[3];    // no down\n        if (j == 0) mask &= mask_no[0];      // no left\n        if (j == N-1) mask &= mask_no[2];    // no right\n        if (i == N-2 && j == N-1) mask &= mask_no[3]; // no down to empty\n        if (i == N-1 && j == N-2) mask &= mask_no[2]; // no right to empty\n        if (i == N-1 && j == N-1) mask = (1 << 0);    // only empty tile\n        else mask &= ~(1 << 0);              // empty tile already used\n        dom[i][j] = mask;\n    }\n    memset(assigned, 0, sizeof(assigned));\n    memset(csp_board, -1, sizeof(csp_board));\n    memcpy(csp_tile_counts, tile_counts, sizeof(tile_counts));\n    assigned[N-1][N-1] = true;\n    csp_board[N-1][N-1] = 0;\n    csp_tile_counts[0]--;\n    dom[N-1][N-1] = 0;\n\n    bool csp_ok = dfs_csp(1);\n    assert(csp_ok); // problem guarantees solvable\n\n    // ---------- ID assignment and matching ----------\n    int init_id[MAXN][MAXN];\n    int id_to_type[MAXV];\n    int id_count = 0;\n    for (int i=0; i<N; ++i) for (int j=0; j<N; ++j) {\n        if (init_type[i][j] == 0) {\n            init_id[i][j] = EMPTY_ID;\n            id_to_type[EMPTY_ID] = 0;\n        } else {\n            init_id[i][j] = id_count;\n            id_to_type[id_count] = init_type[i][j];\n            id_count++;\n        }\n    }\n\n    int targetPos[MAXV];\n    targetPos[EMPTY_ID] = (N-1)*N + (N-1);\n\n    vector<int> ids_of_type[16];\n    vector<int> cells_of_type[16];\n    for (int i=0; i<N; ++i) for (int j=0; j<N; ++j) {\n        int t = csp_board[i][j];\n        if (t != 0) {\n            cells_of_type[t].push_back(i*N + j);\n        }\n    }\n    for (int id=0; id<EMPTY_ID; ++id) {\n        int t = id_to_type[id];\n        ids_of_type[t].push_back(id);\n    }\n\n    // initial positions of IDs\n    int initPos[MAXV];\n    for (int i=0; i<N; ++i) for (int j=0; j<N; ++j) {\n        initPos[init_id[i][j]] = i*N + j;\n    }\n\n    for (int t=1; t<16; ++t) {\n        int n = ids_of_type[t].size();\n        if (n == 0) continue;\n        vector<vector<int>> cost(n, vector<int>(n));\n        for (int i=0; i<n; ++i) {\n            int id = ids_of_type[t][i];\n            int r1 = initPos[id] / N, c1 = initPos[id] % N;\n            for (int j=0; j<n; ++j) {\n                int cell = cells_of_type[t][j];\n                int r2 = cell / N, c2 = cell % N;\n                cost[i][j] = abs(r1-r2) + abs(c1-c2);\n            }\n        }\n        vector<int> assignment = hungarian(cost);\n        for (int i=0; i<n; ++i) {\n            int id = ids_of_type[t][i];\n            int j = assignment[i];\n            targetPos[id] = cells_of_type[t][j];\n        }\n    }\n\n    // ---------- Manhattan distance table ----------\n    int manDist[MAXV][MAXV];\n    for (int id=0; id<V; ++id) {\n        int tr = targetPos[id] / N, tc = targetPos[id] % N;\n        for (int cell=0; cell<V; ++cell) {\n            int r = cell / N, c = cell % N;\n            manDist[id][cell] = abs(tr-r) + abs(tc-c);\n        }\n    }\n\n    // ---------- Zobrist hashing ----------\n    mt19937_64 rng(12345);\n    uint64 zob[MAXV][MAXV];\n    for (int id=0; id<V; ++id)\n        for (int cell=0; cell<V; ++cell)\n            zob[id][cell] = rng();\n\n    // ---------- Initial state ----------\n    Node root;\n    for (int i=0; i<N; ++i)\n        for (int j=0; j<N; ++j)\n            root.board[i*N+j] = init_id[i][j];\n\n    int init_h = 0;\n    uint64 init_hash = 0;\n    for (int cell=0; cell<V; ++cell) {\n        int id = root.board[cell];\n        if (id == EMPTY_ID) root.empty = cell;\n        init_h += manDist[id][cell];\n        init_hash ^= zob[id][cell];\n    }\n    root.h = init_h;\n    root.hash = init_hash;\n    root.parent = -1;\n    root.move = 0;\n\n    if (init_h == 0) {\n        cout << \"\" << endl;\n        return 0;\n    }\n\n    // ---------- Beam search ----------\n    vector<Node> nodes;\n    nodes.reserve(400000);\n    unordered_set<uint64_t> global_hash;\n    global_hash.reserve(400000);\n\n    nodes.push_back(root);\n    global_hash.insert(root.hash);\n\n    vector<int> current_beam = {0};\n    int goal_node = -1;\n    int best_h_node = 0;\n    int best_h = init_h;\n    const int beam_width = 150;\n\n    clock_t start_time = clock();\n    const double TIME_LIMIT = 2.8 * CLOCKS_PER_SEC;\n\n    for (int depth = 0; depth < T; ++depth) {\n        if (clock() - start_time > TIME_LIMIT) break;\n        vector<int> next_nodes;\n        for (int idx : current_beam) {\n            Node& cur = nodes[idx];\n            int e = cur.empty;\n            int r = e / N, c = e % N;\n            for (int d=0; d<4; ++d) {\n                int nr = r + drow[d], nc = c + dcol[d];\n                if (nr<0 || nr>=N || nc<0 || nc>=N) continue;\n                if (cur.move != 0) {\n                    if (move_chars[d] == opp_char_map[cur.move]) continue;\n                }\n                int neighbor = nr*N + nc;\n                int tileID = cur.board[neighbor];\n\n                Node next;\n                memcpy(next.board, cur.board, V * sizeof(uint8_t));\n                next.board[e] = tileID;\n                next.board[neighbor] = EMPTY_ID;\n                next.empty = neighbor;\n\n                uint64 new_hash = cur.hash;\n                new_hash ^= zob[tileID][e] ^ zob[tileID][neighbor] ^ zob[EMPTY_ID][neighbor] ^ zob[EMPTY_ID][e];\n                next.hash = new_hash;\n                if (global_hash.count(new_hash)) continue;\n\n                int new_h = cur.h;\n                new_h += manDist[tileID][e] - manDist[tileID][neighbor];\n                new_h += manDist[EMPTY_ID][neighbor] - manDist[EMPTY_ID][e];\n                next.h = new_h;\n                next.parent = idx;\n                next.move = move_chars[d];\n\n                if (new_h == 0) goal_node = nodes.size();\n\n                nodes.push_back(next);\n                global_hash.insert(new_hash);\n                next_nodes.push_back(nodes.size()-1);\n\n                if (new_h < best_h) {\n                    best_h = new_h;\n                    best_h_node = nodes.size()-1;\n                }\n                if (goal_node != -1) break;\n            }\n            if (goal_node != -1) break;\n        }\n        if (goal_node != -1) break;\n        if (next_nodes.empty()) break;\n\n        sort(next_nodes.begin(), next_nodes.end(), [&](int a, int b) {\n            return nodes[a].h < nodes[b].h;\n        });\n        if (next_nodes.size() > beam_width) next_nodes.resize(beam_width);\n        current_beam = move(next_nodes);\n    }\n\n    // ---------- Output ----------\n    int out_node = (goal_node != -1) ? goal_node : best_h_node;\n    string seq;\n    while (nodes[out_node].parent != -1) {\n        seq.push_back(nodes[out_node].move);\n        out_node = nodes[out_node].parent;\n    }\n    reverse(seq.begin(), seq.end());\n    if ((int)seq.length() > T) seq = seq.substr(0, T);\n    cout << seq << endl;\n\n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <numeric>\n#include <cstdlib>\n#include <tuple>\n#include <cmath>\n#include <climits>\n\nusing namespace std;\n\nstruct Point { int x, y; };\nstruct Line { int p1x, p1y, p2x, p2y; };\n\nvector<int> a(11);\nint total_attendees;\n\nlong long cross(const Line& L, const Point& p) {\n    long long dx = L.p2x - L.p1x;\n    long long dy = L.p2y - L.p1y;\n    long long px = p.x - L.p1x;\n    long long py = p.y - L.p1y;\n    return dx * py - dy * px;\n}\n\nbool line_intersects_circle(const Line& L) {\n    long long dx = L.p2x - L.p1x;\n    long long dy = L.p2y - L.p1y;\n    long long cross_val = std::llabs((long long)L.p1x * L.p2y - (long long)L.p1y * L.p2x);\n    long long lhs = cross_val * cross_val;\n    long long rhs = 100000000LL * (dx * dx + dy * dy);\n    return lhs <= rhs;\n}\n\nint side(const Line& L, const Point& p) {\n    long long c = cross(L, p);\n    if (c > 0) return 1;\n    if (c < 0) return -1;\n    return 0;\n}\n\nstruct State {\n    vector<int> cell_of_point;\n    vector<int> cell_count;\n    vector<vector<int>> cell_points;\n    int score; // internal score = 100*sum(min(a,b)) - large_pieces\n};\n\nint compute_score_from_counts(const vector<int>& cell_count) {\n    int b[11] = {0};\n    int large = 0;\n    for (int cnt : cell_count) {\n        if (cnt > 0 && cnt <= 10) b[cnt]++;\n        else if (cnt > 10) large++;\n    }\n    int res = 0;\n    for (int d = 1; d <= 10; ++d) res += min(a[d], b[d]);\n    return res * 100 - large;\n}\n\nState build_initial_state(const vector<Point>& pts) {\n    State st;\n    int N = pts.size();\n    st.cell_of_point.assign(N, 0);\n    st.cell_count = {N};\n    st.cell_points = { vector<int>(N) };\n    iota(st.cell_points[0].begin(), st.cell_points[0].end(), 0);\n    st.score = compute_score_from_counts(st.cell_count);\n    return st;\n}\n\ntuple<vector<int>, vector<int>, int> simulate(const State& st, const Line& L, const vector<Point>& pts) {\n    int N = pts.size();\n    int C = st.cell_count.size();\n    vector<int> new_count(2 * C, 0);\n    vector<int> bits(N);\n    long long dx = L.p2x - L.p1x;\n    long long dy = L.p2y - L.p1y;\n    for (int i = 0; i < N; ++i) {\n        int old_c = st.cell_of_point[i];\n        long long px = pts[i].x - L.p1x;\n        long long py = pts[i].y - L.p1y;\n        long long c = dx * py - dy * px;\n        if (c == 0) return { {}, {}, -1 };\n        int bit = (c > 0) ? 1 : 0;\n        bits[i] = bit;\n        int nc = old_c * 2 + bit;\n        new_count[nc]++;\n    }\n    int score = compute_score_from_counts(new_count);\n    return {new_count, bits, score};\n}\n\nvoid apply_line(State& st, const Line& /*L*/, const vector<int>& new_count,\n                const vector<int>& bits, const vector<Point>& pts) {\n    int N = pts.size();\n    int C = st.cell_count.size();\n    vector<int> new_cell_id(2 * C, -1);\n    int new_C = 0;\n    for (int c = 0; c < 2 * C; ++c)\n        if (new_count[c] > 0) new_cell_id[c] = new_C++;\n    st.cell_count.resize(new_C);\n    st.cell_points.assign(new_C, vector<int>());\n    for (int c = 0; c < 2 * C; ++c) {\n        if (new_count[c] > 0) {\n            int nid = new_cell_id[c];\n            st.cell_count[nid] = new_count[c];\n            st.cell_points[nid].reserve(new_count[c]);\n        }\n    }\n    for (int i = 0; i < N; ++i) {\n        int old_c = st.cell_of_point[i];\n        int nid = new_cell_id[old_c * 2 + bits[i]];\n        st.cell_of_point[i] = nid;\n        st.cell_points[nid].push_back(i);\n    }\n    st.score = compute_score_from_counts(st.cell_count);\n}\n\n// ----- candidate generators -----\nLine random_line_through_cake(mt19937& rng) {\n    uniform_int_distribution<int> dist_coord(-10000, 10000);\n    uniform_int_distribution<int> dist_d(-1000, 1000);\n    while (true) {\n        int x = dist_coord(rng);\n        int y = dist_coord(rng);\n        if ((long long)x * x + (long long)y * y < 100000000LL) {\n            int dx = dist_d(rng);\n            int dy = dist_d(rng);\n            if (dx == 0 && dy == 0) dx = 1;\n            return {x, y, x + dx, y + dy};\n        }\n    }\n}\n\nLine random_cell_split_line(const State& st, const vector<Point>& pts, mt19937& rng) {\n    const auto& cell_points = st.cell_points;\n    vector<int> valid_cells;\n    for (int c = 0; c < (int)cell_points.size(); ++c)\n        if (cell_points[c].size() >= 2) valid_cells.push_back(c);\n    if (valid_cells.empty()) return random_line_through_cake(rng);\n    uniform_int_distribution<int> dist_cell(0, valid_cells.size() - 1);\n    int c = valid_cells[dist_cell(rng)];\n    const auto& pvec = cell_points[c];\n    uniform_int_distribution<int> dist_pt(0, pvec.size() - 1);\n    int i1 = pvec[dist_pt(rng)];\n    int i2 = pvec[dist_pt(rng)];\n    while (i2 == i1) i2 = pvec[dist_pt(rng)];\n    Point p1 = pts[i1], p2 = pts[i2];\n    int mx = (p1.x + p2.x) / 2;\n    int my = (p1.y + p2.y) / 2;\n    uniform_int_distribution<int> dist_d(-200, 200);\n    int dx = dist_d(rng);\n    int dy = dist_d(rng);\n    if (dx == 0 && dy == 0) dx = 1;\n    Line L = {mx, my, mx + dx, my + dy};\n    int s1 = side(L, p1), s2 = side(L, p2);\n    if (s1 == s2 || s1 == 0 || s2 == 0) {\n        int ndx = -dy, ndy = dx;\n        dx = ndx; dy = ndy;\n        L = {mx, my, mx + dx, my + dy};\n        s1 = side(L, p1); s2 = side(L, p2);\n        if (s1 == s2 || s1 == 0 || s2 == 0) {\n            return random_line_through_cake(rng);\n        }\n    }\n    return L;\n}\n\nLine random_separating_line(const vector<Point>& pts, int N, mt19937& rng) {\n    uniform_int_distribution<int> dist_pt(0, N - 1);\n    int i1 = dist_pt(rng);\n    int i2 = dist_pt(rng);\n    while (i2 == i1) i2 = dist_pt(rng);\n    Point p1 = pts[i1], p2 = pts[i2];\n    int mx = (p1.x + p2.x) / 2;\n    int my = (p1.y + p2.y) / 2;\n    uniform_int_distribution<int> dist_d(-1000, 1000);\n    int dx = dist_d(rng);\n    int dy = dist_d(rng);\n    if (dx == 0 && dy == 0) dx = 1;\n    Line L = {mx, my, mx + dx, my + dy};\n    if (side(L, p1) == side(L, p2) || side(L, p1) == 0 || side(L, p2) == 0) {\n        swap(dx, dy); dx = -dx;\n        L = {mx, my, mx + dx, my + dy};\n        if (side(L, p1) == side(L, p2) || side(L, p1) == 0 || side(L, p2) == 0)\n            return random_line_through_cake(rng);\n    }\n    return L;\n}\n\nLine perturb_existing_line(const vector<Line>& lines, mt19937& rng) {\n    if (lines.empty()) return random_line_through_cake(rng);\n    uniform_int_distribution<int> dist_idx(0, lines.size() - 1);\n    uniform_int_distribution<int> dist_delta(-200, 200);\n    uniform_int_distribution<int> dist_coord(0, 3);\n    Line L = lines[dist_idx(rng)];\n    int delta = dist_delta(rng);\n    int coord = dist_coord(rng);\n    if (coord == 0) L.p1x += delta;\n    else if (coord == 1) L.p1y += delta;\n    else if (coord == 2) L.p2x += delta;\n    else L.p2y += delta;\n    if (L.p1x == L.p2x && L.p1y == L.p2y) L.p1x += 1;\n    return L;\n}\n\n// attempt to find a line separating point sets A and B\nLine try_separate(const vector<Point>& A, const vector<Point>& B, mt19937& rng, int max_tries) {\n    uniform_real_distribution<double> angle_dist(0, 2 * M_PI);\n    for (int t = 0; t < max_tries; ++t) {\n        double angle = angle_dist(rng);\n        long long dx = (long long)(cos(angle) * 10000);\n        long long dy = (long long)(sin(angle) * 10000);\n        if (dx == 0 && dy == 0) continue;\n        long long minA = LLONG_MAX, maxA = LLONG_MIN;\n        for (const auto& p : A) {\n            long long proj = dx * p.x + dy * p.y;\n            if (proj < minA) minA = proj;\n            if (proj > maxA) maxA = proj;\n        }\n        long long minB = LLONG_MAX, maxB = LLONG_MIN;\n        for (const auto& p : B) {\n            long long proj = dx * p.x + dy * p.y;\n            if (proj < minB) minB = proj;\n            if (proj > maxB) maxB = proj;\n        }\n        if (maxA < minB || maxB < minA) {\n            long long mid = (maxA < minB) ? (maxA + minB) / 2 : (maxB + minA) / 2;\n            // line: dx*x + dy*y = mid\n            // generate two distinct integer points on this line\n            int px, py, qx, qy;\n            if (dx == 0) {\n                if (dy == 0) continue;\n                py = mid / dy;\n                px = 0;\n                qx = 10000;\n                qy = (mid - dx * qx) / dy;\n            } else {\n                if (dy != 0) {\n                    px = 0; py = mid / dy;\n                    qx = 10000; qy = (mid - dx * 10000) / dy;\n                } else {\n                    px = mid / dx; py = 0;\n                    qx = mid / dx; qy = 10000;\n                }\n            }\n            if (px == qx && py == qy) continue;\n            return {px, py, qx, qy};\n        }\n    }\n    return {0,0,0,0}; // invalid\n}\n\nLine targeted_candidate(const State& st, const vector<Point>& pts, mt19937& rng) {\n    // find unmet demands\n    vector<int> need(11, 0);\n    for (int d = 1; d <= 10; ++d) {\n        int bd = 0;\n        for (int cnt : st.cell_count) if (cnt == d) bd++;\n        if (bd < a[d]) need[d] = a[d] - bd;\n    }\n    bool any_need = false;\n    for (int d = 1; d <= 10; ++d) if (need[d] > 0) any_need = true;\n    if (!any_need) return random_line_through_cake(rng);\n\n    // pick a random unmet d\n    vector<int> unmet;\n    for (int d = 1; d <= 10; ++d) if (need[d] > 0) unmet.push_back(d);\n    uniform_int_distribution<int> dist_d(0, unmet.size() - 1);\n    int d = unmet[dist_d(rng)];\n\n    // find cells with count > d (so we can split)\n    vector<int> cells;\n    for (int c = 0; c < (int)st.cell_count.size(); ++c)\n        if (st.cell_count[c] > d) cells.push_back(c);\n    if (cells.empty()) return random_line_through_cake(rng);\n\n    uniform_int_distribution<int> dist_cell(0, cells.size() - 1);\n    int c = cells[dist_cell(rng)];\n    const auto& pvec = st.cell_points[c];\n    int C = pvec.size();\n    if (C < d + 1) return random_line_through_cake(rng);\n\n    // pick random subset of size d\n    vector<int> perm(C);\n    iota(perm.begin(), perm.end(), 0);\n    shuffle(perm.begin(), perm.end(), rng);\n    vector<Point> A(d);\n    for (int i = 0; i < d; ++i) A[i] = pts[pvec[perm[i]]];\n    vector<Point> B(C - d);\n    for (int i = d; i < C; ++i) B[i - d] = pts[pvec[perm[i]]];\n\n    Line L = try_separate(A, B, rng, 20);\n    if (L.p1x == 0 && L.p1y == 0 && L.p2x == 0 && L.p2y == 0)\n        return random_line_through_cake(rng);\n    return L;\n}\n\nint main() {\n    ios::sync_with_stdio(false); cin.tie(0);\n    auto start_time = chrono::steady_clock::now();\n\n    int N, K; cin >> N >> K;\n    total_attendees = 0;\n    for (int d = 1; d <= 10; ++d) { cin >> a[d]; total_attendees += a[d]; }\n    vector<Point> pts(N);\n    for (int i = 0; i < N; ++i) cin >> pts[i].x >> pts[i].y;\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    State st = build_initial_state(pts);\n    vector<Line> lines;\n    lines.reserve(K);\n\n    const double TIME_LIMIT = 2.95;\n    const int NUM_GREEDY_CANDIDATES = 300;\n    const int NUM_LOCAL_CANDIDATES = 200;\n\n    // greedy addition\n    while ((int)lines.size() < K) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n        if (elapsed > TIME_LIMIT) break;\n        int best_score = -1e9;\n        Line best_line;\n        vector<int> best_new_count, best_bits;\n        for (int t = 0; t < NUM_GREEDY_CANDIDATES; ++t) {\n            Line cand;\n            int type = uniform_int_distribution<int>(0, 11)(rng);\n            if (type < 2) cand = random_line_through_cake(rng);\n            else if (type < 5) cand = random_cell_split_line(st, pts, rng);\n            else if (type < 8) cand = random_separating_line(pts, N, rng);\n            else if (type < 10) cand = perturb_existing_line(lines, rng);\n            else cand = targeted_candidate(st, pts, rng);\n            if (!line_intersects_circle(cand)) continue;\n            auto [new_count, bits, score] = simulate(st, cand, pts);\n            if (score < 0) continue; // hits a strawberry\n            if (score > best_score) {\n                best_score = score;\n                best_line = cand;\n                best_new_count = std::move(new_count);\n                best_bits = std::move(bits);\n            }\n        }\n        if (best_score < 0) { // fallback: any valid line\n            while (true) {\n                Line cand = random_line_through_cake(rng);\n                if (!line_intersects_circle(cand)) continue;\n                auto [new_count, bits, score] = simulate(st, cand, pts);\n                if (score >= 0) {\n                    best_line = cand;\n                    best_new_count = std::move(new_count);\n                    best_bits = std::move(bits);\n                    break;\n                }\n            }\n        }\n        apply_line(st, best_line, best_new_count, best_bits, pts);\n        lines.push_back(best_line);\n    }\n\n    // local search: replace lines\n    bool improved = true;\n    int local_iter = 0;\n    while (improved && (int)lines.size() == K && local_iter < 6) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n        if (elapsed > TIME_LIMIT) break;\n        improved = false;\n        local_iter++;\n        vector<int> order(K);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n        for (int idx : order) {\n            elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n            if (elapsed > TIME_LIMIT) break;\n            Line old_line = lines[idx];\n            State curr = build_initial_state(pts);\n            for (int j = 0; j < K; ++j) {\n                if (j == idx) continue;\n                auto [new_count, bits, score] = simulate(curr, lines[j], pts);\n                apply_line(curr, lines[j], new_count, bits, pts);\n            }\n            int best_score = curr.score;\n            Line best_line;\n            vector<int> best_new_count, best_bits;\n            for (int t = 0; t < NUM_LOCAL_CANDIDATES; ++t) {\n                Line cand;\n                int type = uniform_int_distribution<int>(0, 11)(rng);\n                if (type < 2) cand = random_line_through_cake(rng);\n                else if (type < 5) cand = random_cell_split_line(curr, pts, rng);\n                else if (type < 8) cand = random_separating_line(pts, N, rng);\n                else if (type < 10) cand = perturb_existing_line(lines, rng);\n                else cand = targeted_candidate(curr, pts, rng);\n                if (!line_intersects_circle(cand)) continue;\n                auto [new_count, bits, score] = simulate(curr, cand, pts);\n                if (score < 0) continue;\n                if (score > best_score) {\n                    best_score = score;\n                    best_line = cand;\n                    best_new_count = std::move(new_count);\n                    best_bits = std::move(bits);\n                }\n            }\n            if (best_score > curr.score) {\n                lines[idx] = best_line;\n                improved = true;\n            } else {\n                lines[idx] = old_line;\n            }\n        }\n        if (improved) {\n            st = build_initial_state(pts);\n            for (const Line& L : lines) {\n                auto [new_count, bits, score] = simulate(st, L, pts);\n                apply_line(st, L, new_count, bits, pts);\n            }\n        }\n    }\n\n    // output\n    cout << lines.size() << \"\\n\";\n    for (const Line& L : lines) {\n        cout << L.p1x << \" \" << L.p1y << \" \" << L.p2x << \" \" << L.p2y << \"\\n\";\n    }\n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <array>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <numeric>\n\nusing namespace std;\n\nstruct Pt { int x, y; };\n\nint main() {\n    auto global_start = chrono::steady_clock::now();\n    auto elapsed = [&]() { return chrono::duration<double>(chrono::steady_clock::now() - global_start).count(); };\n\n    int N, M;\n    cin >> N >> M;\n    vector<Pt> initial_dots(M);\n    for (int i = 0; i < M; ++i) cin >> initial_dots[i].x >> initial_dots[i].y;\n\n    int c = (N - 1) / 2;\n    vector<vector<int>> weight(N, vector<int>(N));\n    long long S = 0, initial_sum = 0;\n    for (int x = 0; x < N; ++x) for (int y = 0; y < N; ++y) {\n        weight[x][y] = (x - c) * (x - c) + (y - c) * (y - c) + 1;\n        S += weight[x][y];\n    }\n    for (auto& p : initial_dots) initial_sum += weight[p.x][p.y];\n\n    auto run_sim = [&](uint64_t seed) {\n        mt19937 rng(static_cast<unsigned int>(seed));\n\n        vector<vector<bool>> dot(N, vector<bool>(N, false));\n        vector<vector<bool>> used_h(N - 1, vector<bool>(N, false));\n        vector<vector<bool>> used_v(N, vector<bool>(N - 1, false));\n        vector<vector<bool>> used_d1(N - 1, vector<bool>(N - 1, false));\n        vector<vector<bool>> used_d2(N - 1, vector<bool>(N, false));\n        vector<vector<int>> row_dots(N), col_dots(N);\n        int diag_offs = N - 1;\n        vector<vector<int>> diag1(2 * N - 1), diag2(2 * N - 1);\n\n        for (auto& p : initial_dots) {\n            dot[p.x][p.y] = true;\n            row_dots[p.y].push_back(p.x);\n            col_dots[p.x].push_back(p.y);\n            diag1[p.x - p.y + diag_offs].push_back(p.y * N + p.x); // encode as index\n            diag2[p.x + p.y].push_back(p.y * N + p.x);\n        }\n        long long cur_sum = initial_sum;\n        vector<array<Pt, 4>> history;\n\n        auto segment_check = [&](Pt a, Pt b, bool check_only) -> bool {\n            int dx = b.x - a.x, dy = b.y - a.y;\n            int steps = max(abs(dx), abs(dy));\n            int sx = (dx == 0 ? 0 : (dx > 0 ? 1 : -1));\n            int sy = (dy == 0 ? 0 : (dy > 0 ? 1 : -1));\n            int cx = a.x, cy = a.y;\n            for (int s = 1; s <= steps; ++s) {\n                int nx = cx + sx, ny = cy + sy;\n                if (s < steps && dot[nx][ny]) return false;\n                if (sx != 0 && sy == 0) {\n                    int x = min(cx, nx), y = cy;\n                    if (check_only) { if (used_h[x][y]) return false; }\n                    else used_h[x][y] = true;\n                } else if (sx == 0 && sy != 0) {\n                    int x = cx, y = min(cy, ny);\n                    if (check_only) { if (used_v[x][y]) return false; }\n                    else used_v[x][y] = true;\n                } else if (sx == 1 && sy == 1) {\n                    if (check_only) { if (used_d1[cx][cy]) return false; }\n                    else used_d1[cx][cy] = true;\n                } else if (sx == -1 && sy == -1) {\n                    if (check_only) { if (used_d1[nx][ny]) return false; }\n                    else used_d1[nx][ny] = true;\n                } else if (sx == 1 && sy == -1) {\n                    if (check_only) { if (used_d2[cx][cy]) return false; }\n                    else used_d2[cx][cy] = true;\n                } else if (sx == -1 && sy == 1) {\n                    if (check_only) { if (used_d2[nx][ny]) return false; }\n                    else used_d2[nx][ny] = true;\n                } else return false;\n                cx = nx; cy = ny;\n            }\n            return true;\n        };\n\n        auto is_valid = [&](const array<Pt, 4>& p) {\n            if (dot[p[0].x][p[0].y]) return false;\n            if (!dot[p[1].x][p[1].y] || !dot[p[2].x][p[2].y] || !dot[p[3].x][p[3].y]) return false;\n            for (int i = 0; i < 4; ++i)\n                if (!segment_check(p[i], p[(i + 1) % 4], true)) return false;\n            return true;\n        };\n\n        auto apply_move = [&](const array<Pt, 4>& p) {\n            int x0 = p[0].x, y0 = p[0].y;\n            dot[x0][y0] = true;\n            row_dots[y0].push_back(x0);\n            col_dots[x0].push_back(y0);\n            int enc = y0 * N + x0;\n            diag1[x0 - y0 + diag_offs].push_back(enc);\n            diag2[x0 + y0].push_back(enc);\n            cur_sum += weight[x0][y0];\n            for (int i = 0; i < 4; ++i)\n                segment_check(p[i], p[(i + 1) % 4], false);\n        };\n\n        auto add_axis_small = [&](int x, int y, vector<array<Pt, 4>>& cands) {\n            if (x + 1 < N && y + 1 < N) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x + 1, y}, Pt{x + 1, y + 1}, Pt{x, y + 1}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n            if (x > 0 && y + 1 < N) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x, y + 1}, Pt{x - 1, y + 1}, Pt{x - 1, y}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n            if (x > 0 && y > 0) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x - 1, y}, Pt{x - 1, y - 1}, Pt{x, y - 1}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n            if (x + 1 < N && y > 0) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x, y - 1}, Pt{x + 1, y - 1}, Pt{x + 1, y}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n        };\n\n        auto add_diamond_small = [&](int x, int y, vector<array<Pt, 4>>& cands) {\n            if (x + 2 < N && y >= 1 && y + 1 < N) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x + 1, y + 1}, Pt{x + 2, y}, Pt{x + 1, y - 1}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n            if (x >= 1 && x + 1 < N && y >= 2) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x + 1, y - 1}, Pt{x, y - 2}, Pt{x - 1, y - 1}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n            if (x >= 2 && y >= 1 && y + 1 < N) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x - 1, y - 1}, Pt{x - 2, y}, Pt{x - 1, y + 1}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n            if (x >= 1 && x + 1 < N && y + 2 < N) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x - 1, y + 1}, Pt{x, y + 2}, Pt{x + 1, y + 1}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n        };\n\n        auto add_axis_large = [&](int x1, int y1, vector<array<Pt, 4>>& cands) {\n            for (int x2 : row_dots[y1]) {\n                if (x2 == x1) continue;\n                for (int y2 : col_dots[x1]) {\n                    if (y2 == y1) continue;\n                    if (!dot[x2][y2]) continue;\n                    array<Pt, 4> p = {Pt{x1, y1}, Pt{x2, y1}, Pt{x2, y2}, Pt{x1, y2}};\n                    if (is_valid(p)) cands.push_back(p);\n                }\n            }\n        };\n\n        auto add_general_diamond = [&](int x1, int y1, vector<array<Pt, 4>>& cands) {\n            int d1 = x1 - y1 + diag_offs;\n            int d2 = x1 + y1;\n            const auto& list1 = diag1[d1];\n            const auto& list2 = diag2[d2];\n            for (int enc2 : list1) {\n                int x2 = enc2 % N, y2 = enc2 / N;\n                if (x2 == x1 && y2 == y1) continue;\n                for (int enc4 : list2) {\n                    int x4 = enc4 % N, y4 = enc4 / N;\n                    if (x4 == x1 && y4 == y1) continue;\n                    int x3 = x2 + x4 - x1;\n                    int y3 = y2 + y4 - y1;\n                    if (x3 < 0 || x3 >= N || y3 < 0 || y3 >= N) continue;\n                    if (!dot[x3][y3]) continue;\n                    array<Pt, 4> p = {Pt{x1, y1}, Pt{x2, y2}, Pt{x3, y3}, Pt{x4, y4}};\n                    if (is_valid(p)) cands.push_back(p);\n                }\n            }\n        };\n\n        while (true) {\n            if (elapsed() > 4.8) break;\n            vector<array<Pt, 4>> cands;\n            // small moves\n            for (int x = 0; x < N; ++x)\n                for (int y = 0; y < N; ++y) {\n                    if (dot[x][y]) continue;\n                    add_axis_small(x, y, cands);\n                    add_diamond_small(x, y, cands);\n                }\n\n            if (cands.empty()) {\n                // large moves, search by descending weight to find good candidates quickly\n                vector<int> empty_idx;\n                for (int x = 0; x < N; ++x)\n                    for (int y = 0; y < N; ++y)\n                        if (!dot[x][y]) empty_idx.push_back(y * N + x);\n                sort(empty_idx.begin(), empty_idx.end(), [&](int a, int b) {\n                    return weight[a % N][a / N] > weight[b % N][b / N];\n                });\n                for (int enc : empty_idx) {\n                    if (cands.size() >= 30) break; // enough\n                    int x = enc % N, y = enc / N;\n                    add_axis_large(x, y, cands);\n                    add_general_diamond(x, y, cands);\n                }\n                if (cands.empty()) break;\n            }\n\n            // selection\n            vector<int> w(cands.size());\n            for (size_t i = 0; i < cands.size(); ++i)\n                w[i] = weight[cands[i][0].x][cands[i][0].y];\n            int max_w = *max_element(w.begin(), w.end());\n            vector<int> best_idx;\n            for (size_t i = 0; i < cands.size(); ++i)\n                if (w[i] == max_w) best_idx.push_back(static_cast<int>(i));\n            int pick;\n            if (best_idx.size() == cands.size() || (rng() % 100) < 80) {\n                pick = best_idx[rng() % best_idx.size()];\n            } else {\n                pick = rng() % cands.size();\n            }\n            apply_move(cands[pick]);\n            history.push_back(cands[pick]);\n        }\n        return make_pair(cur_sum, history);\n    };\n\n    long long best_sum = -1;\n    vector<array<Pt, 4>> best_hist;\n    int sim = 0;\n    while (true) {\n        if (elapsed() > 4.85) break;\n        uint64_t seed = chrono::steady_clock::now().time_since_epoch().count() + sim * 12345;\n        auto [sum, hist] = run_sim(seed);\n        if (sum > best_sum) {\n            best_sum = sum;\n            best_hist = move(hist);\n        }\n        ++sim;\n    }\n\n    cout << best_hist.size() << \"\\n\";\n    for (auto& p : best_hist) {\n        cout << p[0].x << \" \" << p[0].y << \" \"\n             << p[1].x << \" \" << p[1].y << \" \"\n             << p[2].x << \" \" << p[2].y << \" \"\n             << p[3].x << \" \" << p[3].y << \"\\n\";\n    }\n    return 0;\n}","ahc015":"#include <iostream>\n#include <cstring>\nusing namespace std;\n\nconst char DIR[4] = {'F', 'B', 'L', 'R'};\n\n// BFS queue and visited array for sum-of-squares computation\nstatic int q[100];\nstatic int vis[100];\nstatic int vis_ver = 0;\n\n// Compute sum of squares of connected component sizes\nint sum_sq(const int* b) {\n    ++vis_ver;\n    int tot = 0;\n    for (int i = 0; i < 100; ++i) {\n        if (b[i] && vis[i] != vis_ver) {\n            int f = b[i];\n            int head = 0, tail = 0;\n            q[tail++] = i;\n            vis[i] = vis_ver;\n            int sz = 0;\n            while (head < tail) {\n                int idx = q[head++];\n                ++sz;\n                int r = idx / 10, c = idx % 10;\n                if (r > 0 && b[idx - 10] == f && vis[idx - 10] != vis_ver)\n                    vis[idx - 10] = vis_ver, q[tail++] = idx - 10;\n                if (r < 9 && b[idx + 10] == f && vis[idx + 10] != vis_ver)\n                    vis[idx + 10] = vis_ver, q[tail++] = idx + 10;\n                if (c > 0 && b[idx - 1] == f && vis[idx - 1] != vis_ver)\n                    vis[idx - 1] = vis_ver, q[tail++] = idx - 1;\n                if (c < 9 && b[idx + 1] == f && vis[idx + 1] != vis_ver)\n                    vis[idx + 1] = vis_ver, q[tail++] = idx + 1;\n            }\n            tot += sz * sz;\n        }\n    }\n    return tot;\n}\n\n// Apply a tilt: 0=F, 1=B, 2=L, 3=R\nvoid tilt(const int* src, int dir, int* dst) {\n    if (dir == 0) {  // Forward\n        for (int c = 0; c < 10; ++c) {\n            int d = 0;\n            for (int r = 0; r < 10; ++r) {\n                int v = src[r * 10 + c];\n                if (v) dst[d++ * 10 + c] = v;\n            }\n            for (; d < 10; ++d) dst[d * 10 + c] = 0;\n        }\n    } else if (dir == 1) {  // Backward\n        for (int c = 0; c < 10; ++c) {\n            int d = 9;\n            for (int r = 9; r >= 0; --r) {\n                int v = src[r * 10 + c];\n                if (v) dst[d-- * 10 + c] = v;\n            }\n            for (; d >= 0; --d) dst[d * 10 + c] = 0;\n        }\n    } else if (dir == 2) {  // Left\n        for (int r = 0; r < 10; ++r) {\n            int base = r * 10, d = 0;\n            for (int c = 0; c < 10; ++c) {\n                int v = src[base + c];\n                if (v) dst[base + d++] = v;\n            }\n            for (; d < 10; ++d) dst[base + d] = 0;\n        }\n    } else {  // Right\n        for (int r = 0; r < 10; ++r) {\n            int base = r * 10, d = 9;\n            for (int c = 9; c >= 0; --c) {\n                int v = src[base + c];\n                if (v) dst[base + d--] = v;\n            }\n            for (; d >= 0; --d) dst[base + d] = 0;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int flavors[100];\n    for (int i = 0; i < 100; ++i) cin >> flavors[i];\n\n    int board[100] = {0};\n\n    for (int t = 0; t < 100; ++t) {\n        int p;\n        cin >> p;\n\n        // Place the candy in the p-th empty cell\n        int pos = -1, empty_cnt = 0;\n        for (int i = 0; i < 100; ++i) {\n            if (board[i] == 0) {\n                ++empty_cnt;\n                if (empty_cnt == p) { pos = i; break; }\n            }\n        }\n        board[pos] = flavors[t];\n\n        // Last move: any output is fine\n        if (t == 99) {\n            cout << \"F\\n\" << flush;\n            break;\n        }\n\n        int next_f = flavors[t + 1];\n        int best_dir = 0;\n        double best_val = -1e18;\n\n        // Try all 4 tilts as the first move\n        for (int d0 = 0; d0 < 4; ++d0) {\n            int b1[100];\n            tilt(board, d0, b1);\n\n            // Collect currently empty cells in the tilted board\n            int empty[100];\n            int n_empty = 0;\n            for (int i = 0; i < 100; ++i)\n                if (b1[i] == 0) empty[n_empty++] = i;\n\n            double val;\n            if (n_empty == 0) {\n                val = sum_sq(b1);\n            } else {\n                int total_sq = 0;\n                for (int i = 0; i < n_empty; ++i) {\n                    int e = empty[i];\n                    b1[e] = next_f;          // temporarily place next candy\n                    int best_sq = -1;\n                    for (int d2 = 0; d2 < 4; ++d2) {\n                        int b3[100];\n                        tilt(b1, d2, b3);\n                        int sq = sum_sq(b3);\n                        if (sq > best_sq) best_sq = sq;\n                    }\n                    total_sq += best_sq;\n                    b1[e] = 0;               // remove the candy\n                }\n                val = (double)total_sq / n_empty;\n            }\n\n            if (val > best_val) {\n                best_val = val;\n                best_dir = d0;\n            }\n        }\n\n        cout << DIR[best_dir] << '\\n' << flush;\n\n        // Apply the chosen tilt for the real game state\n        int nb[100];\n        tilt(board, best_dir, nb);\n        memcpy(board, nb, sizeof(board));\n    }\n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <numeric>\n\nusing namespace std;\n\nstruct GraphInfo {\n    vector<vector<bool>> mat;\n    vector<int> sorted_deg;\n    string adj_str;\n};\n\n// Build M threshold graphs with minimum L1 distance between degree sequences\n// based on target D_min derived from epsilon and N.\nvector<GraphInfo> build_threshold_graphs(int N, int M, double eps, mt19937& rng) {\n    int L = N * (N - 1) / 2;\n    double sigma = 2.0 * sqrt(L * eps * (1.0 - eps));\n    // try different multipliers for minimum distance\n    vector<int> d_targets;\n    for (int mult = 6; mult >= 1; mult--) {\n        int d = max(1, (int)ceil(mult * sigma));\n        d_targets.push_back(d);\n    }\n    \n    int pool_size = max(M * 50, 30000);\n    bernoulli_distribution bit_dist(0.5);\n    \n    // generate a large pool of random threshold graphs\n    struct Candidate {\n        vector<int> deg;\n        string adj;\n    };\n    vector<Candidate> pool;\n    pool.reserve(pool_size);\n    \n    for (int idx = 0; idx < pool_size; idx++) {\n        // binary signature c[0] = 0, c[1..N-1] random bits\n        vector<int> c(N, 0);\n        for (int j = 1; j < N; j++) c[j] = bit_dist(rng) ? 1 : 0;\n        \n        // compute suffix sums of c\n        vector<int> suff(N+1, 0);\n        for (int j = N-1; j >= 0; j--) {\n            suff[j] = suff[j+1] + c[j];\n        }\n        \n        // compute degrees\n        vector<int> deg(N);\n        for (int i = 0; i < N; i++) {\n            deg[i] = suff[i+1] + (c[i] ? i : 0);\n        }\n        sort(deg.begin(), deg.end(), greater<int>());\n        \n        // build adjacency string in lexicographic order\n        string adj(L, '0');\n        int pos = 0;\n        for (int i = 0; i < N; i++) {\n            for (int j = i+1; j < N; j++) {\n                if (c[j] == 1) adj[pos] = '1';\n                pos++;\n            }\n        }\n        pool.push_back({move(deg), move(adj)});\n    }\n    \n    // Greedy selection trying each target distance\n    for (int D_min : d_targets) {\n        vector<Candidate> selected;\n        selected.reserve(M);\n        // randomise order\n        shuffle(pool.begin(), pool.end(), rng);\n        for (auto& cand : pool) {\n            bool ok = true;\n            for (auto& sel : selected) {\n                int dist = 0;\n                for (int i = 0; i < N; i++) {\n                    dist += abs(cand.deg[i] - sel.deg[i]);\n                }\n                if (dist < D_min) {\n                    ok = false;\n                    break;\n                }\n            }\n            if (ok) {\n                selected.push_back(cand);\n                if ((int)selected.size() == M) break;\n            }\n        }\n        if ((int)selected.size() == M) {\n            // convert to GraphInfo (with matrix for simulation)\n            vector<GraphInfo> graphs;\n            graphs.reserve(M);\n            for (auto& sel : selected) {\n                // build matrix from adj_str\n                vector<vector<bool>> mat(N, vector<bool>(N, false));\n                int pos = 0;\n                for (int i = 0; i < N; i++) {\n                    for (int j = i+1; j < N; j++) {\n                        if (sel.adj[pos] == '1') {\n                            mat[i][j] = mat[j][i] = true;\n                        }\n                        pos++;\n                    }\n                }\n                graphs.push_back({move(mat), move(sel.deg), move(sel.adj)});\n            }\n            return graphs;\n        }\n    }\n    return {}; // failed\n}\n\n// Simulate 100 queries and return number of wrong predictions\nint simulate_errors(int N, const vector<GraphInfo>& graphs, double eps, mt19937& rng) {\n    int M = (int)graphs.size();\n    uniform_int_distribution<int> s_dist(0, M-1);\n    uniform_real_distribution<double> flip_dist(0.0, 1.0);\n    int errors = 0;\n    \n    for (int q = 0; q < 100; q++) {\n        int s = s_dist(rng);\n        auto noisy_mat = graphs[s].mat;\n        \n        // apply noise\n        for (int i = 0; i < N; i++) {\n            for (int j = i+1; j < N; j++) {\n                if (flip_dist(rng) < eps) {\n                    noisy_mat[i][j] = !noisy_mat[i][j];\n                    noisy_mat[j][i] = noisy_mat[i][j];\n                }\n            }\n        }\n        \n        // random shuffle\n        vector<int> perm(N);\n        iota(perm.begin(), perm.end(), 0);\n        shuffle(perm.begin(), perm.end(), rng);\n        \n        // build H_mat using the permuted indices\n        vector<vector<bool>> H_mat(N, vector<bool>(N, false));\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (noisy_mat[i][j]) {\n                    int ui = perm[i], uj = perm[j];\n                    H_mat[ui][uj] = true;\n                }\n            }\n        }\n        \n        // compute degrees of H (undirected, no self-loops)\n        vector<int> H_deg(N, 0);\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (H_mat[i][j]) H_deg[i]++;\n            }\n        }\n        sort(H_deg.begin(), H_deg.end(), greater<int>());\n        \n        // nearest neighbour\n        int best_t = 0;\n        int best_dist = 1e9;\n        for (int t = 0; t < M; t++) {\n            int dist = 0;\n            for (int i = 0; i < N; i++) {\n                dist += abs(H_deg[i] - graphs[t].sorted_deg[i]);\n            }\n            if (dist < best_dist) {\n                best_dist = dist;\n                best_t = t;\n            }\n        }\n        if (best_t != s) errors++;\n    }\n    return errors;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int M;\n    double eps;\n    cin >> M >> eps;\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    double best_score = -1.0;\n    int best_N = 20;\n    vector<GraphInfo> best_graphs;\n    \n    auto start_time = chrono::steady_clock::now();\n    auto time_limit = chrono::milliseconds(4700);\n    \n    // Search over possible number of vertices\n    for (int N = 4; N <= 100; N++) {\n        auto now = chrono::steady_clock::now();\n        if (now - start_time > time_limit) break;\n        \n        auto graphs = build_threshold_graphs(N, M, eps, rng);\n        if (graphs.empty()) continue;\n        \n        // evaluate by simulation\n        int total_err = 0;\n        int sims = 3;\n        for (int s = 0; s < sims; s++) {\n            total_err += simulate_errors(N, graphs, eps, rng);\n        }\n        double avg_err = (double)total_err / sims;\n        double score = round(1e9 * pow(0.9, avg_err) / N);\n        \n        if (score > best_score) {\n            best_score = score;\n            best_N = N;\n            best_graphs = move(graphs);\n        }\n    }\n    \n    // Fallback: if nothing succeeded, create a simple set\n    if (best_graphs.empty()) {\n        int N = 20;\n        best_N = N;\n        best_graphs = build_threshold_graphs(N, M, eps, rng);\n    }\n    \n    // Output the chosen graphs\n    cout << best_N << \"\\n\";\n    for (auto& g : best_graphs) {\n        cout << g.adj_str << \"\\n\";\n    }\n    cout.flush();\n    \n    // Answer 100 queries\n    int N = best_N;\n    for (int q = 0; q < 100; q++) {\n        string H_str;\n        cin >> H_str;\n        \n        // compute sorted degree sequence\n        vector<int> H_deg(N, 0);\n        int pos = 0;\n        for (int i = 0; i < N; i++) {\n            for (int j = i+1; j < N; j++) {\n                if (H_str[pos] == '1') {\n                    H_deg[i]++;\n                    H_deg[j]++;\n                }\n                pos++;\n            }\n        }\n        sort(H_deg.begin(), H_deg.end(), greater<int>());\n        \n        // nearest neighbour among the stored candidates\n        int best_t = 0;\n        int best_dist = 1e9;\n        for (int t = 0; t < M; t++) {\n            int dist = 0;\n            for (int i = 0; i < N; i++) {\n                dist += abs(H_deg[i] - best_graphs[t].sorted_deg[i]);\n            }\n            if (dist < best_dist) {\n                best_dist = dist;\n                best_t = t;\n            }\n        }\n        cout << best_t << \"\\n\";\n        cout.flush();\n    }\n    \n    return 0;\n}","ahc017":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <chrono>\n#include <limits>\n#include <tuple>\nusing namespace std;\nusing ll = long long;\n\nconst int INF = 1'000'000'000;\n\nint main() {\n    auto start_time = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count();\n    };\n    \n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n    vector<int> U(M), V(M), W(M);\n    vector<vector<tuple<int,int,int>>> orig_adj(N); // to, weight, edge_id\n    vector<int> edge_idx(N*N, -1);\n    for (int i = 0; i < M; ++i) {\n        cin >> U[i] >> V[i] >> W[i];\n        --U[i]; --V[i];\n        orig_adj[U[i]].emplace_back(V[i], W[i], i);\n        orig_adj[V[i]].emplace_back(U[i], W[i], i);\n        edge_idx[U[i]*N + V[i]] = i;\n        edge_idx[V[i]*N + U[i]] = i;\n    }\n    // read and ignore coordinates\n    int dummy;\n    for (int i = 0; i < N; ++i) cin >> dummy >> dummy;\n    \n    // Compute original all-pairs shortest paths and edge centralities\n    vector<int> orig(N*N, INF);\n    vector<ll> cnt(M, 0);\n    vector<int> dist(N);\n    priority_queue<pair<int,int>, vector<pair<int,int>>, greater<>> pq;\n    \n    for (int s = 0; s < N; ++s) {\n        fill(dist.begin(), dist.end(), INF);\n        vector<int> parent_node(N, -1);\n        vector<int> parent_edge(N, -1);\n        dist[s] = 0;\n        pq.push({0, s});\n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop();\n            if (d != dist[u]) continue;\n            for (auto &edge : orig_adj[u]) {\n                int v = get<0>(edge), w = get<1>(edge), eid = get<2>(edge);\n                if (dist[v] > d + w) {\n                    dist[v] = d + w;\n                    parent_node[v] = u;\n                    parent_edge[v] = eid;\n                    pq.push({dist[v], v});\n                }\n            }\n        }\n        for (int t = 0; t < N; ++t) {\n            orig[s*N + t] = dist[t];\n        }\n        // compute subtree sizes for centrality\n        vector<int> sub(N, 1);\n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) { return dist[a] > dist[b]; });\n        for (int v : order) {\n            if (v == s) continue;\n            int p = parent_node[v];\n            if (p != -1) {\n                sub[p] += sub[v];\n                if (parent_edge[v] != -1) {\n                    cnt[parent_edge[v]] += sub[v];\n                }\n            }\n        }\n    }\n    \n    // Greedy assignment based on cnt\n    vector<int> assign(M, -1);\n    vector<int> day_cnt(D, 0);\n    vector<ll> day_sum_cnt(D, 0);\n    vector<int> sorted_edges(M);\n    iota(sorted_edges.begin(), sorted_edges.end(), 0);\n    sort(sorted_edges.begin(), sorted_edges.end(), [&](int a, int b) { return cnt[a] > cnt[b]; });\n    for (int e : sorted_edges) {\n        int best_d = -1;\n        ll best_sum = numeric_limits<ll>::max();\n        for (int d = 0; d < D; ++d) {\n            if (day_cnt[d] < K && day_sum_cnt[d] < best_sum) {\n                best_sum = day_sum_cnt[d];\n                best_d = d;\n            }\n        }\n        assign[e] = best_d;\n        day_cnt[best_d]++;\n        day_sum_cnt[best_d] += cnt[e];\n    }\n    \n    // Store day edges\n    vector<vector<int>> day_edges(D);\n    for (int e = 0; e < M; ++e) {\n        day_edges[assign[e]].push_back(e);\n    }\n    \n    // Exact evaluation helper\n    vector<bool> removed(M);\n    auto compute_day_dist = [&](const vector<int>& removed_edges, vector<int>& out_dist, ll& out_diff) {\n        fill(removed.begin(), removed.end(), false);\n        for (int e : removed_edges) removed[e] = true;\n        out_dist.assign(N*N, INF);\n        out_diff = 0;\n        for (int s = 0; s < N; ++s) {\n            fill(dist.begin(), dist.end(), INF);\n            dist[s] = 0;\n            pq.push({0, s});\n            while (!pq.empty()) {\n                auto [d, u] = pq.top(); pq.pop();\n                if (d != dist[u]) continue;\n                for (auto &edge : orig_adj[u]) {\n                    int v = get<0>(edge), w = get<1>(edge), eid = get<2>(edge);\n                    if (removed[eid]) continue;\n                    if (dist[v] > d + w) {\n                        dist[v] = d + w;\n                        pq.push({dist[v], v});\n                    }\n                }\n            }\n            int base = s * N;\n            for (int t = 0; t < N; ++t) {\n                out_dist[base + t] = dist[t];\n            }\n            for (int t = s+1; t < N; ++t) {\n                out_diff += dist[t] - orig[base + t];\n            }\n        }\n    };\n    \n    // Initial exact evaluation\n    vector<vector<int>> day_dist(D);\n    vector<ll> day_diff(D, 0);\n    ll total_diff = 0;\n    for (int d = 0; d < D; ++d) {\n        compute_day_dist(day_edges[d], day_dist[d], day_diff[d]);\n        total_diff += day_diff[d];\n    }\n    ll best_total_diff = total_diff;\n    vector<int> best_assign = assign;\n    \n    // Local search\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> real_dist(0.0, 1.0);\n    \n    const int TIME_LIMIT_MS = 5800;\n    while (elapsed() < TIME_LIMIT_MS) {\n        // Pick a day A weighted by day_diff\n        ll sum_weights = accumulate(day_diff.begin(), day_diff.end(), 0LL);\n        int A;\n        if (sum_weights > 0) {\n            discrete_distribution<int> day_sel(day_diff.begin(), day_diff.end());\n            A = day_sel(rng);\n        } else {\n            uniform_int_distribution<int> unif(0, D-1);\n            A = unif(rng);\n        }\n        if (day_edges[A].empty()) continue;\n        \n        // Pick a random edge in A\n        uniform_int_distribution<int> edge_sel_A(0, (int)day_edges[A].size() - 1);\n        int e = day_edges[A][edge_sel_A(rng)];\n        \n        // Pick a random B != A with capacity\n        vector<int> candidates;\n        for (int d = 0; d < D; ++d) {\n            if (d != A && day_cnt[d] < K) candidates.push_back(d);\n        }\n        if (candidates.empty()) continue;\n        uniform_int_distribution<int> cand_sel(0, (int)candidates.size() - 1);\n        int B = candidates[cand_sel(rng)];\n        \n        // Evaluate move: remove e from A, add e to B\n        vector<int> new_A_edges = day_edges[A];\n        new_A_edges.erase(remove(new_A_edges.begin(), new_A_edges.end(), e), new_A_edges.end());\n        vector<int> new_dA;\n        ll new_diffA;\n        compute_day_dist(new_A_edges, new_dA, new_diffA);\n        \n        // New B: S_B U {e} (incremental update)\n        vector<int> oldB = day_dist[B];\n        vector<int> new_dB = oldB;\n        int u = U[e], v = V[e], w = W[e];\n        for (int i = 0; i < N; ++i) {\n            int iu = oldB[i*N + u];\n            int iv = oldB[i*N + v];\n            int base_i = i * N;\n            for (int j = 0; j < N; ++j) {\n                int idx = base_i + j;\n                int via_u = iu + w + oldB[v*N + j];\n                int via_v = iv + w + oldB[u*N + j];\n                if (via_u < new_dB[idx]) new_dB[idx] = via_u;\n                if (via_v < new_dB[idx]) new_dB[idx] = via_v;\n            }\n        }\n        ll new_diffB = 0;\n        for (int i = 0; i < N; ++i) {\n            int base = i * N;\n            for (int j = i+1; j < N; ++j) {\n                new_diffB += new_dB[base + j] - orig[base + j];\n            }\n        }\n        \n        ll new_total_diff = total_diff - day_diff[A] - day_diff[B] + new_diffA + new_diffB;\n        if (new_total_diff < total_diff) {\n            // Accept move\n            assign[e] = B;\n            day_cnt[A]--;\n            day_cnt[B]++;\n            auto &vecA = day_edges[A];\n            vecA.erase(remove(vecA.begin(), vecA.end(), e), vecA.end());\n            day_edges[B].push_back(e);\n            day_dist[A] = move(new_dA);\n            day_dist[B] = move(new_dB);\n            day_diff[A] = new_diffA;\n            day_diff[B] = new_diffB;\n            total_diff = new_total_diff;\n            if (total_diff < best_total_diff) {\n                best_total_diff = total_diff;\n                best_assign = assign;\n            }\n        }\n    }\n    \n    // Output best assignment\n    for (int i = 0; i < M; ++i) {\n        if (i) cout << \" \";\n        cout << best_assign[i] + 1;\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc019":"#include <iostream>\n#include <vector>\n#include <string>\n#include <tuple>\n#include <algorithm>\n\nusing namespace std;\n\nconst int perms[6][3] = {{0,1,2},{0,2,1},{1,0,2},{1,2,0},{2,0,1},{2,1,0}};\n\nint main() {\n    int D;\n    cin >> D;\n    vector<string> f[2], r[2];\n    for (int i = 0; i < 2; i++) {\n        f[i].resize(D);\n        for (int k = 0; k < D; k++) cin >> f[i][k];\n        r[i].resize(D);\n        for (int k = 0; k < D; k++) cin >> r[i][k];\n    }\n\n    int total = D * D * D;\n    vector<bool> allowed[2], used[2];\n    vector<vector<bool>> uncov_f[2], uncov_r[2];\n    vector<int> bid[2];\n\n    for (int i = 0; i < 2; i++) {\n        allowed[i].assign(total, false);\n        used[i].assign(total, false);\n        uncov_f[i].assign(D, vector<bool>(D, false));\n        uncov_r[i].assign(D, vector<bool>(D, false));\n        bid[i].assign(total, 0);\n    }\n\n    auto idx = [&](int x, int y, int z) {\n        return x * D * D + y * D + z;\n    };\n\n    // Initialize allowed and uncovered\n    for (int i = 0; i < 2; i++) {\n        for (int z = 0; z < D; z++) {\n            for (int x = 0; x < D; x++) {\n                if (f[i][z][x] == '1') uncov_f[i][z][x] = true;\n            }\n            for (int y = 0; y < D; y++) {\n                if (r[i][z][y] == '1') uncov_r[i][z][y] = true;\n            }\n        }\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    if (f[i][z][x] == '1' && r[i][z][y] == '1') {\n                        allowed[i][idx(x, y, z)] = true;\n                    }\n                }\n            }\n        }\n    }\n\n    auto can_place = [&](int i, int x0, int y0, int z0, int dx, int dy, int dz) {\n        for (int x = x0; x < x0 + dx; x++)\n            for (int y = y0; y < y0 + dy; y++)\n                for (int z = z0; z < z0 + dz; z++)\n                    if (!allowed[i][idx(x, y, z)] || used[i][idx(x, y, z)])\n                        return false;\n        return true;\n    };\n\n    auto count_covered = [&](int i, int x0, int y0, int z0, int dx, int dy, int dz) {\n        bool fc[14][14] = {false}, rc[14][14] = {false};\n        for (int x = x0; x < x0 + dx; x++)\n            for (int y = y0; y < y0 + dy; y++)\n                for (int z = z0; z < z0 + dz; z++) {\n                    if (uncov_f[i][z][x]) fc[z][x] = true;\n                    if (uncov_r[i][z][y]) rc[z][y] = true;\n                }\n        int cnt = 0;\n        for (int z = 0; z < D; z++) for (int x = 0; x < D; x++) if (fc[z][x]) cnt++;\n        for (int z = 0; z < D; z++) for (int y = 0; y < D; y++) if (rc[z][y]) cnt++;\n        return cnt;\n    };\n\n    auto apply_placement = [&](int i, int x0, int y0, int z0, int dx, int dy, int dz, int b_id) {\n        for (int x = x0; x < x0 + dx; x++)\n            for (int y = y0; y < y0 + dy; y++)\n                for (int z = z0; z < z0 + dz; z++) {\n                    int id = idx(x, y, z);\n                    used[i][id] = true;\n                    bid[i][id] = b_id;\n                    uncov_f[i][z][x] = false;\n                    uncov_r[i][z][y] = false;\n                }\n    };\n\n    auto compute_maximal_box = [&](int i, int sx, int sy, int sz,\n                                   int &x0, int &y0, int &z0, int &dx, int &dy, int &dz) {\n        x0 = sx; y0 = sy; z0 = sz;\n        int x1 = sx, y1 = sy, z1 = sz;\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            while (x0 > 0) {\n                bool ok = true;\n                for (int y = y0; y <= y1 && ok; y++)\n                    for (int z = z0; z <= z1 && ok; z++)\n                        if (!allowed[i][idx(x0-1, y, z)] || used[i][idx(x0-1, y, z)]) ok = false;\n                if (ok) { x0--; changed = true; } else break;\n            }\n            while (x1 < D-1) {\n                bool ok = true;\n                for (int y = y0; y <= y1 && ok; y++)\n                    for (int z = z0; z <= z1 && ok; z++)\n                        if (!allowed[i][idx(x1+1, y, z)] || used[i][idx(x1+1, y, z)]) ok = false;\n                if (ok) { x1++; changed = true; } else break;\n            }\n            while (y0 > 0) {\n                bool ok = true;\n                for (int x = x0; x <= x1 && ok; x++)\n                    for (int z = z0; z <= z1 && ok; z++)\n                        if (!allowed[i][idx(x, y0-1, z)] || used[i][idx(x, y0-1, z)]) ok = false;\n                if (ok) { y0--; changed = true; } else break;\n            }\n            while (y1 < D-1) {\n                bool ok = true;\n                for (int x = x0; x <= x1 && ok; x++)\n                    for (int z = z0; z <= z1 && ok; z++)\n                        if (!allowed[i][idx(x, y1+1, z)] || used[i][idx(x, y1+1, z)]) ok = false;\n                if (ok) { y1++; changed = true; } else break;\n            }\n            while (z0 > 0) {\n                bool ok = true;\n                for (int x = x0; x <= x1 && ok; x++)\n                    for (int y = y0; y <= y1 && ok; y++)\n                        if (!allowed[i][idx(x, y, z0-1)] || used[i][idx(x, y, z0-1)]) ok = false;\n                if (ok) { z0--; changed = true; } else break;\n            }\n            while (z1 < D-1) {\n                bool ok = true;\n                for (int x = x0; x <= x1 && ok; x++)\n                    for (int y = y0; y <= y1 && ok; y++)\n                        if (!allowed[i][idx(x, y, z1+1)] || used[i][idx(x, y, z1+1)]) ok = false;\n                if (ok) { z1++; changed = true; } else break;\n            }\n        }\n        dx = x1 - x0 + 1;\n        dy = y1 - y0 + 1;\n        dz = z1 - z0 + 1;\n    };\n\n    auto find_best_placement = [&](int j, int dx, int dy, int dz,\n                                   int &bx0, int &by0, int &bz0, int &bdx, int &bdy, int &bdz) {\n        int best_cc = -1;\n        int dims[3] = {dx, dy, dz};\n        for (auto &p : perms) {\n            int gdx = dims[p[0]], gdy = dims[p[1]], gdz = dims[p[2]];\n            for (int x0 = 0; x0 <= D - gdx; x0++) {\n                for (int y0 = 0; y0 <= D - gdy; y0++) {\n                    for (int z0 = 0; z0 <= D - gdz; z0++) {\n                        if (can_place(j, x0, y0, z0, gdx, gdy, gdz)) {\n                            int cc = count_covered(j, x0, y0, z0, gdx, gdy, gdz);\n                            if (cc > best_cc) {\n                                best_cc = cc;\n                                bx0 = x0; by0 = y0; bz0 = z0;\n                                bdx = gdx; bdy = gdy; bdz = gdz;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        return best_cc >= 0;\n    };\n\n    struct Block {\n        // for debugging / not strictly needed\n        int dx, dy, dz;\n    };\n    vector<Block> blocks;\n\n    while (true) {\n        int uncov_cnt[2] = {0, 0};\n        for (int i = 0; i < 2; i++) {\n            for (int z = 0; z < D; z++) {\n                for (int x = 0; x < D; x++) if (uncov_f[i][z][x]) uncov_cnt[i]++;\n                for (int y = 0; y < D; y++) if (uncov_r[i][z][y]) uncov_cnt[i]++;\n            }\n        }\n        if (uncov_cnt[0] == 0 && uncov_cnt[1] == 0) break;\n\n        int i = (uncov_cnt[0] >= uncov_cnt[1]) ? 0 : 1;\n        int j = 1 - i;\n\n        int z_sel = -1, x_sel = -1, y_sel = -1;\n        bool is_front = false;\n        for (int z = 0; z < D && z_sel == -1; z++) {\n            for (int x = 0; x < D; x++) if (uncov_f[i][z][x]) {\n                z_sel = z; x_sel = x; is_front = true; break;\n            }\n            if (z_sel == -1) {\n                for (int y = 0; y < D; y++) if (uncov_r[i][z][y]) {\n                    z_sel = z; y_sel = y; is_front = false; break;\n                }\n            }\n        }\n\n        vector<tuple<int,int,int>> seeds;\n        if (is_front) {\n            for (int y = 0; y < D; y++) {\n                if (allowed[i][idx(x_sel, y, z_sel)] && !used[i][idx(x_sel, y, z_sel)])\n                    seeds.emplace_back(x_sel, y, z_sel);\n            }\n        } else {\n            for (int x = 0; x < D; x++) {\n                if (allowed[i][idx(x, y_sel, z_sel)] && !used[i][idx(x, y_sel, z_sel)])\n                    seeds.emplace_back(x, y_sel, z_sel);\n            }\n        }\n        if (seeds.empty()) {\n            for (int x = 0; x < D; x++) for (int y = 0; y < D; y++) for (int z = 0; z < D; z++) {\n                if (allowed[i][idx(x, y, z)] && !used[i][idx(x, y, z)]) {\n                    seeds.emplace_back(x, y, z);\n                    goto seed_done;\n                }\n            }\n            seed_done:;\n        }\n\n        struct SeedInfo {\n            int sx, sy, sz;\n            int x0, y0, z0, dx, dy, dz;\n            int score;\n            bool matchable;\n            int jx0, jy0, jz0, jdx, jdy, jdz;\n        };\n        vector<SeedInfo> infos;\n        for (auto [sx, sy, sz] : seeds) {\n            int x0, y0, z0, dx, dy, dz;\n            compute_maximal_box(i, sx, sy, sz, x0, y0, z0, dx, dy, dz);\n            int vol = dx * dy * dz;\n            int cc = count_covered(i, x0, y0, z0, dx, dy, dz);\n            int score = vol * 1000 + cc;\n            int jx0, jy0, jz0, jdx, jdy, jdz;\n            bool ok = find_best_placement(j, dx, dy, dz, jx0, jy0, jz0, jdx, jdy, jdz);\n            infos.push_back({sx, sy, sz, x0, y0, z0, dx, dy, dz, score, ok, jx0, jy0, jz0, jdx, jdy, jdz});\n        }\n\n        // pick best matchable seed\n        int best_idx = -1;\n        for (int k = 0; k < (int)infos.size(); k++) {\n            if (!infos[k].matchable) continue;\n            if (best_idx == -1 || infos[k].score > infos[best_idx].score)\n                best_idx = k;\n        }\n\n        if (best_idx != -1) {\n            // place in both\n            SeedInfo &info = infos[best_idx];\n            int id = blocks.size() + 1;\n            apply_placement(i, info.x0, info.y0, info.z0, info.dx, info.dy, info.dz, id);\n            apply_placement(j, info.jx0, info.jy0, info.jz0, info.jdx, info.jdy, info.jdz, id);\n            blocks.push_back({info.dx, info.dy, info.dz});\n            continue;\n        }\n\n        // No matchable seed -> try sub-boxes of the best seed (by score)\n        best_idx = 0;\n        for (int k = 1; k < (int)infos.size(); k++) {\n            if (infos[k].score > infos[best_idx].score) best_idx = k;\n        }\n        SeedInfo &best = infos[best_idx];\n        int bx0 = best.x0, by0 = best.y0, bz0 = best.z0;\n        int bdx = best.dx, bdy = best.dy, bdz = best.dz;\n        vector<tuple<int,int,int,int,int,int>> sub_boxes;\n        for (int x0 = bx0; x0 <= best.sx; x0++) {\n            for (int x1 = best.sx; x1 < bx0 + bdx; x1++) {\n                int dx_sub = x1 - x0 + 1;\n                for (int y0 = by0; y0 <= best.sy; y0++) {\n                    for (int y1 = best.sy; y1 < by0 + bdy; y1++) {\n                        int dy_sub = y1 - y0 + 1;\n                        for (int z0 = bz0; z0 <= best.sz; z0++) {\n                            for (int z1 = best.sz; z1 < bz0 + bdz; z1++) {\n                                int dz_sub = z1 - z0 + 1;\n                                sub_boxes.emplace_back(x0, y0, z0, dx_sub, dy_sub, dz_sub);\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        sort(sub_boxes.begin(), sub_boxes.end(), [](auto &a, auto &b) {\n            return get<3>(a)*get<4>(a)*get<5>(a) > get<3>(b)*get<4>(b)*get<5>(b);\n        });\n\n        bool placed_sub = false;\n        for (auto &sub : sub_boxes) {\n            int sx0 = get<0>(sub), sy0 = get<1>(sub), sz0 = get<2>(sub);\n            int sdx = get<3>(sub), sdy = get<4>(sub), sdz = get<5>(sub);\n            int jx0, jy0, jz0, jdx, jdy, jdz;\n            if (find_best_placement(j, sdx, sdy, sdz, jx0, jy0, jz0, jdx, jdy, jdz)) {\n                int id = blocks.size() + 1;\n                apply_placement(i, sx0, sy0, sz0, sdx, sdy, sdz, id);\n                apply_placement(j, jx0, jy0, jz0, jdx, jdy, jdz, id);\n                blocks.push_back({sdx, sdy, sdz});\n                placed_sub = true;\n                break;\n            }\n        }\n\n        if (!placed_sub) {\n            // fallback: place the best seed's maximal box only in i\n            int id = blocks.size() + 1;\n            apply_placement(i, bx0, by0, bz0, bdx, bdy, bdz, id);\n            blocks.push_back({bdx, bdy, bdz});\n        }\n    }\n\n    int n = blocks.size();\n    cout << n << \"\\n\";\n    for (int i = 0; i < 2; i++) {\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 (x != 0 || y != 0 || z != 0) cout << \" \";\n                    cout << bid[i][idx(x, y, z)];\n                }\n            }\n        }\n        cout << \"\\n\";\n    }\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\nusing int64 = long long;\n\ninline int64 ceil_sqrt(int64 x) {\n    if (x <= 0) return 0;\n    int64 r = (int64)sqrt((long double)x);\n    while (r * r < x) ++r;\n    while (r * r > x) --r;\n    if (r * r < x) ++r;\n    return r;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start_time = chrono::steady_clock::now();\n    auto elapsed = [&]() { return chrono::duration<double>(chrono::steady_clock::now() - start_time).count(); };\n\n    int N, M, K;\n    cin >> N >> M >> K;\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; ++i) cin >> x[i] >> y[i];\n    vector<tuple<int, int, int>> edges(M);\n    vector<vector<pair<int, int>>> adj(N);\n    map<pair<int, int>, int> edge_id_map;\n    for (int j = 0; j < M; ++j) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        --u; --v;\n        edges[j] = {u, v, w};\n        adj[u].push_back({v, w});\n        adj[v].push_back({u, w});\n        edge_id_map[{min(u, v), max(u, v)}] = j;\n    }\n    vector<int> a(K), b(K);\n    for (int k = 0; k < K; ++k) cin >> a[k] >> b[k];\n\n    // ---------- all-pairs shortest paths ----------\n    vector<vector<int64>> dist(N, vector<int64>(N));\n    vector<vector<int>> nxt(N, vector<int>(N, -1));\n    for (int s = 0; s < N; ++s) {\n        priority_queue<pair<int64, int>, vector<pair<int64, int>>, greater<>> pq;\n        vector<int64> d(N, numeric_limits<int64>::max());\n        d[s] = 0;\n        nxt[s][s] = s;\n        pq.push({0, s});\n        while (!pq.empty()) {\n            auto [du, u] = pq.top(); pq.pop();\n            if (du != d[u]) continue;\n            for (auto &[v, w] : adj[u]) {\n                if (d[u] + w < d[v]) {\n                    d[v] = d[u] + w;\n                    nxt[s][v] = u;\n                    pq.push({d[v], v});\n                }\n            }\n        }\n        dist[s] = d;\n    }\n\n    // ---------- precompute path edge indices ----------\n    vector<vector<vector<int>>> path_edges(N, vector<vector<int>>(N));\n    for (int s = 0; s < N; ++s) {\n        for (int t = 0; t < N; ++t) {\n            if (s == t) continue;\n            vector<int> eids;\n            int cur = t;\n            while (cur != s) {\n                int p = nxt[s][cur];\n                int u = min(cur, p), v = max(cur, p);\n                auto it = edge_id_map.find({u, v});\n                if (it != edge_id_map.end()) {\n                    eids.push_back(it->second);\n                }\n                cur = p;\n            }\n            path_edges[s][t] = eids;\n        }\n    }\n\n    // ---------- precompute distances and resident lists ----------\n    const int64 R2 = 25000000LL; // 5000^2\n    vector<vector<int64>> dsq(N, vector<int64>(K));\n    vector<vector<int>> station_res(N);\n    for (int i = 0; i < N; ++i) {\n        for (int k = 0; k < K; ++k) {\n            int64 dx = x[i] - a[k];\n            int64 dy = y[i] - b[k];\n            int64 d2 = dx * dx + dy * dy;\n            dsq[i][k] = d2;\n            if (d2 <= R2) station_res[i].push_back(k);\n        }\n    }\n    vector<vector<int>> res_stations(K);\n    for (int k = 0; k < K; ++k) {\n        vector<pair<int64, int>> tmp;\n        for (int i = 0; i < N; ++i) {\n            if (dsq[i][k] <= R2) tmp.push_back({dsq[i][k], i});\n        }\n        sort(tmp.begin(), tmp.end());\n        for (auto &p : tmp) res_stations[k].push_back(p.second);\n    }\n\n    // coverage state\n    vector<int> cov_count(K, 0);\n    auto add_station = [&](int i, vector<bool> &active) {\n        if (active[i]) return;\n        active[i] = true;\n        for (int k : station_res[i]) ++cov_count[k];\n    };\n    auto del_station = [&](int i, vector<bool> &active) {\n        if (!active[i]) return;\n        active[i] = false;\n        for (int k : station_res[i]) --cov_count[k];\n    };\n\n    // ---------- evaluation ----------\n    auto evaluate = [&](const vector<bool> &active) -> int64 {\n        vector<int> T;\n        for (int i = 0; i < N; ++i) if (active[i]) T.push_back(i);\n        int t = T.size();\n\n        // metric MST + mapping to real edges\n        vector<bool> used_edge(M, false);\n        if (t > 1) {\n            // Prim metric MST\n            vector<bool> inmst(t, false);\n            vector<int64> minw(t, numeric_limits<int64>::max());\n            vector<int> parent(t, -1);\n            minw[0] = 0;\n            for (int i = 0; i < t; ++i) {\n                int u = -1;\n                for (int j = 0; j < t; ++j)\n                    if (!inmst[j] && (u == -1 || minw[j] < minw[u])) u = j;\n                inmst[u] = true;\n                if (parent[u] != -1) {\n                    int src = T[u], dst = T[parent[u]];\n                    for (int eid : path_edges[src][dst]) used_edge[eid] = true;\n                }\n                for (int v = 0; v < t; ++v) {\n                    if (!inmst[v]) {\n                        int64 wgt = dist[T[u]][T[v]];\n                        if (wgt < minw[v]) {\n                            minw[v] = wgt;\n                            parent[v] = u;\n                        }\n                    }\n                }\n            }\n        }\n\n        // BFS to find reachable vertices\n        vector<vector<int>> radj(N);\n        for (int j = 0; j < M; ++j) {\n            if (used_edge[j]) {\n                auto [u, v, w] = edges[j];\n                radj[u].push_back(v);\n                radj[v].push_back(u);\n            }\n        }\n        vector<bool> reachable(N, false);\n        queue<int> q;\n        reachable[0] = true; q.push(0);\n        while (!q.empty()) {\n            int node = q.front(); q.pop();\n            for (int to : radj[node]) {\n                if (!reachable[to]) {\n                    reachable[to] = true;\n                    q.push(to);\n                }\n            }\n        }\n\n        // Kruskal on reachable subgraph\n        vector<tuple<int64, int, int>> sorted_edges;\n        for (int j = 0; j < M; ++j) {\n            auto [u, v, w] = edges[j];\n            if (reachable[u] && reachable[v]) sorted_edges.push_back({w, u, v});\n        }\n        sort(sorted_edges.begin(), sorted_edges.end());\n        vector<int> uf(N);\n        iota(uf.begin(), uf.end(), 0);\n        function<int(int)> find = [&](int x) { return uf[x] == x ? x : uf[x] = find(uf[x]); };\n        int comps = 0;\n        for (int i = 0; i < N; ++i) if (reachable[i]) comps++;\n        int used_cnt = 0;\n        int64 cable_cost = 0;\n        for (auto &[w, u, v] : sorted_edges) {\n            int ru = find(u), rv = find(v);\n            if (ru != rv) {\n                uf[ru] = rv;\n                cable_cost += w;\n                if (++used_cnt == comps - 1) break;\n            }\n        }\n        if (used_cnt != comps - 1) return numeric_limits<int64>::max();\n\n        // power cost\n        vector<int64> max_dsq(N, 0);\n        for (int k = 0; k < K; ++k) {\n            const auto &lst = res_stations[k];\n            int best = -1;\n            for (int i : lst) {\n                if (active[i]) { best = i; break; }\n            }\n            if (best == -1) return numeric_limits<int64>::max();\n            int64 d = dsq[best][k];\n            if (d > max_dsq[best]) max_dsq[best] = d;\n        }\n        int64 power_cost = 0;\n        for (int i = 0; i < N; ++i) {\n            if (max_dsq[i] > 0) {\n                int64 P = ceil_sqrt(max_dsq[i]);\n                if (P > 5000) return numeric_limits<int64>::max();\n                power_cost += P * P;\n            }\n        }\n        return cable_cost + power_cost;\n    };\n\n    // ---------- initial greedy set cover ----------\n    vector<bool> cur_active(N, false);\n    add_station(0, cur_active);\n    vector<bool> covered(K, false);\n    int uncovered = K;\n    for (int k : station_res[0]) { covered[k] = true; --uncovered; }\n    while (uncovered > 0) {\n        int best_i = -1, best_cov = 0;\n        for (int i = 1; i < N; ++i) {\n            if (cur_active[i]) continue;\n            int cnt = 0;\n            for (int k : station_res[i]) if (!covered[k]) ++cnt;\n            if (cnt > best_cov) { best_cov = cnt; best_i = i; }\n        }\n        if (best_i == -1) {\n            // fallback: activate any that can cover remaining\n            for (int i = 1; i < N && uncovered > 0; ++i) {\n                if (!cur_active[i]) {\n                    for (int k : station_res[i]) if (!covered[k]) {\n                        add_station(i, cur_active);\n                        for (int kk : station_res[i]) if (!covered[kk]) { covered[kk] = true; --uncovered; }\n                        break;\n                    }\n                }\n            }\n            break;\n        }\n        add_station(best_i, cur_active);\n        for (int k : station_res[best_i]) if (!covered[k]) { covered[k] = true; --uncovered; }\n    }\n\n    // ---------- initial hill-climbing (removal) ----------\n    int64 cur_cost = evaluate(cur_active);\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int i = 1; i < N; ++i) {\n            if (!cur_active[i]) continue;\n            del_station(i, cur_active);\n            bool ok = true;\n            for (int k : station_res[i]) if (cov_count[k] == 0) { ok = false; break; }\n            if (!ok) { add_station(i, cur_active); continue; }\n            int64 new_cost = evaluate(cur_active);\n            if (new_cost < cur_cost) {\n                cur_cost = new_cost;\n                improved = true;\n            } else {\n                add_station(i, cur_active);\n            }\n        }\n    }\n\n    vector<bool> best_active = cur_active;\n    int64 best_cost = cur_cost;\n\n    // ---------- Simulated Annealing ----------\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> rand_vertex(1, N - 1);\n    uniform_real_distribution<double> rand_double(0.0, 1.0);\n\n    double T_start = max(1e6, (double)cur_cost * 0.05);\n    double T_end = T_start * 1e-6;\n    double sa_start = elapsed();\n\n    while (elapsed() < 1.75) {\n        double frac = (elapsed() - sa_start) / (1.75 - sa_start);\n        double T = T_start * pow(T_end / T_start, frac);\n        if (T < 1e-9) T = 1e-9;\n\n        int i = rand_vertex(rng);\n        bool old = cur_active[i];\n        if (old) {\n            del_station(i, cur_active);\n            bool ok = true;\n            for (int k : station_res[i]) if (cov_count[k] == 0) { ok = false; break; }\n            if (!ok) { add_station(i, cur_active); continue; }\n        } else {\n            add_station(i, cur_active);\n        }\n        int64 new_cost = evaluate(cur_active);\n        bool accept = (new_cost < cur_cost);\n        if (!accept && new_cost != numeric_limits<int64>::max()) {\n            double delta = (double)(int64)(new_cost - cur_cost);\n            double prob = exp(-delta / T);\n            if (rand_double(rng) < prob) accept = true;\n        }\n        if (accept) {\n            cur_cost = new_cost;\n            if (new_cost < best_cost) {\n                best_cost = new_cost;\n                best_active = cur_active;\n            }\n        } else {\n            if (old) add_station(i, cur_active);\n            else del_station(i, cur_active);\n        }\n    }\n\n    // ---------- final hill-climbing on best ----------\n    cur_active = best_active;\n    cur_cost = best_cost;\n    improved = true;\n    while (improved && elapsed() < 1.9) {\n        improved = false;\n        for (int i = 1; i < N; ++i) {\n            bool old = cur_active[i];\n            if (old) {\n                del_station(i, cur_active);\n                bool ok = true;\n                for (int k : station_res[i]) if (cov_count[k] == 0) { ok = false; break; }\n                if (!ok) { add_station(i, cur_active); continue; }\n            } else {\n                add_station(i, cur_active);\n            }\n            int64 new_cost = evaluate(cur_active);\n            if (new_cost < cur_cost) {\n                cur_cost = new_cost;\n                if (new_cost < best_cost) {\n                    best_cost = new_cost;\n                    best_active = cur_active;\n                }\n                improved = true;\n            } else {\n                if (old) add_station(i, cur_active);\n                else del_station(i, cur_active);\n            }\n        }\n    }\n\n    // ---------- power assignment optimization ----------\n    // Recompute nearest active assignment and then improve\n    vector<int> assign(K, -1);\n    vector<vector<int>> station_assign(N);\n    vector<int64> max_dsq(N, 0);\n\n    auto rebuild_assignment = [&]() {\n        for (int i = 0; i < N; ++i) station_assign[i].clear();\n        fill(max_dsq.begin(), max_dsq.end(), 0);\n        for (int k = 0; k < K; ++k) {\n            const auto &lst = res_stations[k];\n            for (int i : lst) {\n                if (best_active[i]) {\n                    assign[k] = i;\n                    station_assign[i].push_back(k);\n                    if (dsq[i][k] > max_dsq[i]) max_dsq[i] = dsq[i][k];\n                    break;\n                }\n            }\n        }\n    };\n    rebuild_assignment();\n\n    auto power_sum = [&]() {\n        int64 s = 0;\n        for (int i = 0; i < N; ++i) if (max_dsq[i] > 0) {\n            int64 P = ceil_sqrt(max_dsq[i]);\n            if (P > 5000) P = 5000;\n            s += P * P;\n        }\n        return s;\n    };\n\n    bool changed = true;\n    while (changed && elapsed() < 1.95) {\n        changed = false;\n        for (int k = 0; k < K; ++k) {\n            int cur = assign[k];\n            int64 cur_d2 = dsq[cur][k];\n            const auto &lst = res_stations[k];\n            for (int j : lst) {\n                if (j == cur || !best_active[j]) continue;\n                // new max for cur if we remove k\n                int64 new_max_cur = 0;\n                // if cur_d2 != max_dsq[cur] then max won't change; else we need to recompute\n                if (cur_d2 == max_dsq[cur]) {\n                    for (int kk : station_assign[cur]) {\n                        if (kk != k && dsq[cur][kk] > new_max_cur) new_max_cur = dsq[cur][kk];\n                    }\n                } else {\n                    new_max_cur = max_dsq[cur];\n                }\n                int64 new_max_j = max(max_dsq[j], dsq[j][k]);\n                int64 old_val = (ceil_sqrt(max_dsq[cur]) * ceil_sqrt(max_dsq[cur])) +\n                                (ceil_sqrt(max_dsq[j]) * ceil_sqrt(max_dsq[j]));\n                int64 new_val = (ceil_sqrt(new_max_cur) * ceil_sqrt(new_max_cur)) +\n                                (ceil_sqrt(new_max_j) * ceil_sqrt(new_max_j));\n                if (new_val < old_val) {\n                    // perform move\n                    auto &vcur = station_assign[cur];\n                    vcur.erase(find(vcur.begin(), vcur.end(), k));\n                    station_assign[j].push_back(k);\n                    max_dsq[cur] = new_max_cur;\n                    max_dsq[j] = new_max_j;\n                    assign[k] = j;\n                    changed = true;\n                    break; // reconsider next k\n                }\n            }\n        }\n    }\n\n    // ---------- build final edges ----------\n    vector<int> final_B(M, 0);\n    {\n        vector<int> T;\n        for (int i = 0; i < N; ++i) if (best_active[i]) T.push_back(i);\n        int t = T.size();\n        vector<bool> used_edge(M, false);\n        if (t > 1) {\n            vector<bool> inmst(t, false);\n            vector<int64> minw(t, numeric_limits<int64>::max());\n            vector<int> parent(t, -1);\n            minw[0] = 0;\n            for (int i = 0; i < t; ++i) {\n                int u = -1;\n                for (int j = 0; j < t; ++j)\n                    if (!inmst[j] && (u == -1 || minw[j] < minw[u])) u = j;\n                inmst[u] = true;\n                if (parent[u] != -1) {\n                    int src = T[u], dst = T[parent[u]];\n                    for (int eid : path_edges[src][dst]) used_edge[eid] = true;\n                }\n                for (int v = 0; v < t; ++v) {\n                    if (!inmst[v] && dist[T[u]][T[v]] < minw[v]) {\n                        minw[v] = dist[T[u]][T[v]];\n                        parent[v] = u;\n                    }\n                }\n            }\n        }\n        vector<vector<int>> radj(N);\n        for (int j = 0; j < M; ++j) if (used_edge[j]) {\n            auto [u, v, w] = edges[j];\n            radj[u].push_back(v);\n            radj[v].push_back(u);\n        }\n        vector<bool> reachable(N, false);\n        queue<int> q;\n        reachable[0] = true; q.push(0);\n        while (!q.empty()) {\n            int node = q.front(); q.pop();\n            for (int to : radj[node]) {\n                if (!reachable[to]) {\n                    reachable[to] = true;\n                    q.push(to);\n                }\n            }\n        }\n        vector<tuple<int64, int, int>> sorted_edges;\n        for (int j = 0; j < M; ++j) {\n            auto [u, v, w] = edges[j];\n            if (reachable[u] && reachable[v]) sorted_edges.push_back({w, u, v});\n        }\n        sort(sorted_edges.begin(), sorted_edges.end());\n        vector<int> uf(N);\n        iota(uf.begin(), uf.end(), 0);\n        function<int(int)> find = [&](int x) { return uf[x] == x ? x : uf[x] = find(uf[x]); };\n        int comps = count(reachable.begin(), reachable.end(), true);\n        int used = 0;\n        for (auto &[w, u, v] : sorted_edges) {\n            int ru = find(u), rv = find(v);\n            if (ru != rv) {\n                uf[ru] = rv;\n                int a = min(u, v), b = max(u, v);\n                auto it = edge_id_map.find({a, b});\n                if (it != edge_id_map.end()) final_B[it->second] = 1;\n                if (++used == comps - 1) break;\n            }\n        }\n    }\n\n    vector<int> final_P(N, 0);\n    for (int i = 0; i < N; ++i) {\n        if (max_dsq[i] > 0) {\n            int64 P = ceil_sqrt(max_dsq[i]);\n            if (P > 5000) P = 5000;\n            final_P[i] = (int)P;\n        }\n    }\n\n    // ---------- output ----------\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << final_P[i];\n    }\n    cout << '\\n';\n    for (int j = 0; j < M; ++j) {\n        if (j) cout << ' ';\n        cout << final_B[j];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <random>\n#include <cmath>\n#include <chrono>\nusing namespace std;\n\nconst int N = 30;\nconst int V = N * (N + 1) / 2;   // 465\n\nint xc[V], yc[V];\nint id(int x, int y) { return x * (x + 1) / 2 + y; }\n\nbool is_anc(int a, int b) {\n    int xa = xc[a], ya = yc[a];\n    int xb = xc[b], yb = yc[b];\n    if (xa > xb) return false;\n    if (ya > yb) return false;\n    if (yb - ya > xb - xa) return false;\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    // init coordinates\n    for (int x = 0; x < N; ++x)\n        for (int y = 0; y <= x; ++y) {\n            int i = id(x, y);\n            xc[i] = x;\n            yc[i] = y;\n        }\n\n    // adjacency, parents, children\n    vector<vector<int>> adj(V), parents(V), children(V);\n    for (int i = 0; i < V; ++i) {\n        int x = xc[i], y = yc[i];\n        if (x > 0) {\n            if (y > 0) {\n                int p = id(x - 1, y - 1);\n                adj[i].push_back(p);\n                parents[i].push_back(p);\n            }\n            if (y <= x - 1) {\n                int p = id(x - 1, y);\n                adj[i].push_back(p);\n                parents[i].push_back(p);\n            }\n        }\n        if (y > 0) adj[i].push_back(id(x, y - 1));\n        if (y < x) adj[i].push_back(id(x, y + 1));\n        if (x < N - 1) {\n            int c1 = id(x + 1, y);\n            int c2 = id(x + 1, y + 1);\n            adj[i].push_back(c1);\n            adj[i].push_back(c2);\n            children[i].push_back(c1);\n            children[i].push_back(c2);\n        }\n    }\n\n    // input\n    vector<int> init_pos(V);\n    vector<int> grid(V);\n    for (int x = 0; x < N; ++x)\n        for (int y = 0; y <= x; ++y) {\n            int v;\n            cin >> v;\n            int node = id(x, y);\n            grid[node] = v;\n            init_pos[v] = node;\n        }\n\n    // precompute all-pairs distances\n    vector<vector<int>> dist(V, vector<int>(V, -1));\n    for (int s = 0; s < V; ++s) {\n        queue<int> q;\n        q.push(s);\n        dist[s][s] = 0;\n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            for (int v : adj[u]) {\n                if (dist[s][v] == -1) {\n                    dist[s][v] = dist[s][u] + 1;\n                    q.push(v);\n                }\n            }\n        }\n    }\n\n    // canonical row assignment for the initial target\n    vector<int> val_row(V);\n    {\n        int cur = 0;\n        for (int r = 0; r < N; ++r)\n            for (int c = 0; c <= r; ++c)\n                val_row[cur++] = r;\n    }\n\n    // Hungarian algorithm\n    auto hungarian = [&](const vector<vector<int>>& cost) -> vector<int> {\n        int n = cost.size(), m = cost[0].size();\n        if (n == 0) return {};\n        vector<int> u(n + 1), v(m + 1), p(m + 1), way(m + 1);\n        for (int i = 1; i <= n; ++i) {\n            p[0] = i;\n            int j0 = 0;\n            vector<int> minv(m + 1, 1e9);\n            vector<char> used(m + 1, false);\n            do {\n                used[j0] = true;\n                int i0 = p[j0], delta = 1e9, j1 = 0;\n                for (int j = 1; j <= m; ++j) {\n                    if (!used[j]) {\n                        int cur = cost[i0 - 1][j - 1] - u[i0] - v[j];\n                        if (cur < minv[j]) {\n                            minv[j] = cur;\n                            way[j] = j0;\n                        }\n                        if (minv[j] < delta) {\n                            delta = minv[j];\n                            j1 = j;\n                        }\n                    }\n                }\n                for (int j = 0; j <= m; ++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        vector<int> ass(n);\n        for (int j = 1; j <= m; ++j)\n            if (p[j] != 0)\n                ass[p[j] - 1] = j - 1;\n        return ass;\n    };\n\n    // initial target by row\u2011wise Hungarian\n    vector<int> target_val(V, -1), target_node(V, -1);\n    for (int r = 0; r < N; ++r) {\n        vector<int> nodes_r, vals_r;\n        for (int i = 0; i < V; ++i) {\n            if (xc[i] == r) nodes_r.push_back(i);\n            if (val_row[i] == r) vals_r.push_back(i);\n        }\n        if (vals_r.empty()) continue;\n        int sz = vals_r.size();\n        vector<vector<int>> cost(sz, vector<int>(sz));\n        for (int i = 0; i < sz; ++i) {\n            int v = vals_r[i];\n            int start = init_pos[v];\n            for (int j = 0; j < sz; ++j)\n                cost[i][j] = dist[start][nodes_r[j]];\n        }\n        vector<int> ass = hungarian(cost);\n        for (int i = 0; i < sz; ++i) {\n            int v = vals_r[i];\n            int node = nodes_r[ass[i]];\n            target_val[node] = v;\n            target_node[v] = node;\n        }\n    }\n\n    long long cur_cost = 0;\n    for (int v = 0; v < V; ++v)\n        cur_cost += dist[init_pos[v]][target_node[v]];\n\n    // SA parameters\n    mt19937 rng(random_device{}());\n    uniform_real_distribution<double> prob_dist(0.0, 1.0);\n    uniform_int_distribution<int> node_dist(0, V - 1);\n\n    double T_start = 10000.0, T_end = 0.1;\n    double time_limit = 1.9;  // seconds for SA\n    auto start_time = chrono::steady_clock::now();\n    long long iter = 0;\n    double T = T_start;\n\n    while (true) {\n        if ((iter & 1023) == 0) {\n            double elapsed =\n                chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n            if (elapsed > time_limit) break;\n            T = T_start * pow(T_end / T_start, min(elapsed / time_limit, 1.0));\n        }\n        ++iter;\n\n        int u = node_dist(rng);\n        int v = node_dist(rng);\n        if (u == v) continue;\n        if (is_anc(u, v) || is_anc(v, u)) continue;\n\n        int val_u = target_val[u];\n        int val_v = target_val[v];\n\n        bool ok = true;\n        for (int p : parents[u])\n            if (target_val[p] > val_v) { ok = false; break; }\n        if (ok)\n            for (int c : children[u])\n                if (val_v > target_val[c]) { ok = false; break; }\n        if (ok)\n            for (int p : parents[v])\n                if (target_val[p] > val_u) { ok = false; break; }\n        if (ok)\n            for (int c : children[v])\n                if (val_u > target_val[c]) { ok = false; break; }\n        if (!ok) continue;\n\n        long long delta = dist[init_pos[val_u]][v] + dist[init_pos[val_v]][u] -\n                          dist[init_pos[val_u]][u] - dist[init_pos[val_v]][v];\n\n        if (delta <= 0 || prob_dist(rng) < exp(-delta / T)) {\n            target_val[u] = val_v;\n            target_val[v] = val_u;\n            target_node[val_u] = v;\n            target_node[val_v] = u;\n            cur_cost += delta;\n        }\n    }\n\n    // ---------- routing phase ----------\n    vector<int> cur_pos = init_pos;\n    vector<bool> locked(V, false);\n    vector<pair<int, int>> moves;\n\n    // bottom \u2192 top, left \u2192 right\n    for (int r = N - 1; r >= 0; --r) {\n        for (int c = 0; c <= r; ++c) {\n            int tgt_id = id(r, c);\n            int v = target_val[tgt_id];\n            if (cur_pos[v] == tgt_id) {\n                locked[tgt_id] = true;\n                continue;\n            }\n\n            vector<int> parent(V, -1);\n            queue<int> q;\n            int start = cur_pos[v];\n            q.push(start);\n            parent[start] = start;\n            while (!q.empty()) {\n                int u = q.front(); q.pop();\n                if (u == tgt_id) break;\n                for (int w : adj[u])\n                    if (!locked[w] && parent[w] == -1) {\n                        parent[w] = u;\n                        q.push(w);\n                    }\n            }\n\n            vector<int> path;\n            for (int at = tgt_id; at != start; at = parent[at])\n                path.push_back(at);\n            path.push_back(start);\n            reverse(path.begin(), path.end());\n\n            for (size_t i = 0; i + 1 < path.size(); ++i) {\n                int n1 = path[i], n2 = path[i + 1];\n                int val1 = grid[n1], val2 = grid[n2];\n                swap(grid[n1], grid[n2]);\n                cur_pos[val1] = n2;\n                cur_pos[val2] = n1;\n                moves.emplace_back(n1, n2);\n                if (moves.size() >= 10000) goto output_moves;\n            }\n            locked[tgt_id] = true;\n        }\n    }\n\noutput_moves:\n    cout << moves.size() << \"\\n\";\n    for (auto [a, b] : moves)\n        cout << xc[a] << \" \" << yc[a] << \" \" << xc[b] << \" \" << yc[b] << \"\\n\";\n\n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <functional>\n#include <utility>\n\nusing namespace std;\n\nint main() {\n    // Read initial information\n    int D, N;\n    cin >> D >> N;\n    int ent_r = 0, ent_c = (D - 1) / 2;\n    int start = ent_r * D + ent_c;\n\n    // Mark cells that cannot hold containers (entrance + obstacles)\n    vector<vector<bool>> blocked(D, vector<bool>(D, false));\n    blocked[ent_r][ent_c] = true;  // entrance\n    for (int i = 0; i < N; i++) {\n        int r, c;\n        cin >> r >> c;\n        blocked[r][c] = true;\n    }\n\n    int K = D * D - 1 - N;  // number of containers\n\n    // BFS distances from entrance over free cells\n    vector<int> dist(D * D, -1);\n    queue<int> q;\n    dist[start] = 0;\n    q.push(start);\n    const int dr[4] = {-1, 1, 0, 0};\n    const int dc[4] = {0, 0, -1, 1};\n\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        int r = u / D, c = u % D;\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n            if (blocked[nr][nc]) continue;\n            int v = nr * D + nc;\n            if (dist[v] == -1) {\n                dist[v] = dist[u] + 1;\n                q.push(v);\n            }\n        }\n    }\n\n    // Collect all free cells (non-blocked, non-entrance)\n    vector<int> free_cells;\n    for (int r = 0; r < D; r++) {\n        for (int c = 0; c < D; c++) {\n            if (!blocked[r][c]) {\n                free_cells.push_back(r * D + c);\n            }\n        }\n    }\n\n    // Sort free cells by distance, then by ID (row-major)\n    sort(free_cells.begin(), free_cells.end(), [&](int a, int b) {\n        if (dist[a] != dist[b]) return dist[a] < dist[b];\n        return a < b;\n    });\n\n    // Prepare mapping: order of each cell, and ideal cell for each rank\n    vector<int> ord(D * D, -1);\n    vector<int> ideal(K);\n    for (int i = 0; i < K; i++) {\n        int cell = free_cells[i];\n        ord[cell] = i;\n        ideal[i] = cell;\n    }\n\n    // State of the warehouse\n    vector<bool> occupied(D * D, false);\n    vector<int> rank_at(D * D, -1);\n\n    // Process arrivals\n    for (int d = 0; d < K; d++) {\n        int rank;\n        cin >> rank;\n\n        // Get all empty cells currently reachable from entrance\n        vector<int> reachable;\n        vector<bool> vis(D * D, false);\n        queue<int> bfs;\n        bfs.push(start);\n        vis[start] = true;\n        while (!bfs.empty()) {\n            int u = bfs.front(); bfs.pop();\n            reachable.push_back(u);\n            int r = u / D, c = u % D;\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (blocked[nr][nc]) continue;\n                int v = nr * D + nc;\n                if (occupied[v]) continue;\n                if (!vis[v]) {\n                    vis[v] = true;\n                    bfs.push(v);\n                }\n            }\n        }\n\n        // Build adjacency among reachable cells\n        vector<vector<int>> adj(D * D);\n        for (int u : reachable) {\n            int r = u / D, c = u % D;\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (blocked[nr][nc]) continue;\n                int v = nr * D + nc;\n                if (occupied[v]) continue;\n                if (vis[v]) {\n                    adj[u].push_back(v);\n                }\n            }\n        }\n\n        // Find articulation points (cells that would disconnect the empty area)\n        vector<int> disc(D * D, -1), low(D * D, -1);\n        vector<bool> is_art(D * D, false);\n        int timer = 0;\n        function<void(int, int)> dfs = [&](int u, int parent) {\n            disc[u] = low[u] = timer++;\n            int children = 0;\n            for (int v : adj[u]) {\n                if (v == parent) continue;\n                if (disc[v] == -1) {\n                    dfs(v, u);\n                    low[u] = min(low[u], low[v]);\n                    if (parent != -1 && low[v] >= disc[u]) {\n                        is_art[u] = true;\n                    }\n                    children++;\n                } else {\n                    low[u] = min(low[u], disc[v]);\n                }\n            }\n            if (parent == -1 && children > 1) {\n                is_art[u] = true;\n            }\n        };\n        dfs(start, -1);\n\n        // Safe cells = reachable empty cells except entrance and articulation points\n        vector<int> safe;\n        for (int u : reachable) {\n            if (u == start) continue;\n            if (!is_art[u]) {\n                safe.push_back(u);\n            }\n        }\n\n        // Choose placement cell\n        int target = ideal[rank];\n        int chosen = -1;\n        bool target_safe = false;\n        for (int u : safe) if (u == target) { target_safe = true; break; }\n\n        if (target_safe) {\n            chosen = target;\n        } else {\n            int best_diff = 1e9;\n            for (int u : safe) {\n                int diff = abs(ord[u] - rank);\n                if (diff < best_diff) {\n                    best_diff = diff;\n                    chosen = u;\n                } else if (diff == best_diff) {\n                    if (ord[u] < ord[chosen]) {\n                        chosen = u;\n                    }\n                }\n            }\n        }\n\n        // Place the container\n        occupied[chosen] = true;\n        rank_at[chosen] = rank;\n        cout << chosen / D << \" \" << chosen % D << endl;\n    }\n\n    // Removal phase\n    vector<bool> removed(D * D, false);\n    vector<pair<int, int>> removal_seq;\n\n    while (removal_seq.size() < K) {\n        queue<int> bfs;\n        vector<bool> vis(D * D, false);\n        bfs.push(start);\n        vis[start] = true;\n        vector<int> candidates;\n\n        while (!bfs.empty()) {\n            int u = bfs.front(); bfs.pop();\n            int r = u / D, c = u % D;\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (blocked[nr][nc]) continue;\n                int v = nr * D + nc;\n                if (vis[v]) continue;\n                if (removed[v] || v == start) {\n                    vis[v] = true;\n                    bfs.push(v);\n                } else if (occupied[v] && !removed[v]) {\n                    candidates.push_back(v);\n                }\n            }\n        }\n\n        sort(candidates.begin(), candidates.end());\n        candidates.erase(unique(candidates.begin(), candidates.end()), candidates.end());\n\n        int best = -1, best_rank = 1e9;\n        for (int v : candidates) {\n            if (rank_at[v] < best_rank) {\n                best_rank = rank_at[v];\n                best = v;\n            }\n        }\n\n        removed[best] = true;\n        removal_seq.emplace_back(best / D, best % D);\n    }\n\n    for (auto [r, c] : removal_seq) {\n        cout << r << \" \" << c << endl;\n    }\n\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 50;\nconst int N2 = N * N;\nconst int MAXC = 101; // 0..100\n\nbool adj_req[MAXC][MAXC];\nint vis[N2];\nint vis_token = 0;\nint bfs_queue[N2];\nvector<array<int,4>> nb(N2);\nvector<int> boundary_idx;\n\nvoid compute_energy(const int* g, int m, int& E, int& viol_conn, int& viol_adj) {\n    ++vis_token;\n    E = 0;\n    viol_conn = 0;\n    viol_adj = 0;\n    int comp_count[MAXC] = {0};\n    int cell_count[MAXC] = {0};\n\n    // Connectivity for colors 1..m\n    for (int i = 0; i < N2; ++i) {\n        int c = g[i];\n        if (c == 0) {\n            ++E;\n        } else {\n            cell_count[c]++;\n            if (vis[i] != vis_token) {\n                comp_count[c]++;\n                int head = 0, tail = 0;\n                bfs_queue[tail++] = i;\n                vis[i] = vis_token;\n                while (head < tail) {\n                    int v = bfs_queue[head++];\n                    for (int nbr : nb[v]) {\n                        if (nbr != -1 && g[nbr] == c && vis[nbr] != vis_token) {\n                            vis[nbr] = vis_token;\n                            bfs_queue[tail++] = nbr;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    for (int c = 1; c <= m; ++c) {\n        if (cell_count[c] == 0) viol_conn += 1;\n        else if (comp_count[c] != 1) viol_conn += comp_count[c] - 1;\n    }\n\n    // Connectivity for 0 (must be connected to the outside)\n    int head = 0, tail = 0;\n    for (int idx : boundary_idx) {\n        if (g[idx] == 0 && vis[idx] != vis_token) {\n            vis[idx] = vis_token;\n            bfs_queue[tail++] = idx;\n        }\n    }\n    while (head < tail) {\n        int v = bfs_queue[head++];\n        for (int nbr : nb[v]) {\n            if (nbr != -1 && g[nbr] == 0 && vis[nbr] != vis_token) {\n                vis[nbr] = vis_token;\n                bfs_queue[tail++] = nbr;\n            }\n        }\n    }\n    int unvisited_0 = 0;\n    for (int i = 0; i < N2; ++i) {\n        if (g[i] == 0 && vis[i] != vis_token) ++unvisited_0;\n    }\n    viol_conn += unvisited_0;\n\n    // Adjacency\n    int adj[MAXC][MAXC] = {0};\n    for (int i = 0; i < N2; ++i) {\n        int c1 = g[i];\n        if (i % N < N - 1) {\n            int c2 = g[i + 1];\n            if (c1 != c2) { adj[c1][c2]++; adj[c2][c1]++; }\n        }\n        if (i / N < N - 1) {\n            int c2 = g[i + N];\n            if (c1 != c2) { adj[c1][c2]++; adj[c2][c1]++; }\n        }\n    }\n    // Boundary edges with outside 0\n    for (int idx : boundary_idx) {\n        int c = g[idx];\n        if (c != 0) {\n            adj[c][0]++;\n            adj[0][c]++;\n        }\n    }\n    for (int a = 0; a <= m; ++a) {\n        for (int b = a + 1; b <= m; ++b) {\n            if (adj_req[a][b]) {\n                if (adj[a][b] == 0) viol_adj++;\n            } else {\n                if (adj[a][b] > 0) viol_adj += adj[a][b];\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start_time = chrono::high_resolution_clock::now();\n    auto elapsed_ms = [&]() {\n        return chrono::duration_cast<chrono::milliseconds>(\n            chrono::high_resolution_clock::now() - start_time).count();\n    };\n\n    int n, m;\n    cin >> n >> m;\n    vector<vector<int>> orig(n, vector<int>(n));\n    for (int i = 0; i < n; ++i)\n        for (int j = 0; j < n; ++j)\n            cin >> orig[i][j];\n\n    // Build required adjacency graph from the original map\n    memset(adj_req, 0, sizeof(adj_req));\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c1 = orig[i][j];\n            if (j < n - 1) {\n                int c2 = orig[i][j + 1];\n                if (c1 != c2) adj_req[c1][c2] = adj_req[c2][c1] = true;\n            }\n            if (i < n - 1) {\n                int c2 = orig[i + 1][j];\n                if (c1 != c2) adj_req[c1][c2] = adj_req[c2][c1] = true;\n            }\n            if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                adj_req[c1][0] = adj_req[0][c1] = true;\n            }\n        }\n    }\n\n    // Precompute 4\u2011neighbors and boundary indices\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int idx = i * n + j;\n            nb[idx][0] = (i > 0) ? idx - n : -1;\n            nb[idx][1] = (i < n - 1) ? idx + n : -1;\n            nb[idx][2] = (j > 0) ? idx - 1 : -1;\n            nb[idx][3] = (j < n - 1) ? idx + 1 : -1;\n            if (i == 0 || i == n - 1 || j == 0 || j == n - 1)\n                boundary_idx.push_back(idx);\n        }\n    }\n\n    // ----- Phase 1: greedy erosion from the boundary -----\n    int g2d[N][N];\n    int count[MAXC] = {0};\n    int adj[MAXC][MAXC] = {0};\n\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            g2d[i][j] = orig[i][j];\n            count[orig[i][j]]++;\n        }\n    }\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c1 = g2d[i][j];\n            if (j < n - 1) {\n                int c2 = g2d[i][j + 1];\n                if (c1 != c2) { adj[c1][c2]++; adj[c2][c1]++; }\n            }\n            if (i < n - 1) {\n                int c2 = g2d[i + 1][j];\n                if (c1 != c2) { adj[c1][c2]++; adj[c2][c1]++; }\n            }\n            if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                if (c1 != 0) { adj[c1][0]++; adj[0][c1]++; }\n            }\n        }\n    }\n\n    int vis_g[N][N];\n    int vis_token_g = 0;\n    auto has_zero_neighbor = [&](int i, int j) -> bool {\n        if (i == 0 || i == n - 1 || j == 0 || j == n - 1) return true;\n        if (g2d[i - 1][j] == 0 || g2d[i + 1][j] == 0 ||\n            g2d[i][j - 1] == 0 || g2d[i][j + 1] == 0) return true;\n        return false;\n    };\n\n    auto try_remove = [&](int i, int j) -> bool {\n        int c = g2d[i][j];\n        if (c == 0 || count[c] <= 1) return false;\n        const int di[] = {-1, 1, 0, 0};\n        const int dj[] = {0, 0, -1, 1};\n\n        int lost[MAXC] = {0}, gain[MAXC] = {0};\n        for (int k = 0; k < 4; ++k) {\n            int ni = i + di[k], nj = j + dj[k];\n            int d;\n            if (ni < 0 || ni >= n || nj < 0 || nj >= n) d = 0;\n            else d = g2d[ni][nj];\n            if (d == c) continue;\n            lost[d]++;\n            if (d != 0) gain[d]++;\n        }\n        for (int d = 0; d <= m; ++d) {\n            if (lost[d] > 0 && adj_req[c][d] && adj[c][d] - lost[d] < 1) return false;\n            if (gain[d] > 0 && !adj_req[0][d]) return false;\n        }\n\n        // Connectivity of color c after removal\n        int si = -1, sj = -1;\n        for (int k = 0; k < 4; ++k) {\n            int ni = i + di[k], nj = j + dj[k];\n            if (ni >= 0 && ni < n && nj >= 0 && nj < n && g2d[ni][nj] == c) {\n                si = ni; sj = nj; break;\n            }\n        }\n        if (si == -1) return false;\n        ++vis_token_g;\n        queue<pair<int,int>> q;\n        q.push({si, sj});\n        vis_g[si][sj] = vis_token_g;\n        int visited = 0;\n        while (!q.empty()) {\n            auto [x, y] = q.front(); q.pop();\n            visited++;\n            for (int k = 0; k < 4; ++k) {\n                int nx = x + di[k], ny = y + dj[k];\n                if (nx >= 0 && nx < n && ny >= 0 && ny < n &&\n                    !(nx == i && ny == j) && g2d[nx][ny] == c &&\n                    vis_g[nx][ny] != vis_token_g) {\n                    vis_g[nx][ny] = vis_token_g;\n                    q.push({nx, ny});\n                }\n            }\n        }\n        if (visited != count[c] - 1) return false;\n        return true;\n    };\n\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                if (g2d[i][j] == 0 || !has_zero_neighbor(i, j)) continue;\n                if (try_remove(i, j)) {\n                    int c = g2d[i][j];\n                    const int di[] = {-1, 1, 0, 0};\n                    const int dj[] = {0, 0, -1, 1};\n                    for (int k = 0; k < 4; ++k) {\n                        int ni = i + di[k], nj = j + dj[k];\n                        int d;\n                        if (ni < 0 || ni >= n || nj < 0 || nj >= n) d = 0;\n                        else d = g2d[ni][nj];\n                        if (d == c) continue;\n                        adj[c][d]--; adj[d][c]--;\n                        if (d != 0) { adj[0][d]++; adj[d][0]++; }\n                    }\n                    g2d[i][j] = 0;\n                    count[c]--;\n                    changed = true;\n                }\n            }\n        }\n    }\n\n    // Convert greedy result to 1D\n    int init_g[N2];\n    for (int i = 0; i < n; ++i)\n        for (int j = 0; j < n; ++j)\n            init_g[i * n + j] = g2d[i][j];\n\n    // ----- Phase 2: Simulated Annealing -----\n    int cur_g[N2];\n    memcpy(cur_g, init_g, sizeof(cur_g));\n    int best_valid_g[N2];\n    memcpy(best_valid_g, init_g, sizeof(best_valid_g));\n    int best_valid_E = -1;\n\n    int testE, testVc, testVa;\n    compute_energy(init_g, m, testE, testVc, testVa);\n    if (testVc == 0 && testVa == 0) best_valid_E = testE;\n\n    const double W_CONN = 5000.0;\n    const double W_ADJ  = 5000.0;\n    const double T_start = 100000.0;\n    const double T_end   = 0.1;\n\n    int cur_E, cur_vc, cur_va;\n    compute_energy(cur_g, m, cur_E, cur_vc, cur_va);\n    double cur_energy = -cur_E + W_CONN * cur_vc + W_ADJ * cur_va;\n    double best_energy = cur_energy;\n\n    uint64_t rng_state = 123456789;\n    auto rng_next = [&]() -> uint64_t {\n        rng_state = rng_state * 6364136223846793005ULL + 1442695040888963407ULL;\n        return rng_state >> 33;\n    };\n    auto rng_int = [&](int n) { return rng_next() % n; };\n    auto rng_double = [&]() { return (rng_next() & 0xFFFFFFFF) / 4294967296.0; };\n\n    while (elapsed_ms() < 1800) {\n        double progress = elapsed_ms() / 1800.0;\n        double T = T_start * pow(T_end / T_start, progress);\n\n        int idx = rng_int(N2);\n        int old_c = cur_g[idx];\n        int new_c = (rng_double() < 0.5) ? 0 : (rng_int(m) + 1);\n        if (new_c == old_c) continue;\n\n        cur_g[idx] = new_c;\n        int new_E, new_vc, new_va;\n        compute_energy(cur_g, m, new_E, new_vc, new_va);\n        double new_energy = -new_E + W_CONN * new_vc + W_ADJ * new_va;\n        double delta = new_energy - cur_energy;\n\n        bool accept = (delta <= 0) || (rng_double() < exp(-delta / T));\n        if (accept) {\n            cur_energy = new_energy;\n            cur_E = new_E; cur_vc = new_vc; cur_va = new_va;\n            if (new_energy < best_energy) best_energy = new_energy;\n            if (new_vc == 0 && new_va == 0 && new_E > best_valid_E) {\n                best_valid_E = new_E;\n                memcpy(best_valid_g, cur_g, sizeof(best_valid_g));\n            }\n        } else {\n            cur_g[idx] = old_c;\n        }\n    }\n\n    // Output the best valid grid found (fallback to the original if none)\n    if (best_valid_E < 0) {\n        // Use the original input (always valid)\n        for (int i = 0; i < n; ++i)\n            for (int j = 0; j < n; ++j)\n                best_valid_g[i * n + j] = orig[i][j];\n    }\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (j) cout << ' ';\n            cout << best_valid_g[i * n + j];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <cmath>\n#include <functional>\n\nusing namespace std;\n\nint Q_total;\nint used_queries = 0;\n\n// safe query: outputs and reads, increments used_queries\nchar ask(const vector<int>& L, const vector<int>& R) {\n    cout << L.size() << \" \" << R.size();\n    for (int x : L) cout << \" \" << x;\n    for (int x : R) cout << \" \" << x;\n    cout << endl;\n    char res; cin >> res;\n    used_queries++;\n    return res;\n}\n\nchar compare_items(int a, int b) {\n    return ask({a}, {b});\n}\n\nstruct TournamentTree {\n    int N;\n    int size;\n    vector<int> tree;       // 2*size, leaves indices\n    vector<int> leaf_pos;   // mapping item -> leaf index\n    vector<int> sorted;      // extracted items in descending order\n\n    TournamentTree(int n) : N(n) {\n        size = 1;\n        while (size < N) size <<= 1;\n        tree.assign(2 * size, -1);\n        leaf_pos.resize(N);\n        for (int i = 0; i < N; ++i) {\n            int leaf = size + i;\n            tree[leaf] = i;\n            leaf_pos[i] = leaf;\n        }\n        // build heap bottom-up\n        for (int i = size - 1; i >= 1; --i) {\n            int l = tree[2*i], r = tree[2*i+1];\n            if (l == -1) tree[i] = r;\n            else if (r == -1) tree[i] = l;\n            else {\n                if (used_queries >= Q_total) break;\n                char res = compare_items(l, r);\n                if (res == '>') tree[i] = l;\n                else if (res == '<') tree[i] = r;\n                else tree[i] = l;\n            }\n        }\n    }\n\n    // extract the current winner (largest remaining)\n    // returns item index, -1 if empty, -2 if query limit hit\n    int extract() {\n        if (tree[1] == -1) return -1;\n        if (used_queries >= Q_total) return -2;\n        int winner = tree[1];\n        int leaf = leaf_pos[winner];\n        tree[leaf] = -1;\n        int node = leaf / 2;\n        while (node >= 1) {\n            int l = tree[2*node], r = tree[2*node+1];\n            if (l == -1) tree[node] = r;\n            else if (r == -1) tree[node] = l;\n            else {\n                if (used_queries >= Q_total) return -2;\n                char res = compare_items(l, r);\n                if (res == '>') tree[node] = l;\n                else if (res == '<') tree[node] = r;\n                else tree[node] = l;\n            }\n            node /= 2;\n        }\n        sorted.push_back(winner);\n        return winner;\n    }\n\n    // return remaining items in a linear extension of the heap order (BFS)\n    vector<int> get_remaining_order() {\n        vector<int> ord;\n        vector<bool> seen(N, false);\n        for (int i = 1; i < 2*size; ++i) {\n            int it = tree[i];\n            if (it != -1 && !seen[it]) {\n                seen[it] = true;\n                ord.push_back(it);\n            }\n        }\n        return ord;\n    }\n};\n\n// greedy best-fit decreasing partition\nvector<int> greedy_partition(const vector<double>& w, int D) {\n    int N = w.size();\n    vector<pair<double,int>> items(N);\n    for (int i = 0; i < N; ++i) items[i] = {w[i], i};\n    sort(items.begin(), items.end(), [](auto& a, auto& b) { return a.first > b.first; });\n    vector<int> P(N, 0);\n    vector<double> bin_sum(D, 0.0);\n    for (auto& p : items) {\n        int idx = p.second;\n        int best = 0;\n        for (int b = 1; b < D; ++b)\n            if (bin_sum[b] < bin_sum[best]) best = b;\n        P[idx] = best;\n        bin_sum[best] += p.first;\n    }\n    return P;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int N, D, Q;\n    cin >> N >> D >> Q;\n    Q_total = Q;\n\n    // precompute expected order statistics for exponential with lambda=1e-5\n    vector<double> H(N + 1, 0.0);\n    for (int i = 1; i <= N; ++i) H[i] = H[i-1] + 1.0 / i;\n    vector<double> exp_w(N);\n    for (int r = 0; r < N; ++r) {\n        exp_w[r] = 100000.0 * (H[N] - H[r]); // r=0 largest\n    }\n\n    // Phase 1: tournament tree & extraction\n    TournamentTree tt(N);\n    // extract as many as queries allow\n    while (used_queries < Q_total) {\n        int res = tt.extract();\n        if (res == -1) break;      // no more items\n        if (res == -2) break;      // hit query limit while inside\n    }\n    vector<int>& sorted = tt.sorted;\n    int K = sorted.size();\n    vector<int> remaining_order = tt.get_remaining_order();\n\n    // initial weights: assign expected weights according to the overall order\n    vector<double> w(N, 1.0);\n    for (int i = 0; i < K; ++i) w[sorted[i]] = exp_w[i];\n    for (int j = 0; j < (int)remaining_order.size(); ++j)\n        w[remaining_order[j]] = exp_w[K + j];\n\n    // we will store bin comparison queries for post-processing\n    struct BinQuery { vector<int> L, R; char res; };\n    vector<BinQuery> bin_queries;\n\n    // Phase 2: remaining queries for bin comparisons\n    if (used_queries < Q_total) {\n        vector<int> P = greedy_partition(w, D);\n        while (used_queries < Q_total) {\n            vector<double> bin_sum(D, 0.0);\n            for (int i = 0; i < N; ++i) bin_sum[P[i]] += w[i];\n            // find two bins with closest sum\n            int b1 = -1, b2 = -1;\n            double min_diff = 1e30;\n            for (int i = 0; i < D; ++i) {\n                if (bin_sum[i] == 0) continue;\n                for (int j = i + 1; j < D; ++j) {\n                    if (bin_sum[j] == 0) continue;\n                    double diff = fabs(bin_sum[i] - bin_sum[j]);\n                    if (diff < min_diff) { min_diff = diff; b1 = i; b2 = j; }\n                }\n            }\n            if (b1 == -1) { b1 = 0; b2 = (D > 1 ? 1 : 0); }\n            vector<int> L, R;\n            for (int i = 0; i < N; ++i) {\n                if (P[i] == b1) L.push_back(i);\n                else if (P[i] == b2) R.push_back(i);\n            }\n            char res = ask(L, R);\n            bin_queries.push_back({L, R, res});\n\n            // online adjustment\n            double sL = 0, sR = 0;\n            for (int i : L) sL += w[i];\n            for (int i : R) sR += w[i];\n            double margin = 0.0;\n            if (res == '<' && sL >= sR - margin) {\n                double error = sL - sR + margin;\n                double adj = 0.5 * error / (L.size() + R.size());\n                for (int i : L) w[i] -= adj;\n                for (int i : R) w[i] += adj;\n            } else if (res == '>' && sL <= sR + margin) {\n                double error = sR - sL + margin;\n                double adj = 0.5 * error / (L.size() + R.size());\n                for (int i : L) w[i] += adj;\n                for (int i : R) w[i] -= adj;\n            } else if (res == '=' && fabs(sL - sR) > margin) {\n                double diff = sL - sR;\n                double adj = 0.5 * diff / (L.size() + R.size());\n                for (int i : L) w[i] -= adj;\n                for (int i : R) w[i] += adj;\n            }\n            // clip\n            for (int i : L) w[i] = max(w[i], 1.0);\n            for (int i : R) w[i] = max(w[i], 1.0);\n            // enforce order among extracted items\n            for (int i = 0; i + 1 < K; ++i) {\n                if (w[sorted[i]] < w[sorted[i+1]]) {\n                    double avg = (w[sorted[i]] + w[sorted[i+1]]) / 2.0;\n                    w[sorted[i]] = avg + 0.5;\n                    w[sorted[i+1]] = avg - 0.5;\n                }\n            }\n            // recompute partition occasionally\n            if (used_queries % 5 == 0) P = greedy_partition(w, D);\n        }\n    }\n\n    // Phase 3: post-process weight refinement using all bin queries\n    if (!bin_queries.empty()) {\n        // construct full order: sorted + remaining_order\n        vector<int> full_order = sorted;\n        full_order.insert(full_order.end(), remaining_order.begin(), remaining_order.end());\n        int iterations = min(2000, (int)bin_queries.size() * 5);\n        double step = 0.3;\n        for (int it = 0; it < iterations; ++it) {\n            for (auto& q : bin_queries) {\n                double sL = 0, sR = 0;\n                for (int i : q.L) sL += w[i];\n                for (int i : q.R) sR += w[i];\n                if (q.res == '<' && sL >= sR) {\n                    double error = sL - sR + 1.0;\n                    double adj = step * error / (q.L.size() + q.R.size());\n                    for (int i : q.L) w[i] -= adj;\n                    for (int i : q.R) w[i] += adj;\n                } else if (q.res == '>' && sL <= sR) {\n                    double error = sR - sL + 1.0;\n                    double adj = step * error / (q.L.size() + q.R.size());\n                    for (int i : q.L) w[i] += adj;\n                    for (int i : q.R) w[i] -= adj;\n                } else if (q.res == '=' && fabs(sL - sR) > 0.5) {\n                    double diff = sL - sR;\n                    double adj = step * diff / (q.L.size() + q.R.size());\n                    for (int i : q.L) w[i] -= adj;\n                    for (int i : q.R) w[i] += adj;\n                }\n                for (int i : q.L) w[i] = max(w[i], 1.0);\n                for (int i : q.R) w[i] = max(w[i], 1.0);\n            }\n            // enforce monotone decreasing on full_order\n            for (int i = 0; i + 1 < (int)full_order.size(); ++i) {\n                int a = full_order[i], b = full_order[i+1];\n                if (w[a] < w[b]) {\n                    double avg = (w[a] + w[b]) / 2.0;\n                    w[a] = avg + 0.5;\n                    w[b] = avg - 0.5;\n                }\n                if (w[a] < 1.0) w[a] = 1.0;\n                if (w[b] < 1.0) w[b] = 1.0;\n            }\n            // additionally, ensure K extracted items >= any remaining\n            if (K > 0 && full_order.size() > K) {\n                for (int j = K; j < (int)full_order.size(); ++j) {\n                    if (w[full_order[K-1]] < w[full_order[j]]) {\n                        double avg = (w[full_order[K-1]] + w[full_order[j]]) / 2.0;\n                        w[full_order[K-1]] = avg + 0.5;\n                        w[full_order[j]] = avg - 0.5;\n                    }\n                }\n            }\n            step *= 0.999;\n            if (step < 0.01) step = 0.01;\n        }\n    }\n\n    // Final partition: simulated annealing using estimated weights\n    vector<int> P = greedy_partition(w, D);\n    vector<double> bin_sum(D, 0.0);\n    for (int i = 0; i < N; ++i) bin_sum[P[i]] += w[i];\n    double mean = accumulate(bin_sum.begin(), bin_sum.end(), 0.0) / D;\n    double var = 0.0;\n    for (double s : bin_sum) var += (s - mean) * (s - mean);\n    var /= D;\n\n    mt19937 rng(12345);\n    uniform_int_distribution<int> dist_item(0, N - 1);\n    uniform_int_distribution<int> dist_bin(0, D - 1);\n    uniform_real_distribution<double> uni(0.0, 1.0);\n    const int SA_ITERS = 200000;\n    double T = 1.0;\n    for (int it = 0; it < SA_ITERS; ++it) {\n        int i = dist_item(rng);\n        int old_b = P[i];\n        int new_b = dist_bin(rng);\n        if (new_b == old_b) continue;\n\n        double new_old = bin_sum[old_b] - w[i];\n        double new_new = bin_sum[new_b] + w[i];\n        double delta = ((new_old - mean) * (new_old - mean) + \n                        (new_new - mean) * (new_new - mean)\n                        - (bin_sum[old_b] - mean) * (bin_sum[old_b] - mean)\n                        - (bin_sum[new_b] - mean) * (bin_sum[new_b] - mean)) / D;\n        if (delta < 0 || uni(rng) < exp(-delta / T)) {\n            P[i] = new_b;\n            bin_sum[old_b] = new_old;\n            bin_sum[new_b] = new_new;\n            var += delta;\n        }\n        T *= 0.99995;\n        if (T < 0.001) T = 0.001;\n    }\n\n    // output final division\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << \" \";\n        cout << P[i];\n    }\n    cout << endl;\n\n    return 0;\n}","ahc026":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <climits>\n#include <utility>\n\nusing namespace std;\n\nstruct State {\n    vector<vector<int>> stacks;\n    vector<pair<int,int>> pos;     // pos[box] = {stack, index}\n    vector<int> min_val;           // minimum value in each stack, INT_MAX if empty\n    int n, m;\n\n    State(const vector<vector<int>>& init, int n_, int m_) : n(n_), m(m_) {\n        stacks = init;\n        pos.assign(n + 1, {-1, -1});\n        min_val.assign(m, INT_MAX);\n        for (int i = 0; i < m; ++i) {\n            for (int j = 0; j < (int)stacks[i].size(); ++j) {\n                int box = stacks[i][j];\n                pos[box] = {i, j};\n            }\n            if (!stacks[i].empty())\n                min_val[i] = *min_element(stacks[i].begin(), stacks[i].end());\n        }\n    }\n\n    // move boxes [idx .. end] from stack s to stack t\n    void move_block(int s, int idx, int t) {\n        vector<int> block(stacks[s].begin() + idx, stacks[s].end());\n        stacks[s].erase(stacks[s].begin() + idx, stacks[s].end());\n        for (int val : block) {\n            stacks[t].push_back(val);\n            pos[val] = {t, (int)stacks[t].size() - 1};\n        }\n        if (stacks[s].empty()) min_val[s] = INT_MAX;\n        else min_val[s] = *min_element(stacks[s].begin(), stacks[s].end());\n        if (stacks[t].empty()) min_val[t] = INT_MAX;\n        else min_val[t] = *min_element(stacks[t].begin(), stacks[t].end());\n    }\n\n    // remove the top box of stack s (the current target box)\n    void carry_out(int s) {\n        int v = stacks[s].back();\n        stacks[s].pop_back();\n        pos[v] = {-1, -1};\n        if (stacks[s].empty()) min_val[s] = INT_MAX;\n        else min_val[s] = *min_element(stacks[s].begin(), stacks[s].end());\n    }\n};\n\n// deterministic heuristic for choosing a destination stack\nint choose_target(const State& st, int s, int p) {\n    int max_block = -1;\n    for (int i = p + 1; i < (int)st.stacks[s].size(); ++i)\n        max_block = max(max_block, st.stacks[s][i]);\n\n    int best_t = -1;\n    int best_priority = -1;   // 2 = ideal, 1 = empty, 0 = violation\n    int best_key = 0;\n\n    for (int t = 0; t < st.m; ++t) {\n        if (t == s) continue;\n        if (st.stacks[t].empty()) {\n            if (best_priority < 1) {\n                best_priority = 1;\n                best_t = t;\n            }\n        } else {\n            int min_t = st.min_val[t];\n            if (min_t > max_block) {                   // ideal\n                if (best_priority < 2) {\n                    best_priority = 2;\n                    best_key = min_t;\n                    best_t = t;\n                } else if (best_priority == 2 && min_t < best_key) {\n                    best_key = min_t;\n                    best_t = t;\n                }\n            } else {                                    // violation\n                if (best_priority < 0) {\n                    best_priority = 0;\n                    best_key = min_t;\n                    best_t = t;\n                } else if (best_priority == 0 && min_t > best_key) {\n                    best_key = min_t;\n                    best_t = t;\n                }\n            }\n        }\n    }\n    return best_t;\n}\n\n// greedy simulation from box start_v to the end\nint simulate_rest(State state, int start_v) {\n    int total_cost = 0;\n    for (int v = start_v; v <= state.n; ++v) {\n        auto [s, p] = state.pos[v];\n        while (p != (int)state.stacks[s].size() - 1) {\n            int idx = p + 1;\n            int k = state.stacks[s].size() - idx;\n            int t = choose_target(state, s, p);\n            state.move_block(s, idx, t);\n            total_cost += k + 1;\n        }\n        state.carry_out(s);\n    }\n    return total_cost;\n}\n\nconst int SEARCH_DEPTH = 2;   // number of future branching points to explore\n\n// recursive search with limited depth (branch only when a move is necessary)\nint search(State state, int v, int depth) {\n    if (v > state.n) return 0;\n    auto [s, p] = state.pos[v];\n    if (p == (int)state.stacks[s].size() - 1) {\n        state.carry_out(s);\n        return search(state, v + 1, depth);\n    }\n    if (depth == 0) {\n        return simulate_rest(state, v);\n    }\n\n    int best_cost = INT_MAX;\n    int idx = p + 1;\n    int k = state.stacks[s].size() - idx;\n    for (int t = 0; t < state.m; ++t) {\n        if (t == s) continue;\n        State copy = state;\n        copy.move_block(s, idx, t);\n        copy.carry_out(s);\n        int cost = (k + 1) + search(copy, v + 1, depth - 1);\n        if (cost < best_cost) best_cost = cost;\n    }\n    return best_cost;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int n, m;\n    cin >> n >> m;\n    vector<vector<int>> init_stacks(m, vector<int>(n / m));\n    for (int i = 0; i < m; ++i)\n        for (int j = 0; j < n / m; ++j)\n            cin >> init_stacks[i][j];\n\n    State cur_state(init_stacks, n, m);\n    vector<pair<int,int>> ops;   // (v, i)  i=0 -> carry out, otherwise 1\u2011based stack index\n\n    for (int v = 1; v <= n; ++v) {\n        auto [s, p] = cur_state.pos[v];\n        if (p == (int)cur_state.stacks[s].size() - 1) {\n            // already on top\n            ops.push_back({v, 0});\n            cur_state.carry_out(s);\n        } else {\n            int idx = p + 1;\n            int k = cur_state.stacks[s].size() - idx;\n            int best_t = -1;\n            int best_total = INT_MAX;\n\n            // one\u2011step rollout with multi\u2011step lookahead\n            for (int t = 0; t < m; ++t) {\n                if (t == s) continue;\n                State copy = cur_state;\n                copy.move_block(s, idx, t);\n                copy.carry_out(s);\n                int total = (k + 1) + search(copy, v + 1, SEARCH_DEPTH);\n                if (total < best_total) {\n                    best_total = total;\n                    best_t = t;\n                }\n            }\n\n            int v_op = cur_state.stacks[s][idx];          // bottom box of the moved block\n            ops.push_back({v_op, best_t + 1});            // output uses 1\u2011based stack indices\n            cur_state.move_block(s, idx, best_t);\n\n            ops.push_back({v, 0});\n            cur_state.carry_out(s);\n        }\n    }\n\n    for (auto& op : ops)\n        cout << op.first << \" \" << op.second << \"\\n\";\n\n    return 0;\n}","ahc027":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <functional>\n#include <stack>\n#include <numeric>\n#include <cassert>\n\nusing namespace std;\n\n// ---------- Dinic max flow (with initial capacity storage) ----------\nstruct Dinic {\n    struct Edge {\n        int to, rev, cap, init;\n        Edge() {}\n        Edge(int to, int rev, int cap, int init) : to(to), rev(rev), cap(cap), init(init) {}\n    };\n    vector<vector<Edge>> g;\n    vector<int> level, iter;\n    Dinic(int n) : g(n) {}\n    void add_edge(int from, int to, int cap) {\n        g[from].push_back(Edge(to, (int)g[to].size(), cap, cap));\n        g[to].push_back(Edge(from, (int)g[from].size() - 1, 0, 0));\n    }\n    void bfs(int s) {\n        fill(level.begin(), level.end(), -1);\n        queue<int> q;\n        level[s] = 0;\n        q.push(s);\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (auto &e : g[v]) {\n                if (e.cap > 0 && level[e.to] < 0) {\n                    level[e.to] = level[v] + 1;\n                    q.push(e.to);\n                }\n            }\n        }\n    }\n    int dfs(int v, int t, int f) {\n        if (v == t) return f;\n        for (int &i = iter[v]; i < (int)g[v].size(); ++i) {\n            Edge &e = g[v][i];\n            if (e.cap > 0 && level[v] < level[e.to]) {\n                int d = dfs(e.to, t, min(f, e.cap));\n                if (d > 0) {\n                    e.cap -= d;\n                    g[e.to][e.rev].cap += d;\n                    return d;\n                }\n            }\n        }\n        return 0;\n    }\n    int max_flow(int s, int t) {\n        int flow = 0;\n        level.resize(g.size());\n        iter.resize(g.size());\n        while (true) {\n            bfs(s);\n            if (level[t] < 0) break;\n            fill(iter.begin(), iter.end(), 0);\n            int f;\n            while ((f = dfs(s, t, 1e9)) > 0) flow += f;\n        }\n        return flow;\n    }\n};\n\n// ---------- Eulerian circuit ----------\nstruct EulerEdge {\n    int to, rev;\n    bool used;\n};\n\nvector<int> euler_circuit(vector<vector<EulerEdge>>& adj) {\n    vector<int> res;\n    stack<int> st;\n    st.push(0);\n    while (!st.empty()) {\n        int u = st.top();\n        if (!adj[u].empty()) {\n            EulerEdge &e = adj[u].back();\n            if (e.used) {\n                adj[u].pop_back();\n                continue;\n            }\n            int v = e.to;\n            e.used = true;\n            adj[v][e.rev].used = true;\n            st.push(v);\n        } else {\n            res.push_back(u);\n            st.pop();\n        }\n    }\n    reverse(res.begin(), res.end());\n    return res;\n}\n\n// ---------- helper for average dirtiness ----------\nint64_t calc_sum_sq(const vector<int>& times, int L) {\n    if (times.empty()) return 0;\n    int k = times.size();\n    int64_t res = 0;\n    for (int i = 0; i < k - 1; ++i) {\n        int64_t diff = times[i + 1] - times[i];\n        res += diff * diff;\n    }\n    int64_t diff = times[0] + L - times.back();\n    res += diff * diff;\n    return res;\n}\n\n// ---------- fallback : original greedy + SA ----------\nstring fallback_solution(int N, int V, const vector<int>& d,\n                         const vector<vector<int>>& adj) {\n    // DFS double\n    vector<int> base_seq;\n    vector<bool> visited(V, false);\n    vector<int> stack = {0};\n    vector<int> edge_idx(V, 0);\n    visited[0] = true;\n    while (!stack.empty()) {\n        int u = stack.back();\n        if (edge_idx[u] < (int)adj[u].size()) {\n            int w = adj[u][edge_idx[u]++];\n            if (!visited[w]) {\n                visited[w] = true;\n                base_seq.push_back(w);\n                stack.push_back(w);\n            }\n        } else {\n            stack.pop_back();\n            if (!stack.empty()) {\n                base_seq.push_back(stack.back());\n            }\n        }\n    }\n    // base_seq ends with 0\n\n    int L0 = base_seq.size();\n    vector<int> cur_k(V, 0);\n    for (int c : base_seq) cur_k[c]++;\n\n    int L_target = 100000;\n    vector<int> seq = base_seq;\n    int L = L0;\n\n    // add extra cycles\n    double sum_sqrt = 0;\n    for (int i = 0; i < V; ++i) sum_sqrt += sqrt(d[i]);\n    vector<double> target_k(V);\n    for (int i = 0; i < V; ++i) target_k[i] = L_target * sqrt(d[i]) / sum_sqrt;\n\n    vector<int> parent(V, -1);\n    queue<int> q;\n    q.push(0);\n    parent[0] = -2;\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (int w : adj[u]) {\n            if (parent[w] == -1) {\n                parent[w] = u;\n                q.push(w);\n            }\n        }\n    }\n\n    while (L < L_target) {\n        int best = -1;\n        double best_score = -1;\n        for (int i = 0; i < V; ++i) {\n            double deficit = target_k[i] - cur_k[i];\n            if (deficit > 0) {\n                double score = d[i] * deficit;\n                if (score > best_score) {\n                    best_score = score;\n                    best = i;\n                }\n            }\n        }\n        if (best == -1) break;\n        int dest = best;\n        vector<int> path;\n        for (int u = dest; u != 0; u = parent[u]) path.push_back(u);\n        reverse(path.begin(), path.end());\n        int cycle_len = 2 * (int)path.size();\n        if (L + cycle_len > L_target) break;\n\n        for (int c : path) seq.push_back(c);\n        for (int i = (int)path.size() - 2; i >= 0; --i) seq.push_back(path[i]);\n        seq.push_back(0);\n\n        for (int i = 0; i < (int)path.size(); ++i) {\n            int c = path[i];\n            if (i == (int)path.size() - 1) cur_k[c] += 1;\n            else cur_k[c] += 2;\n        }\n        cur_k[0] += 1;\n        L += cycle_len;\n    }\n\n    // SA\n    vector<vector<int>> times(V);\n    for (int t = 0; t < L; ++t) times[seq[t]].push_back(t);\n    int64_t total_O = 0;\n    for (int i = 0; i < V; ++i) total_O += d[i] * calc_sum_sq(times[i], L);\n    vector<int> best_seq = seq;\n    int64_t best_O = total_O;\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> uni01(0.0, 1.0);\n\n    double T_start = max(1e7, (double)total_O / 1000.0);\n    double T_end = 1e2;\n    double total_time = 1.95;\n    auto start_time = chrono::steady_clock::now();\n\n    vector<int> affected;\n    vector<bool> is_aff(V, false);\n    vector<vector<int>> old_pos(V);\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed >= total_time) break;\n        double ratio = elapsed / total_time;\n        if (ratio > 1.0) ratio = 1.0;\n        double T = T_start * pow(T_end / T_start, ratio);\n\n        for (int c : affected) {\n            old_pos[c].clear();\n            is_aff[c] = false;\n        }\n        affected.clear();\n\n        if (L < 3) break;\n        int max_len = min(200, L - 2);\n        if (max_len < 1) continue;\n        uniform_int_distribution<int> l_dist(1, L - 3);\n        int l = l_dist(rng);\n        int max_r = min(L - 2, l + max_len - 1);\n        if (max_r < l) continue;\n        uniform_int_distribution<int> r_dist(l, max_r);\n        int r = r_dist(rng);\n\n        int prev = l - 1, next = r + 1;\n        int u1 = seq[prev], v1 = seq[r];\n        int u2 = seq[l], v2 = seq[next];\n        bool adj1 = false, adj2 = false;\n        for (int w : adj[u1]) if (w == v1) { adj1 = true; break; }\n        for (int w : adj[u2]) if (w == v2) { adj2 = true; break; }\n        if (!adj1 || !adj2) continue;\n\n        for (int p = l; p <= r; ++p) {\n            int c = seq[p];\n            if (!is_aff[c]) {\n                is_aff[c] = true;\n                affected.push_back(c);\n            }\n            old_pos[c].push_back(p);\n        }\n\n        int64_t delta = 0;\n        vector<pair<int, vector<int>>> updates;\n        for (int c : affected) {\n            const vector<int>& old_times = times[c];\n            const vector<int>& op = old_pos[c];\n            int64_t old_sq = calc_sum_sq(old_times, L);\n\n            vector<int> new_times;\n            for (int t : old_times) if (t < l) new_times.push_back(t);\n            vector<int> np;\n            for (int p : op) np.push_back(l + r - p);\n            sort(np.begin(), np.end());\n            for (int t : np) new_times.push_back(t);\n            for (int t : old_times) if (t > r) new_times.push_back(t);\n\n            int64_t new_sq = calc_sum_sq(new_times, L);\n            delta += d[c] * (new_sq - old_sq);\n            updates.emplace_back(c, std::move(new_times));\n        }\n\n        bool accept = (delta <= 0);\n        if (!accept) {\n            double prob = exp(-delta / T);\n            if (uni01(rng) < prob) accept = true;\n        }\n\n        if (accept) {\n            reverse(seq.begin() + l, seq.begin() + r + 1);\n            for (auto& p : updates) {\n                times[p.first] = std::move(p.second);\n            }\n            total_O += delta;\n            if (total_O < best_O) {\n                best_O = total_O;\n                best_seq = seq;\n            }\n        }\n    }\n\n    string ans;\n    int cur = 0;\n    for (int nxt : best_seq) {\n        int ci = cur / N, cj = cur % N;\n        int ni = nxt / N, nj = nxt % N;\n        if (ni == ci - 1) ans += 'U';\n        else if (ni == ci + 1) ans += 'D';\n        else if (nj == cj - 1) ans += 'L';\n        else if (nj == cj + 1) ans += 'R';\n        else ans += 'U';\n        cur = nxt;\n    }\n    return ans;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int N;\n    cin >> N;\n    int V = N * N;\n    vector<string> h(N - 1), v(N);\n    for (int i = 0; i < N - 1; ++i) cin >> h[i];\n    for (int i = 0; i < N; ++i) cin >> v[i];\n    vector<int> d(V);\n    for (int i = 0; i < V; ++i) cin >> d[i];\n\n    auto id = [&](int i, int j) { return i * N + j; };\n\n    // adjacency list with edge ids\n    vector<vector<pair<int,int>>> adj(V);  // (neighbor, edge_id)\n    vector<pair<int,int>> edge_uv;          // (u,v) for each edge\n    int E = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = id(i, j);\n            if (j + 1 < N && v[i][j] == '0') {\n                int w = id(i, j + 1);\n                adj[u].emplace_back(w, E);\n                adj[w].emplace_back(u, E);\n                edge_uv.emplace_back(u, w);\n                E++;\n            }\n            if (i + 1 < N && h[i][j] == '0') {\n                int w = id(i + 1, j);\n                adj[u].emplace_back(w, E);\n                adj[w].emplace_back(u, E);\n                edge_uv.emplace_back(u, w);\n                E++;\n            }\n        }\n    }\n\n    // BFS to build spanning tree and compute deg_T\n    vector<int> parent(V, -1);\n    vector<int> deg_T(V, 0);\n    vector<int> tree_edge(E, 0);\n    queue<int> q;\n    q.push(0);\n    parent[0] = -2;\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (auto [w, eid] : adj[u]) {\n            if (parent[w] == -1) {\n                parent[w] = u;\n                deg_T[u]++;\n                deg_T[w]++;\n                tree_edge[eid] = 1;\n                q.push(w);\n            }\n        }\n    }\n\n    // partition left/right (bipartite)\n    vector<bool> left(V, false);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            left[id(i,j)] = ((i + j) % 2 == 0);\n\n    // sqrt_d\n    vector<double> sqrt_d(V);\n    for (int i = 0; i < V; ++i) sqrt_d[i] = sqrt(d[i]);\n\n    double sum_sqrt_left = 0, sum_sqrt_right = 0;\n    for (int i = 0; i < V; ++i) {\n        if (left[i]) sum_sqrt_left += sqrt_d[i];\n        else sum_sqrt_right += sqrt_d[i];\n    }\n\n    // f_min based on tree degree\n    vector<int> f_min(V);\n    int total_min_left = 0, total_min_right = 0;\n    for (int i = 0; i < V; ++i) {\n        f_min[i] = max(1, (deg_T[i] + 1) / 2); // ceil(deg/2)\n        if (left[i]) total_min_left += f_min[i];\n        else total_min_right += f_min[i];\n    }\n\n    int L_target = 100000;\n    int L_left_target = L_target / 2;\n    int L_right_target = L_target / 2;\n\n    int add_left = L_left_target - total_min_left;\n    int add_right = L_right_target - total_min_right;\n\n    // If impossible, fallback\n    if (add_left < 0 || add_right < 0) {\n        // need simple adjacency for fallback\n        vector<vector<int>> simple_adj(V);\n        for (int i = 0; i < V; ++i)\n            for (auto [w, _] : adj[i])\n                simple_adj[i].push_back(w);\n        string ans = fallback_solution(N, V, d, simple_adj);\n        cout << ans << endl;\n        return 0;\n    }\n\n    vector<int> f = f_min;\n\n    // allocate additional visits proportionally to sqrt(d)\n    auto allocate = [&](bool is_left, int total_add) {\n        vector<int> idx;\n        for (int i = 0; i < V; ++i) if (left[i] == is_left) idx.push_back(i);\n        int n = idx.size();\n        vector<double> w(n);\n        for (int i = 0; i < n; ++i) w[i] = sqrt_d[idx[i]];\n        double sum_w = accumulate(w.begin(), w.end(), 0.0);\n        vector<int> alloc(n, 0);\n        int sum_alloc = 0;\n        vector<pair<double, int>> frac;\n        for (int i = 0; i < n; ++i) {\n            double exact = w[i] * total_add / sum_w;\n            int base = (int)exact;\n            alloc[i] = base;\n            sum_alloc += base;\n            frac.emplace_back(exact - base, i);\n        }\n        sort(frac.rbegin(), frac.rend());\n        int rem = total_add - sum_alloc;\n        for (int i = 0; i < rem; ++i) alloc[frac[i].second]++;\n        for (int i = 0; i < n; ++i) f[idx[i]] += alloc[i];\n    };\n\n    allocate(true, add_left);\n    allocate(false, add_right);\n\n    // b_i and rem\n    vector<int> b(V), rem(V);\n    int sum_rem_left = 0;\n    for (int i = 0; i < V; ++i) {\n        b[i] = 2 * f[i];\n        rem[i] = b[i] - deg_T[i];\n        if (left[i]) sum_rem_left += rem[i];\n    }\n\n    // Dinic\n    int S = V, T = V + 1;\n    Dinic dinic(V + 2);\n    vector<int> flow_fwd_idx(E, -1);\n\n    for (int eid = 0; eid < E; ++eid) {\n        int u = edge_uv[eid].first, v = edge_uv[eid].second;\n        if (!left[u]) swap(u, v);\n        // forward edge index in g[u] before adding\n        int idx = (int)dinic.g[u].size();\n        dinic.add_edge(u, v, 1000000); // INF capacity\n        flow_fwd_idx[eid] = idx;\n    }\n\n    for (int i = 0; i < V; ++i) {\n        if (left[i]) dinic.add_edge(S, i, rem[i]);\n        else dinic.add_edge(i, T, rem[i]);\n    }\n\n    int flow_val = dinic.max_flow(S, T);\n\n    if (flow_val != sum_rem_left) {\n        // fallback to original method\n        vector<vector<int>> simple_adj(V);\n        for (int i = 0; i < V; ++i)\n            for (auto [w, _] : adj[i])\n                simple_adj[i].push_back(w);\n        string ans = fallback_solution(N, V, d, simple_adj);\n        cout << ans << endl;\n        return 0;\n    }\n\n    // Compute edge multiplicities\n    vector<int> mult(E, 0);\n    for (int eid = 0; eid < E; ++eid) {\n        int base = tree_edge[eid];\n        int u = edge_uv[eid].first, v = edge_uv[eid].second;\n        if (!left[u]) swap(u, v);\n        int fwd_idx = flow_fwd_idx[eid];\n        int fe = dinic.g[u][fwd_idx].init - dinic.g[u][fwd_idx].cap; // flow amount\n        mult[eid] = base + fe;\n    }\n\n    // Build Eulerian multigraph\n    vector<vector<EulerEdge>> euler_adj(V);\n    auto add_euler_edge = [&](int u, int v) {\n        euler_adj[u].push_back({v, (int)euler_adj[v].size(), false});\n        euler_adj[v].push_back({u, (int)euler_adj[u].size() - 1, false});\n    };\n    for (int eid = 0; eid < E; ++eid) {\n        int m = mult[eid];\n        int u = edge_uv[eid].first, v = edge_uv[eid].second;\n        for (int k = 0; k < m; ++k) add_euler_edge(u, v);\n    }\n\n    vector<int> circuit = euler_circuit(euler_adj);\n    // rotate to start at 0\n    int first0 = find(circuit.begin(), circuit.end(), 0) - circuit.begin();\n    vector<int> rot;\n    rot.insert(rot.end(), circuit.begin() + first0, circuit.end());\n    rot.insert(rot.end(), circuit.begin(), circuit.begin() + first0);\n    // seq = moves (skip initial 0)\n    vector<int> seq(rot.begin() + 1, rot.end());\n    int L = seq.size();\n\n    // ---------- Simulated Annealing ----------\n    vector<vector<int>> times(V);\n    for (int t = 0; t < L; ++t) times[seq[t]].push_back(t);\n    int64_t total_O = 0;\n    for (int i = 0; i < V; ++i) total_O += d[i] * calc_sum_sq(times[i], L);\n    vector<int> best_seq = seq;\n    int64_t best_O = total_O;\n\n    // simple adjacency for SA checks\n    vector<vector<int>> simple_adj(V);\n    for (int i = 0; i < V; ++i)\n        for (auto [w, _] : adj[i])\n            simple_adj[i].push_back(w);\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> uni01(0.0, 1.0);\n\n    double T_start = max(1e7, (double)total_O / 1000.0);\n    double T_end = 1e2;\n    double total_time = 1.95;\n    auto start_time = chrono::steady_clock::now();\n\n    vector<int> affected;\n    vector<bool> is_aff(V, false);\n    vector<vector<int>> old_pos(V);\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed >= total_time) break;\n        double ratio = elapsed / total_time;\n        if (ratio > 1.0) ratio = 1.0;\n        double T = T_start * pow(T_end / T_start, ratio);\n\n        for (int c : affected) {\n            old_pos[c].clear();\n            is_aff[c] = false;\n        }\n        affected.clear();\n\n        if (L < 3) break;\n        int max_len = min(200, L - 2);\n        if (max_len < 1) continue;\n        uniform_int_distribution<int> l_dist(1, L - 3);\n        int l = l_dist(rng);\n        int max_r = min(L - 2, l + max_len - 1);\n        if (max_r < l) continue;\n        uniform_int_distribution<int> r_dist(l, max_r);\n        int r = r_dist(rng);\n\n        int prev = l - 1, next = r + 1;\n        int u1 = seq[prev], v1 = seq[r];\n        int u2 = seq[l], v2 = seq[next];\n        bool adj1 = false, adj2 = false;\n        for (int w : simple_adj[u1]) if (w == v1) { adj1 = true; break; }\n        for (int w : simple_adj[u2]) if (w == v2) { adj2 = true; break; }\n        if (!adj1 || !adj2) continue;\n\n        for (int p = l; p <= r; ++p) {\n            int c = seq[p];\n            if (!is_aff[c]) {\n                is_aff[c] = true;\n                affected.push_back(c);\n            }\n            old_pos[c].push_back(p);\n        }\n\n        int64_t delta = 0;\n        vector<pair<int, vector<int>>> updates;\n        for (int c : affected) {\n            const vector<int>& old_times = times[c];\n            const vector<int>& op = old_pos[c];\n            int64_t old_sq = calc_sum_sq(old_times, L);\n\n            vector<int> new_times;\n            for (int t : old_times) if (t < l) new_times.push_back(t);\n            vector<int> np;\n            for (int p : op) np.push_back(l + r - p);\n            sort(np.begin(), np.end());\n            for (int t : np) new_times.push_back(t);\n            for (int t : old_times) if (t > r) new_times.push_back(t);\n\n            int64_t new_sq = calc_sum_sq(new_times, L);\n            delta += d[c] * (new_sq - old_sq);\n            updates.emplace_back(c, std::move(new_times));\n        }\n\n        bool accept = (delta <= 0);\n        if (!accept) {\n            double prob = exp(-delta / T);\n            if (uni01(rng) < prob) accept = true;\n        }\n\n        if (accept) {\n            reverse(seq.begin() + l, seq.begin() + r + 1);\n            for (auto& p : updates) {\n                times[p.first] = std::move(p.second);\n            }\n            total_O += delta;\n            if (total_O < best_O) {\n                best_O = total_O;\n                best_seq = seq;\n            }\n        }\n    }\n\n    // Output best route\n    string ans;\n    int cur = 0;\n    for (int nxt : best_seq) {\n        int ci = cur / N, cj = cur % N;\n        int ni = nxt / N, nj = nxt % N;\n        if (ni == ci - 1) ans += 'U';\n        else if (ni == ci + 1) ans += 'D';\n        else if (nj == cj - 1) ans += 'L';\n        else if (nj == cj + 1) ans += 'R';\n        else ans += 'U'; // fallback\n        cur = nxt;\n    }\n    cout << ans << endl;\n\n    return 0;\n}","ahc028":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <chrono>\n#include <cmath>\n#include <cstdlib>\n#include <unordered_map>\n#include <utility>\n\nusing namespace std;\n\nconst int INF = 1e9;\n\nstruct Xorshift {\n    unsigned int x, y, z, w;\n    Xorshift() {\n        auto seed = chrono::steady_clock::now().time_since_epoch().count();\n        x = seed & 0xFFFFFFFF;\n        y = (seed >> 32) ^ 0x12345678;\n        z = seed ^ 0x9abcdef0;\n        w = seed ^ 0xdeadbeef;\n    }\n    unsigned int next() {\n        unsigned int t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = w ^ (w >> 19) ^ t ^ (t >> 8);\n    }\n    int nextInt(int n) { return next() % n; }\n};\n\nint N, M;\nint start_i, start_j;\nchar grid[15][15];\nvector<string> t;\nvector<int> pos[26];\nint dist[225][225];\nint start_idx;\n\nint dp_prev[225], dp_cur[225];\n\nint compute_DP_cost(const string& S) {\n    if (S.empty()) return 0;\n    char c0 = S[0] - 'A';\n    auto& cells0 = pos[c0];\n    int sz0 = cells0.size();\n    for (int i = 0; i < sz0; ++i) {\n        dp_prev[i] = dist[start_idx][cells0[i]] + 1;\n    }\n    const int* cells_prev = cells0.data();\n    int sz_prev = sz0;\n    for (size_t k = 1; k < S.size(); ++k) {\n        char c = S[k] - 'A';\n        auto& cells_cur = pos[c];\n        int sz_cur = cells_cur.size();\n        fill_n(dp_cur, sz_cur, INF);\n        for (int j = 0; j < sz_prev; ++j) {\n            int prev_cell = cells_prev[j];\n            int base = dp_prev[j] + 1;\n            const int* drow = dist[prev_cell];\n            for (int i = 0; i < sz_cur; ++i) {\n                int cost = base + drow[cells_cur[i]];\n                if (cost < dp_cur[i]) dp_cur[i] = cost;\n            }\n        }\n        swap(dp_prev, dp_cur);\n        cells_prev = cells_cur.data();\n        sz_prev = sz_cur;\n    }\n    return *min_element(dp_prev, dp_prev + sz_prev);\n}\n\nvoid compute_DP_path(const string& S, vector<int>& path_out) {\n    int L = S.size();\n    path_out.resize(L);\n    if (L == 0) return;\n    vector<vector<int>> step_cells(L);\n    vector<vector<int>> step_prev(L);\n    char c0 = S[0] - 'A';\n    auto& cells0 = pos[c0];\n    int sz0 = cells0.size();\n    step_cells[0] = cells0;\n    step_prev[0].assign(sz0, -1);\n    for (int i = 0; i < sz0; ++i) dp_prev[i] = dist[start_idx][cells0[i]] + 1;\n    const int* cells_prev = cells0.data();\n    int sz_prev = sz0;\n    for (int k = 1; k < L; ++k) {\n        char c = S[k] - 'A';\n        auto& cells_cur = pos[c];\n        int sz_cur = cells_cur.size();\n        step_cells[k] = cells_cur;\n        step_prev[k].assign(sz_cur, -1);\n        fill_n(dp_cur, sz_cur, INF);\n        for (int j = 0; j < sz_prev; ++j) {\n            int prev_cell = cells_prev[j];\n            int base = dp_prev[j] + 1;\n            const int* drow = dist[prev_cell];\n            for (int i = 0; i < sz_cur; ++i) {\n                int cost = base + drow[cells_cur[i]];\n                if (cost < dp_cur[i]) {\n                    dp_cur[i] = cost;\n                    step_prev[k][i] = j;\n                }\n            }\n        }\n        swap(dp_prev, dp_cur);\n        cells_prev = cells_cur.data();\n        sz_prev = sz_cur;\n    }\n    int best_idx = min_element(dp_prev, dp_prev + sz_prev) - dp_prev;\n    for (int k = L - 1; k >= 0; --k) {\n        path_out[k] = step_cells[k][best_idx];\n        best_idx = step_prev[k][best_idx];\n    }\n}\n\nint main() {\n    auto start_time = chrono::steady_clock::now();\n    const double time_limit = 1.95;\n\n    cin >> N >> M;\n    cin >> start_i >> start_j;\n    for (int i = 0; i < N; ++i) {\n        string line;\n        cin >> line;\n        for (int j = 0; j < N; ++j) grid[i][j] = line[j];\n    }\n    t.resize(M);\n    for (int i = 0; i < M; ++i) cin >> t[i];\n\n    // precomputation\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            int idx = i * N + j;\n            pos[grid[i][j] - 'A'].push_back(idx);\n        }\n    start_idx = start_i * N + start_j;\n    for (int i = 0; i < 225; ++i) {\n        int xi = i / N, yi = i % N;\n        int* drow = dist[i];\n        for (int j = 0; j < 225; ++j) {\n            int xj = j / N, yj = j % N;\n            drow[j] = abs(xi - xj) + abs(yi - yj);\n        }\n    }\n\n    unordered_map<string, int> word_to_idx;\n    for (int i = 0; i < M; ++i) word_to_idx[t[i]] = i;\n\n    vector<vector<int>> ov(M, vector<int>(M, 0));\n    for (int i = 0; i < M; ++i)\n        for (int j = 0; j < M; ++j)\n            for (int k = 1; k <= 5; ++k)\n                if (t[i].substr(5 - k) == t[j].substr(0, k))\n                    ov[i][j] = k;\n\n    Xorshift rnd;\n\n    vector<pair<int, vector<int>>> candidates;\n    int best_len = INF;\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > time_limit * 0.6) break;\n\n        vector<bool> used(M, false);\n        vector<bool> present(M, false);\n        vector<int> perm;\n        string S;\n        int last = -1;\n        int used_cnt = 0;\n\n        while (used_cnt < M) {\n            vector<int> skips;\n            for (int i = 0; i < M; ++i)\n                if (!used[i] && present[i]) skips.push_back(i);\n            if (!skips.empty()) {\n                int pick = skips[rnd.nextInt(skips.size())];\n                used[pick] = true;\n                perm.push_back(pick);\n                used_cnt++;\n                continue;\n            }\n            int best_ov = -1;\n            vector<int> best_candidates;\n            for (int i = 0; i < M; ++i) {\n                if (used[i]) continue;\n                int cur_ov = (last == -1) ? 0 : ov[last][i];\n                if (cur_ov > best_ov) {\n                    best_ov = cur_ov;\n                    best_candidates.clear();\n                    best_candidates.push_back(i);\n                } else if (cur_ov == best_ov) {\n                    best_candidates.push_back(i);\n                }\n            }\n            int pick = best_candidates[rnd.nextInt(best_candidates.size())];\n            used[pick] = true;\n            perm.push_back(pick);\n            int old_len = S.size();\n            if (last == -1)\n                S = t[pick];\n            else\n                S += t[pick].substr(best_ov);\n            last = pick;\n            int new_len = S.size();\n            for (int start = max(0, old_len - 4); start <= new_len - 5; ++start) {\n                string sub = S.substr(start, 5);\n                auto it = word_to_idx.find(sub);\n                if (it != word_to_idx.end()) present[it->second] = true;\n            }\n            used_cnt++;\n        }\n        int len = S.size();\n        if (len <= best_len || candidates.size() < 50) {\n            candidates.push_back({len, perm});\n            sort(candidates.begin(), candidates.end());\n            if (candidates.size() > 50) candidates.pop_back();\n            best_len = candidates[0].first;\n        }\n    }\n\n    int best_total_cost = INF;\n    vector<int> best_path;\n    for (auto& p : candidates) {\n        string S;\n        vector<bool> present(M, false);\n        S.clear();\n        int last = -1;\n        for (int idx : p.second) {\n            if (present[idx]) continue;\n            int old_len = S.size();\n            int best_ov = (last == -1) ? 0 : ov[last][idx];\n            if (last == -1)\n                S = t[idx];\n            else\n                S += t[idx].substr(best_ov);\n            last = idx;\n            int new_len = S.size();\n            for (int start = max(0, old_len - 4); start <= new_len - 5; ++start) {\n                string sub = S.substr(start, 5);\n                auto it = word_to_idx.find(sub);\n                if (it != word_to_idx.end()) present[it->second] = true;\n            }\n        }\n        int cost = compute_DP_cost(S);\n        if (cost < best_total_cost) {\n            best_total_cost = cost;\n            compute_DP_path(S, best_path);\n        }\n    }\n\n    for (int cell : best_path) {\n        int i = cell / N, j = cell % N;\n        cout << i << \" \" << j << \"\\n\";\n    }\n\n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <bitset>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\nconstexpr int MAX_N2 = 400;   // 20*20 = 400\nconstexpr double INF = 1e100;\n\ndouble normal_cdf(double x) {\n    return 0.5 * erfc(-x / sqrt(2.0));\n}\n\nint N, M;\ndouble eps;\nint V_total;\n\nstruct Placement {\n    bitset<MAX_N2> cells;\n    vector<int> q_overlap;   // size Q, contribution to each query\n    vector<char> d_contrib;  // dynamic, size D, 1 if placement covers the drilled cell\n};\n\nstruct FieldInfo {\n    vector<Placement> placements;\n    vector<int> valid;       // indices of placements currently valid\n};\nvector<FieldInfo> fields;\n\n// queries\nint Q = 0;\nvector<bitset<MAX_N2>> query_sets;\nvector<int> query_results;\nvector<vector<double>> log_prob;  // Q x (V_total+1)\n\n// drills\nint D = 0;\nvector<int> drill_cells;\nvector<int> observed;\n\n// Random engine\nmt19937 gen(chrono::steady_clock::now().time_since_epoch().count());\n\ninline int idx(int i, int j) { return i * N + j; }\ninline pair<int,int> unidx(int id) { return {id / N, id % N}; }\n\nvoid read_input() {\n    cin >> N >> M >> eps;\n    fields.resize(M);\n    V_total = 0;\n    for (int k = 0; k < M; ++k) {\n        int d; cin >> d;\n        fields[k].placements.reserve( (N-0)*(N-0) ); // upper bound\n        vector<pair<int,int>> shape(d);\n        for (int a = 0; a < d; ++a) {\n            cin >> shape[a].first >> shape[a].second;\n        }\n        int max_i = 0, max_j = 0;\n        for (auto &p : shape) {\n            max_i = max(max_i, p.first);\n            max_j = max(max_j, p.second);\n        }\n        for (int dx = 0; dx <= N - 1 - max_i; ++dx) {\n            for (int dy = 0; dy <= N - 1 - max_j; ++dy) {\n                Placement pl;\n                bitset<MAX_N2> b;\n                for (auto &p : shape) {\n                    int r = dx + p.first;\n                    int c = dy + p.second;\n                    b.set(idx(r, c));\n                }\n                pl.cells = b;\n                fields[k].placements.push_back(pl);\n            }\n        }\n        V_total += d;\n        // initially all placements are valid\n        fields[k].valid.resize(fields[k].placements.size());\n        iota(fields[k].valid.begin(), fields[k].valid.end(), 0);\n    }\n}\n\nvoid generate_initial_queries(int num_queries) {\n    Q = num_queries;\n    if (Q > 2 * N * N - 10) Q = max(0, 2 * N * N - 10);\n    query_sets.resize(Q);\n    query_results.resize(Q);\n    \n    uniform_int_distribution<int> k_dist(max(2, N*N/2), N*N);\n    vector<int> indices(N*N);\n    iota(indices.begin(), indices.end(), 0);\n    \n    for (int i = 0; i < Q; ++i) {\n        int k = k_dist(gen);\n        shuffle(indices.begin(), indices.end(), gen);\n        bitset<MAX_N2> s;\n        for (int t = 0; t < k; ++t) s.set(indices[t]);\n        query_sets[i] = s;\n        \n        // output query\n        cout << \"q \" << k;\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                if (s.test(idx(r, c))) cout << \" \" << r << \" \" << c;\n            }\n        }\n        cout << \"\\n\" << flush;\n    }\n    \n    for (int i = 0; i < Q; ++i) {\n        cin >> query_results[i];\n    }\n}\n\nvoid precompute_log_prob() {\n    log_prob.resize(Q, vector<double>(V_total + 1));\n    for (int i = 0; i < Q; ++i) {\n        int k = (int)query_sets[i].count();\n        int y = query_results[i];\n        double sigma = sqrt(k * eps * (1.0 - eps));\n        for (int v = 0; v <= V_total; ++v) {\n            double mu = k * eps + v * (1.0 - 2.0 * eps);\n            double prob;\n            if (y == 0) {\n                prob = normal_cdf((0.5 - mu) / sigma);\n            } else {\n                prob = normal_cdf((y + 0.5 - mu) / sigma) - normal_cdf((y - 0.5 - mu) / sigma);\n            }\n            if (prob <= 0.0) prob = 1e-300;\n            log_prob[i][v] = log(prob);\n        }\n    }\n}\n\nvoid precompute_overlaps() {\n    for (int k = 0; k < M; ++k) {\n        for (auto &pl : fields[k].placements) {\n            pl.q_overlap.resize(Q);\n            for (int i = 0; i < Q; ++i) {\n                pl.q_overlap[i] = (pl.cells & query_sets[i]).count();\n            }\n        }\n    }\n}\n\n// ----------------------------------------------------------------------\n// Simulated Annealing\n\nstruct SAState {\n    vector<int> assign;        // absolute placement index for each field\n    vector<int> qover;         // sum of overlaps for each query\n    vector<int> dcnt;          // drill counts (matched exactly)\n    double energy;\n};\n\nSAState create_random_state() {\n    SAState st;\n    st.assign.resize(M);\n    for (int k = 0; k < M; ++k) {\n        const auto &valid = fields[k].valid;\n        uniform_int_distribution<int> dis(0, valid.size() - 1);\n        st.assign[k] = valid[dis(gen)];\n    }\n    st.qover.assign(Q, 0);\n    st.dcnt.assign(D, 0);\n    for (int k = 0; k < M; ++k) {\n        int p = st.assign[k];\n        const auto &pl = fields[k].placements[p];\n        for (int i = 0; i < Q; ++i) st.qover[i] += pl.q_overlap[i];\n        for (int d = 0; d < D; ++d) st.dcnt[d] += pl.d_contrib[d];\n    }\n    st.energy = 0;\n    for (int i = 0; i < Q; ++i) {\n        st.energy += log_prob[i][st.qover[i]];\n    }\n    return st;\n}\n\nSAState run_sa(int moves) {\n    SAState state = create_random_state();\n    vector<int> assign = state.assign;\n    vector<int> qover = state.qover;\n    vector<int> dcnt = state.dcnt;\n    double energy = state.energy;\n\n    double best_energy = energy;\n    vector<int> best_assign = assign;\n\n    uniform_real_distribution<double> real_dis(0.0, 1.0);\n    uniform_int_distribution<int> field_dis(0, M - 1);\n\n    double T_start = 10.0, T_end = 0.01;\n    for (int step = 0; step < moves; ++step) {\n        double frac = (double)step / moves;\n        double T = T_start * pow(T_end / T_start, frac);\n        int k = field_dis(gen);\n        const auto &valid = fields[k].valid;\n        if (valid.size() <= 1) continue;\n        int old_p = assign[k];\n        int idx_new = uniform_int_distribution<int>(0, valid.size() - 1)(gen);\n        int new_p = valid[idx_new];\n        if (new_p == old_p) continue;\n\n        const auto &old_pl = fields[k].placements[old_p];\n        const auto &new_pl = fields[k].placements[new_p];\n\n        // hard drill constraints\n        bool ok = true;\n        for (int d = 0; d < D; ++d) {\n            int new_cnt = dcnt[d] - old_pl.d_contrib[d] + new_pl.d_contrib[d];\n            if (new_cnt != observed[d]) { ok = false; break; }\n        }\n        if (!ok) continue;\n\n        // compute new energy\n        double new_energy = energy;\n        for (int i = 0; i < Q; ++i) {\n            int old_val = qover[i];\n            int new_val = old_val - old_pl.q_overlap[i] + new_pl.q_overlap[i];\n            new_energy += log_prob[i][new_val] - log_prob[i][old_val];\n        }\n\n        if (new_energy >= energy || real_dis(gen) < exp((new_energy - energy) / T)) {\n            assign[k] = new_p;\n            energy = new_energy;\n            for (int i = 0; i < Q; ++i) {\n                qover[i] = qover[i] - old_pl.q_overlap[i] + new_pl.q_overlap[i];\n            }\n            for (int d = 0; d < D; ++d) {\n                dcnt[d] = dcnt[d] - old_pl.d_contrib[d] + new_pl.d_contrib[d];\n            }\n            if (energy > best_energy) {\n                best_energy = energy;\n                best_assign = assign;\n            }\n        }\n    }\n\n    SAState result;\n    result.assign = best_assign;\n    result.qover.assign(Q, 0);\n    result.dcnt.assign(D, 0);\n    for (int k = 0; k < M; ++k) {\n        int p = best_assign[k];\n        const auto &pl = fields[k].placements[p];\n        for (int i = 0; i < Q; ++i) result.qover[i] += pl.q_overlap[i];\n        for (int d = 0; d < D; ++d) result.dcnt[d] += pl.d_contrib[d];\n    }\n    result.energy = 0;\n    for (int i = 0; i < Q; ++i) result.energy += log_prob[i][result.qover[i]];\n    return result;\n}\n\nbitset<MAX_N2> get_mask(const vector<int> &assign) {\n    bitset<MAX_N2> mask;\n    for (int k = 0; k < M; ++k) {\n        mask |= fields[k].placements[assign[k]].cells;\n    }\n    return mask;\n}\n\n// ----------------------------------------------------------------------\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cout << fixed << setprecision(10);\n\n    read_input();\n    int max_ops = 2 * N * N;\n    int ops_used = 0;\n\n    // Phase 1: a few cheap large queries\n    int Q_planned = 50;\n    if (Q_planned > max_ops - 5) Q_planned = max(0, max_ops - 5);\n    generate_initial_queries(Q_planned);\n    ops_used += Q;\n    \n    precompute_log_prob();\n    precompute_overlaps();\n\n    // Phase 2: run SA to quickly guess\n    SAState best;\n    double best_energy = -INF;\n    // run 3 independent SA runs and keep the best\n    for (int r = 0; r < 3; ++r) {\n        SAState st = run_sa(20000);   // 20k moves each\n        if (st.energy > best_energy) {\n            best_energy = st.energy;\n            best = st;\n        }\n    }\n\n    // Guess based on best state\n    bitset<MAX_N2> guess_mask = get_mask(best.assign);\n    vector<pair<int,int>> guess_cells;\n    for (int r = 0; r < N; ++r)\n        for (int c = 0; c < N; ++c)\n            if (guess_mask.test(idx(r, c)))\n                guess_cells.emplace_back(r, c);\n    \n    cout << \"a \" << guess_cells.size();\n    for (auto &p : guess_cells) cout << \" \" << p.first << \" \" << p.second;\n    cout << \"\\n\" << flush;\n    ++ops_used;\n\n    int answer_result;\n    cin >> answer_result;\n    if (answer_result == 1) return 0;\n\n    // Phase 3: guess was wrong \u2014 fallback to full drill\n    // We drill every cell not yet drilled (currently none) and record v>0.\n    vector<pair<int,int>> positive;\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            if (ops_used >= max_ops - 1) break; // need one op for final guess\n            cout << \"q 1 \" << r << \" \" << c << \"\\n\" << flush;\n            ++ops_used;\n            int v;\n            cin >> v;\n            if (v > 0) positive.emplace_back(r, c);\n        }\n    }\n\n    // Final guess with exactly the true positive cells\n    cout << \"a \" << positive.size();\n    for (auto &p : positive) cout << \" \" << p.first << \" \" << p.second;\n    cout << \"\\n\" << flush;\n    // Expect 1\n    cin >> answer_result;\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int i0, j0, i1, j1;\n    int area() const { return (i1 - i0) * (j1 - j0); }\n};\n\nint W, D, N;\nvector<vector<int>> a;\nvector<vector<Rect>> rects;\nint HORIZ_COUNT, VERT_COUNT, SEG;\nvector<uint8_t> wall_counts;\nint total_area_penalty = 0;\nint total_L_sum = 0;\n\n// xorshift random\nunsigned int rng_state = 123456789;\nunsigned int xorshift() {\n    rng_state ^= rng_state << 13;\n    rng_state ^= rng_state >> 17;\n    rng_state ^= rng_state << 5;\n    return rng_state;\n}\ndouble rand_double() {\n    return (xorshift() & 0xFFFFFFFF) / 4294967296.0;\n}\nint rand_int(int n) {\n    return xorshift() % n;\n}\n\nbool overlap(const Rect& a, const Rect& b) {\n    return a.i0 < b.i1 && b.i0 < a.i1 && a.j0 < b.j1 && b.j0 < a.j1;\n}\n\nvoid get_boundaries(const Rect& r, vector<int>& segs) {\n    segs.clear();\n    if (r.i0 >= 1 && r.i0 <= W - 1) {\n        int base = (r.i0 - 1) * W + r.j0;\n        for (int j = 0; j < r.j1 - r.j0; ++j) segs.push_back(base + j);\n    }\n    if (r.i1 >= 1 && r.i1 <= W - 1) {\n        int base = (r.i1 - 1) * W + r.j0;\n        for (int j = 0; j < r.j1 - r.j0; ++j) segs.push_back(base + j);\n    }\n    if (r.j0 >= 1 && r.j0 <= W - 1) {\n        int base = HORIZ_COUNT + (r.j0 - 1);\n        for (int i = r.i0; i < r.i1; ++i) segs.push_back(base + i * (W - 1));\n    }\n    if (r.j1 >= 1 && r.j1 <= W - 1) {\n        int base = HORIZ_COUNT + (r.j1 - 1);\n        for (int i = r.i0; i < r.i1; ++i) segs.push_back(base + i * (W - 1));\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> W >> D >> N;\n    a.resize(D, vector<int>(N));\n    for (int d = 0; d < D; ++d)\n        for (int k = 0; k < N; ++k)\n            cin >> a[d][k];\n\n    HORIZ_COUNT = (W - 1) * W;\n    VERT_COUNT = W * (W - 1);\n    SEG = HORIZ_COUNT + VERT_COUNT;\n\n    rects.resize(D, vector<Rect>(N));\n\n    // ----- initial packing per day (maxrects best\u2011fit) -----\n    for (int d = 0; d < D; ++d) {\n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int x, int y) {\n            return a[d][x] > a[d][y];\n        });\n\n        struct FreeRect { int i0, j0, i1, j1; };\n        vector<FreeRect> free;\n        free.push_back({0, 0, W, W});\n        vector<Rect> placed(N);\n        bool ok = true;\n\n        for (int idx : order) {\n            int req = a[d][idx];\n\n            // best\u2011fit free rectangle\n            int best = -1;\n            int best_area = INT_MAX;\n            for (int i = 0; i < (int)free.size(); ++i) {\n                int fa = (free[i].i1 - free[i].i0) * (free[i].j1 - free[i].j0);\n                if (fa >= req && fa < best_area) {\n                    best_area = fa;\n                    best = i;\n                }\n            }\n            if (best == -1) {\n                // fallback : take first that fits (should not happen)\n                for (int i = 0; i < (int)free.size(); ++i) {\n                    int fa = (free[i].i1 - free[i].i0) * (free[i].j1 - free[i].j0);\n                    if (fa >= req) { best = i; break; }\n                }\n            }\n            if (best == -1) { ok = false; break; }\n\n            FreeRect fr = free[best];\n            free.erase(free.begin() + best);\n\n            int avail_w = fr.j1 - fr.j0;\n            int avail_h = fr.i1 - fr.i0;\n            int w = min(avail_w, max(1, (int)ceil(sqrt(req))));\n            int h = (req + w - 1) / w;\n            if (h > avail_h) {\n                h = avail_h;\n                w = (req + h - 1) / h;\n                if (w > avail_w) w = avail_w;\n            }\n            Rect r;\n            r.i0 = fr.i0; r.j0 = fr.j0;\n            r.i1 = r.i0 + h; r.j1 = r.j0 + w;\n\n            if (r.j1 < fr.j1) free.push_back({fr.i0, r.j1, r.i1, fr.j1});\n            if (r.i1 < fr.i1) free.push_back({r.i1, fr.j0, fr.i1, fr.j1});\n\n            placed[idx] = r;\n        }\n\n        if (!ok) {\n            // fallback : simple row strip packing (height = 1)\n            free.clear();\n            free.push_back({0, 0, W, W});\n            for (int idx : order) {\n                int req = a[d][idx];\n                int best = -1;\n                for (int i = 0; i < (int)free.size(); ++i) {\n                    if ((free[i].i1 - free[i].i0) * (free[i].j1 - free[i].j0) >= req) {\n                        best = i; break;\n                    }\n                }\n                FreeRect fr = free[best];\n                free.erase(free.begin() + best);\n                int w = min(fr.j1 - fr.j0, req);\n                int h = (req + w - 1) / w;\n                if (h > fr.i1 - fr.i0) h = fr.i1 - fr.i0;\n                Rect r;\n                r.i0 = fr.i0; r.j0 = fr.j0;\n                r.i1 = fr.i0 + h; r.j1 = fr.j0 + w;\n                if (r.j1 < fr.j1) free.push_back({fr.i0, r.j1, r.i1, fr.j1});\n                if (r.i1 < fr.i1) free.push_back({r.i1, fr.j0, fr.i1, fr.j1});\n                placed[idx] = r;\n            }\n        }\n        rects[d] = placed;\n    }\n\n    // ----- build wall_counts and initial cost -----\n    wall_counts.assign(D * SEG, 0);\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            vector<int> segs;\n            get_boundaries(rects[d][k], segs);\n            for (int s : segs) wall_counts[d * SEG + s]++;\n        }\n    }\n\n    total_area_penalty = 0;\n    for (int d = 0; d < D; ++d)\n        for (int k = 0; k < N; ++k) {\n            int area = rects[d][k].area();\n            if (area < a[d][k]) total_area_penalty += 100 * (a[d][k] - area);\n        }\n\n    total_L_sum = 0;\n    for (int d = 1; d < D; ++d) {\n        int off_prev = (d - 1) * SEG;\n        int off_cur = d * SEG;\n        for (int s = 0; s < SEG; ++s) {\n            total_L_sum += ((wall_counts[off_prev + s] > 0) != (wall_counts[off_cur + s] > 0));\n        }\n    }\n\n    int best_cost = total_area_penalty + total_L_sum;\n    vector<vector<Rect>> best_rects = rects;\n\n    // ----- SA -----\n    double T0 = 10000.0;\n    double time_limit = 2.9;\n    auto start_time = chrono::steady_clock::now();\n\n    vector<int> old_segs, new_segs;\n    old_segs.reserve(4000);\n    new_segs.reserve(4000);\n    vector<int> only_old, only_new;\n    only_old.reserve(4000);\n    only_new.reserve(4000);\n\n    while (true) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n        if (elapsed > time_limit) break;\n        double T = T0 * (1.0 - elapsed / time_limit);\n        if (T < 0.1) T = 0.1;\n\n        for (int sub = 0; sub < 200; ++sub) {\n            int d = rand_int(D);\n            int k = rand_int(N);\n            int move_type = rand_int(3);\n            Rect old_rect = rects[d][k];\n            Rect new_rect;\n\n            if (move_type == 0) {   // shift\n                int dx = rand_int(7) - 3;\n                int dy = rand_int(7) - 3;\n                if (dx == 0 && dy == 0) continue;\n                new_rect = {old_rect.i0 + dx, old_rect.j0 + dy, old_rect.i1 + dx, old_rect.j1 + dy};\n            } else if (move_type == 1) {  // resize\n                int side = rand_int(4);\n                int delta = rand_int(11) - 5;\n                if (delta == 0) continue;\n                new_rect = old_rect;\n                if (side == 0) new_rect.i0 += delta;\n                else if (side == 1) new_rect.i1 += delta;\n                else if (side == 2) new_rect.j0 += delta;\n                else new_rect.j1 += delta;\n            } else {  // copy from adjacent day\n                int adj = d + (rand_int(2) == 0 ? -1 : 1);\n                if (adj < 0 || adj >= D) continue;\n                new_rect = rects[adj][k];\n            }\n\n            // fast validity checks\n            if (new_rect.i0 < 0 || new_rect.j0 < 0 || new_rect.i1 > W || new_rect.j1 > W) continue;\n            if (new_rect.i0 >= new_rect.i1 || new_rect.j0 >= new_rect.j1) continue;\n            bool bad = false;\n            for (int k2 = 0; k2 < N; ++k2) {\n                if (k2 == k) continue;\n                if (overlap(new_rect, rects[d][k2])) { bad = true; break; }\n            }\n            if (bad) continue;\n\n            // area penalty change\n            int old_area = old_rect.area();\n            int new_area = new_rect.area();\n            int old_short = max(0, a[d][k] - old_area);\n            int new_short = max(0, a[d][k] - new_area);\n            int delta_area = 100 * (new_short - old_short);\n\n            // boundary segments (old / new)\n            get_boundaries(old_rect, old_segs);\n            get_boundaries(new_rect, new_segs);\n            sort(old_segs.begin(), old_segs.end());\n            sort(new_segs.begin(), new_segs.end());\n\n            only_old.clear(); only_new.clear();\n            size_t i = 0, j = 0;\n            while (i < old_segs.size() || j < new_segs.size()) {\n                if (i < old_segs.size() && (j == new_segs.size() || old_segs[i] < new_segs[j])) {\n                    only_old.push_back(old_segs[i]); ++i;\n                } else if (j < new_segs.size() && (i == old_segs.size() || new_segs[j] < old_segs[i])) {\n                    only_new.push_back(new_segs[j]); ++j;\n                } else {\n                    ++i; ++j;\n                }\n            }\n\n            int delta_L = 0;\n            int off_d = d * SEG;\n\n            for (int seg : only_old) {\n                int wc = wall_counts[off_d + seg];\n                bool old_st = (wc > 0);\n                bool new_st = ((wc - 1) > 0);\n                if (old_st != new_st) {\n                    if (d > 0) {\n                        bool prev_st = (wall_counts[(d - 1) * SEG + seg] > 0);\n                        delta_L += (new_st != prev_st) - (old_st != prev_st);\n                    }\n                    if (d + 1 < D) {\n                        bool next_st = (wall_counts[(d + 1) * SEG + seg] > 0);\n                        delta_L += (new_st != next_st) - (old_st != next_st);\n                    }\n                }\n            }\n            for (int seg : only_new) {\n                int wc = wall_counts[off_d + seg];\n                bool old_st = (wc > 0);\n                bool new_st = ((wc + 1) > 0);\n                if (old_st != new_st) {\n                    if (d > 0) {\n                        bool prev_st = (wall_counts[(d - 1) * SEG + seg] > 0);\n                        delta_L += (new_st != prev_st) - (old_st != prev_st);\n                    }\n                    if (d + 1 < D) {\n                        bool next_st = (wall_counts[(d + 1) * SEG + seg] > 0);\n                        delta_L += (new_st != next_st) - (old_st != next_st);\n                    }\n                }\n            }\n\n            int delta_cost = delta_area + delta_L;\n            if (delta_cost <= 0 || rand_double() < exp(-delta_cost / T)) {\n                // accept\n                rects[d][k] = new_rect;\n                total_area_penalty += delta_area;\n                total_L_sum += delta_L;\n                for (int seg : only_old) wall_counts[off_d + seg]--;\n                for (int seg : only_new) wall_counts[off_d + seg]++;\n            }\n        }\n\n        int cur_cost = total_area_penalty + total_L_sum;\n        if (cur_cost < best_cost) {\n            best_cost = cur_cost;\n            best_rects = rects;\n        }\n    }\n\n    // ----- output best solution -----\n    for (int d = 0; d < D; ++d)\n        for (int k = 0; k < N; ++k) {\n            Rect r = best_rects[d][k];\n            cout << r.i0 << \" \" << r.j0 << \" \" << r.i1 << \" \" << r.j1 << \"\\n\";\n        }\n\n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <array>\n#include <chrono>\n#include <random>\n#include <cmath>\n#include <algorithm>\n#include <climits>\n\nusing namespace std;\nusing ll = long long;\nusing ull = unsigned long long;\n\nconst int MOD = 998244353;\n\nstruct Move {\n    int m, p, q;\n    int cells[9];\n    int vals[9];\n};\n\nstruct XorShift {\n    ull s;\n    XorShift(ull seed) : s(seed) {}\n    ull next() {\n        s ^= s << 13;\n        s ^= s >> 7;\n        s ^= s << 17;\n        return s;\n    }\n    int next_int(int mod) {\n        return next() % mod;\n    }\n    double next_double() {\n        return (next() >> 11) * (1.0 / (1ULL << 53));\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K;\n    cin >> N >> M >> K;\n\n    // initial board and sum\n    int init_board[81];\n    ll init_sum = 0;\n    for (int i = 0; i < N * N; ++i) {\n        cin >> init_board[i];\n        init_sum += init_board[i];\n    }\n\n    // read stamps\n    vector<vector<vector<int>>> stamps(M, vector<vector<int>>(3, vector<int>(3)));\n    for (int m = 0; m < M; ++m)\n        for (int i = 0; i < 3; ++i)\n            for (int j = 0; j < 3; ++j)\n                cin >> stamps[m][i][j];\n\n    // precompute all valid moves\n    int rows = N - 2; // = 7\n    int cols = N - 2;\n    int total_moves = M * rows * cols; // 20 * 49 = 980\n    vector<Move> moves(total_moves);\n    for (int m = 0; m < M; ++m) {\n        for (int p = 0; p < rows; ++p) {\n            for (int q = 0; q < cols; ++q) {\n                int idx = m * rows * cols + p * cols + q;\n                moves[idx].m = m;\n                moves[idx].p = p;\n                moves[idx].q = q;\n                int ci = 0;\n                for (int i = 0; i < 3; ++i) {\n                    for (int j = 0; j < 3; ++j) {\n                        moves[idx].cells[ci] = (p + i) * N + (q + j);\n                        moves[idx].vals[ci] = stamps[m][i][j];\n                        ++ci;\n                    }\n                }\n            }\n        }\n    }\n\n    // Lambdas for board updates (capture by reference local board and score)\n    // We'll write a stateful class or pass arrays as parameters. For speed, we'll embed in episode.\n\n    // global best\n    vector<int> global_best_applied;\n    ll global_best_score = 0;\n\n    auto global_start = chrono::steady_clock::now();\n    double time_limit = 1.95;\n    // random seed for episodes\n    random_device rd;\n    ull base_seed = (((ull)rd()) << 32) | rd();\n\n    int episode_count = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - global_start).count();\n        if (elapsed > time_limit) break;\n\n        // setup episode rng\n        XorShift rng(base_seed + episode_count * 1234567ULL);\n        episode_count++;\n\n        // copy initial board and score\n        int board[81];\n        ll score = init_sum;\n        for (int i = 0; i < N * N; ++i) board[i] = init_board[i];\n\n        // define lambdas for this episode\n        auto eval_add = [&](int move_id) -> ll {\n            const Move& mv = moves[move_id];\n            ll d = 0;\n            for (int i = 0; i < 9; ++i) {\n                int c = mv.cells[i];\n                int v = mv.vals[i];\n                int old = board[c];\n                int nv = old + v;\n                if (nv >= MOD) nv -= MOD;\n                d += nv - old;\n            }\n            return d;\n        };\n        auto eval_remove = [&](int move_id) -> ll {\n            const Move& mv = moves[move_id];\n            ll d = 0;\n            for (int i = 0; i < 9; ++i) {\n                int c = mv.cells[i];\n                int v = mv.vals[i];\n                int old = board[c];\n                int nv = old - v;\n                if (nv < 0) nv += MOD;\n                d += nv - old;\n            }\n            return d;\n        };\n        auto apply_add = [&](int move_id) {\n            const Move& mv = moves[move_id];\n            for (int i = 0; i < 9; ++i) {\n                int c = mv.cells[i];\n                int v = mv.vals[i];\n                int old = board[c];\n                int nv = old + v;\n                if (nv >= MOD) nv -= MOD;\n                board[c] = nv;\n                score += nv - old;\n            }\n        };\n        auto apply_remove = [&](int move_id) {\n            const Move& mv = moves[move_id];\n            for (int i = 0; i < 9; ++i) {\n                int c = mv.cells[i];\n                int v = mv.vals[i];\n                int old = board[c];\n                int nv = old - v;\n                if (nv < 0) nv += MOD;\n                board[c] = nv;\n                score += nv - old;\n            }\n        };\n\n        // ---- Randomised greedy initialization ----\n        vector<int> applied;\n        double greediness = 0.8 + rng.next_double() * 0.2; // 0.8 .. 1.0\n        while ((int)applied.size() < K) {\n            // compute all deltas\n            vector<ll> deltas(total_moves);\n            ll best_delta = 0;\n            for (int m = 0; m < total_moves; ++m) {\n                ll d = eval_add(m);\n                deltas[m] = d;\n                if (d > best_delta) best_delta = d;\n            }\n            if (best_delta <= 0) break;\n            ll threshold = (ll)(best_delta * greediness);\n            vector<int> candidates;\n            for (int m = 0; m < total_moves; ++m) {\n                if (deltas[m] >= threshold) candidates.push_back(m);\n            }\n            // should not be empty\n            int pick = candidates[rng.next_int(candidates.size())];\n            apply_add(pick);\n            applied.push_back(pick);\n        }\n\n        // quick hill-climbing polish to improve starting point\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            int L = applied.size();\n            // try add\n            if (L < K) {\n                int best_move = -1;\n                ll best_delta = 0;\n                for (int m = 0; m < total_moves; ++m) {\n                    ll d = eval_add(m);\n                    if (d > best_delta) { best_delta = d; best_move = m; }\n                }\n                if (best_delta > 0) {\n                    apply_add(best_move);\n                    applied.push_back(best_move);\n                    improved = true;\n                    continue;\n                }\n            }\n            // try remove\n            if (L > 0) {\n                int best_idx = -1;\n                ll best_delta = 0;\n                for (int i = 0; i < L; ++i) {\n                    ll d = eval_remove(applied[i]);\n                    if (d > best_delta) { best_delta = d; best_idx = i; }\n                }\n                if (best_delta > 0) {\n                    apply_remove(applied[best_idx]);\n                    applied[best_idx] = applied.back();\n                    applied.pop_back();\n                    improved = true;\n                    continue;\n                }\n            }\n            // try replace\n            if (L > 0) {\n                bool found = false;\n                for (int i = 0; i < L && !found; ++i) {\n                    int old_move = applied[i];\n                    ll score_before = score;\n                    apply_remove(old_move);\n                    int best_new = -1;\n                    ll best_total = 0;\n                    for (int nm = 0; nm < total_moves; ++nm) {\n                        ll delta_add = eval_add(nm);\n                        ll total_delta = (score - score_before) + delta_add;\n                        if (total_delta > best_total) { best_total = total_delta; best_new = nm; }\n                    }\n                    if (best_total > 0) {\n                        apply_add(best_new);\n                        applied[i] = best_new;\n                        improved = true;\n                        found = true;\n                    } else {\n                        // revert\n                        apply_add(old_move);\n                    }\n                }\n                if (found) continue;\n            }\n        }\n\n        // save best after initial\n        vector<int> episode_best_applied = applied;\n        ll episode_best_score = score;\n\n        // ---- Simulated Annealing ----\n        double sa_time_limit = 0.5; // each episode gets at most 0.5s, but global check dominates\n        auto sa_start = chrono::steady_clock::now();\n        double T_start = 1e9;\n        double T_end = 1e0;\n        double log_ratio = log(T_end / T_start);\n        int iter = 0;\n        while (true) {\n            if ((iter & 255) == 0) {\n                auto now2 = chrono::steady_clock::now();\n                double elapsed2 = chrono::duration<double>(now2 - global_start).count();\n                if (elapsed2 > time_limit) break;\n                double progress = chrono::duration<double>(now2 - sa_start).count() / sa_time_limit;\n                if (progress > 1.0) break;\n                // temperature\n                double T = T_start * exp(progress * log_ratio);\n                if (T < T_end) T = T_end;\n                // store for use below\n                // (we will compute T later when needed)\n            }\n            // current temperature\n            double progress = chrono::duration<double>(chrono::steady_clock::now() - sa_start).count() / sa_time_limit;\n            if (progress > 1.0) break;\n            double T = T_start * exp(progress * log_ratio);\n            if (T < T_end) T = T_end;\n\n            int L = applied.size();\n            double r = rng.next_double();\n            if (L == 0) {\n                // can only add\n                int nm = rng.next_int(total_moves);\n                ll delta = eval_add(nm);\n                if (delta >= 0 || rng.next_double() < exp(delta / T)) {\n                    apply_add(nm);\n                    applied.push_back(nm);\n                    if (score > episode_best_score) {\n                        episode_best_score = score;\n                        episode_best_applied = applied;\n                    }\n                }\n            } else if (L == K) {\n                // cannot add\n                if (r < 0.5) {\n                    // remove\n                    int idx = rng.next_int(L);\n                    int old_move = applied[idx];\n                    ll delta = eval_remove(old_move);\n                    if (delta >= 0 || rng.next_double() < exp(delta / T)) {\n                        apply_remove(old_move);\n                        applied[idx] = applied.back();\n                        applied.pop_back();\n                        if (score > episode_best_score) {\n                            episode_best_score = score;\n                            episode_best_applied = applied;\n                        }\n                    }\n                } else {\n                    // replace\n                    int idx = rng.next_int(L);\n                    int old_move = applied[idx];\n                    ll score_before = score;\n                    apply_remove(old_move);\n                    int new_move = rng.next_int(total_moves);\n                    ll delta_add = eval_add(new_move);\n                    ll total_delta = (score - score_before) + delta_add;\n                    if (total_delta >= 0 || rng.next_double() < exp(total_delta / T)) {\n                        apply_add(new_move);\n                        applied[idx] = new_move;\n                        if (score > episode_best_score) {\n                            episode_best_score = score;\n                            episode_best_applied = applied;\n                        }\n                    } else {\n                        apply_add(old_move);\n                    }\n                }\n            } else {\n                // 0 < L < K\n                if (r < 0.25) {\n                    // add\n                    int nm = rng.next_int(total_moves);\n                    ll delta = eval_add(nm);\n                    if (delta >= 0 || rng.next_double() < exp(delta / T)) {\n                        apply_add(nm);\n                        applied.push_back(nm);\n                        if (score > episode_best_score) {\n                            episode_best_score = score;\n                            episode_best_applied = applied;\n                        }\n                    }\n                } else if (r < 0.50) {\n                    // remove\n                    int idx = rng.next_int(L);\n                    int old_move = applied[idx];\n                    ll delta = eval_remove(old_move);\n                    if (delta >= 0 || rng.next_double() < exp(delta / T)) {\n                        apply_remove(old_move);\n                        applied[idx] = applied.back();\n                        applied.pop_back();\n                        if (score > episode_best_score) {\n                            episode_best_score = score;\n                            episode_best_applied = applied;\n                        }\n                    }\n                } else if (r < 0.75) {\n                    // replace (random)\n                    int idx = rng.next_int(L);\n                    int old_move = applied[idx];\n                    ll score_before = score;\n                    apply_remove(old_move);\n                    int new_move = rng.next_int(total_moves);\n                    ll delta_add = eval_add(new_move);\n                    ll total_delta = (score - score_before) + delta_add;\n                    if (total_delta >= 0 || rng.next_double() < exp(total_delta / T)) {\n                        apply_add(new_move);\n                        applied[idx] = new_move;\n                        if (score > episode_best_score) {\n                            episode_best_score = score;\n                            episode_best_applied = applied;\n                        }\n                    } else {\n                        apply_add(old_move);\n                    }\n                } else {\n                    // shift / mutate\n                    int idx = rng.next_int(L);\n                    int old_id = applied[idx];\n                    const Move& old_mv = moves[old_id];\n                    int new_id = -1;\n                    // decide operation\n                    int op = rng.next_int(2);\n                    if (op == 0) { // change stamp\n                        int new_m = rng.next_int(M);\n                        if (new_m == old_mv.m) new_m = (new_m + 1) % M;\n                        new_id = new_m * rows * cols + old_mv.p * cols + old_mv.q;\n                    } else { // shift position\n                        int new_p = old_mv.p, new_q = old_mv.q;\n                        if (rng.next_int(2) == 0) { // shift row\n                            int d = rng.next_int(3) - 1; // -1,0,1\n                            new_p = old_mv.p + d;\n                            if (new_p < 0 || new_p >= rows) new_p = old_mv.p;\n                        } else { // shift col\n                            int d = rng.next_int(3) - 1;\n                            new_q = old_mv.q + d;\n                            if (new_q < 0 || new_q >= cols) new_q = old_mv.q;\n                        }\n                        if (new_p == old_mv.p && new_q == old_mv.q) {\n                            // fallback: change stamp\n                            int new_m = rng.next_int(M);\n                            if (new_m == old_mv.m) new_m = (new_m + 1) % M;\n                            new_id = new_m * rows * cols + old_mv.p * cols + old_mv.q;\n                        } else {\n                            new_id = old_mv.m * rows * cols + new_p * cols + new_q;\n                        }\n                    }\n                    // evaluate total change\n                    ll score_before = score;\n                    apply_remove(old_id);\n                    ll delta_add = eval_add(new_id);\n                    ll total_delta = (score - score_before) + delta_add;\n                    if (total_delta >= 0 || rng.next_double() < exp(total_delta / T)) {\n                        apply_add(new_id);\n                        applied[idx] = new_id;\n                        if (score > episode_best_score) {\n                            episode_best_score = score;\n                            episode_best_applied = applied;\n                        }\n                    } else {\n                        apply_add(old_id);\n                    }\n                }\n            }\n            ++iter;\n        }\n\n        // ---- final polishing ----\n        // Restore best state of this episode\n        applied = episode_best_applied;\n        score = init_sum;\n        for (int i = 0; i < N * N; ++i) board[i] = init_board[i];\n        for (int mid : applied) apply_add(mid);\n\n        // hill climbing again\n        improved = true;\n        while (improved) {\n            improved = false;\n            int L = applied.size();\n            // try add\n            if (L < K) {\n                int best_move = -1;\n                ll best_delta = 0;\n                for (int m = 0; m < total_moves; ++m) {\n                    ll d = eval_add(m);\n                    if (d > best_delta) { best_delta = d; best_move = m; }\n                }\n                if (best_delta > 0) {\n                    apply_add(best_move);\n                    applied.push_back(best_move);\n                    improved = true;\n                    if (score > episode_best_score) {\n                        episode_best_score = score;\n                        episode_best_applied = applied;\n                    }\n                    continue;\n                }\n            }\n            // try remove\n            if (L > 0) {\n                int best_idx = -1;\n                ll best_delta = 0;\n                for (int i = 0; i < L; ++i) {\n                    ll d = eval_remove(applied[i]);\n                    if (d > best_delta) { best_delta = d; best_idx = i; }\n                }\n                if (best_delta > 0) {\n                    apply_remove(applied[best_idx]);\n                    applied[best_idx] = applied.back();\n                    applied.pop_back();\n                    improved = true;\n                    if (score > episode_best_score) {\n                        episode_best_score = score;\n                        episode_best_applied = applied;\n                    }\n                    continue;\n                }\n            }\n            // try replace\n            if (L > 0) {\n                bool found = false;\n                for (int i = 0; i < L && !found; ++i) {\n                    int old_move = applied[i];\n                    ll score_before = score;\n                    apply_remove(old_move);\n                    int best_new = -1;\n                    ll best_total = 0;\n                    for (int nm = 0; nm < total_moves; ++nm) {\n                        ll delta_add = eval_add(nm);\n                        ll total_delta = (score - score_before) + delta_add;\n                        if (total_delta > best_total) { best_total = total_delta; best_new = nm; }\n                    }\n                    if (best_total > 0) {\n                        apply_add(best_new);\n                        applied[i] = best_new;\n                        improved = true;\n                        found = true;\n                        if (score > episode_best_score) {\n                            episode_best_score = score;\n                            episode_best_applied = applied;\n                        }\n                    } else {\n                        apply_add(old_move);\n                    }\n                }\n                if (found) continue;\n            }\n        }\n\n        // update global best\n        if (episode_best_score > global_best_score) {\n            global_best_score = episode_best_score;\n            global_best_applied = episode_best_applied;\n        }\n    }\n\n    // output global best\n    cout << global_best_applied.size() << \"\\n\";\n    for (int mid : global_best_applied) {\n        cout << moves[mid].m << \" \" << moves[mid].p << \" \" << moves[mid].q << \"\\n\";\n    }\n\n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <tuple>\n#include <queue>\nusing namespace std;\n\nint main() {\n    const int N = 5;\n    vector<vector<int>> A(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> A[i][j];\n\n    vector<int> id_to_row(N * N);\n    vector<int> arrival_order[N];\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            id_to_row[A[i][j]] = i;\n            arrival_order[i].push_back(A[i][j]);\n        }\n    }\n\n    int arrival_idx[N] = {0};\n    int ground[N][N];\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            ground[i][j] = -1;\n\n    int container_pos[25];\n    for (int i = 0; i < 25; ++i) container_pos[i] = -1;  // -1: not on ground, -2: dispatched\n\n    int L_r = 0, L_c = 0;\n    int L_holding = -1;\n    int cur_target = 0;\n    string L_actions;\n    int turn = 0;\n\n    auto move_towards = [&](int tr, int tc) -> char {\n        if (L_r < tr) return 'D';\n        if (L_r > tr) return 'U';\n        if (L_c < tc) return 'R';\n        if (L_c > tc) return 'L';\n        return '.';\n    };\n\n    auto find_buffer_cell = [&](int cont) -> pair<int,int> {\n        int tr = cont / 5;\n        // 1) current cell if it is empty and not a dispatch gate\n        if (ground[L_r][L_c] == -1) {\n            if (L_c != 4 && !(L_c == 0 && arrival_idx[L_r] < N)) {\n                return {L_r, L_c};\n            }\n        }\n        // 2) target row, preferred columns 3,2,1\n        for (int c : {3, 2, 1}) {\n            if (ground[tr][c] == -1) return {tr, c};\n        }\n        if (arrival_idx[tr] >= N && ground[tr][0] == -1) return {tr, 0};\n        // 3) other rows\n        for (int r = 0; r < N; ++r) {\n            if (r == tr) continue;\n            for (int c : {3, 2, 1}) {\n                if (ground[r][c] == -1) return {r, c};\n            }\n            if (arrival_idx[r] >= N && ground[r][0] == -1) return {r, 0};\n        }\n        // 4) any other cell except dispatch gates (col 4) and receiving gates that still have pending containers\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c <= 3; ++c) {\n                if (ground[r][c] == -1) {\n                    if (c == 0 && arrival_idx[r] < N) continue;\n                    return {r, c};\n                }\n            }\n        }\n        // absolute fallback (should never be reached)\n        return {L_r, L_c};\n    };\n\n    while (cur_target < 25 && turn < 10000) {\n        // ---------- Step 1 : Receiving ----------\n        for (int i = 0; i < N; ++i) {\n            if (ground[i][0] == -1 && arrival_idx[i] < N) {\n                // arrival is blocked only if a crane holding a container is present\n                bool blocked = (L_holding != -1 && L_r == i && L_c == 0);\n                if (!blocked) {\n                    int cont = arrival_order[i][arrival_idx[i]++];\n                    ground[i][0] = cont;\n                    container_pos[cont] = i * 5 + 0;\n                }\n            }\n        }\n\n        // ---------- Step 2 : Large crane action ----------\n        char act = '.';\n        if (L_holding != -1) {\n            int cont = L_holding;\n            if (cont == cur_target) {\n                int tr = cont / 5;\n                int tc = 4;\n                if (L_r == tr && L_c == tc) {\n                    act = 'Q';\n                } else {\n                    act = move_towards(tr, tc);\n                }\n            } else {\n                auto [tr, tc] = find_buffer_cell(cont);\n                if (L_r == tr && L_c == tc) {\n                    act = 'Q';\n                } else {\n                    act = move_towards(tr, tc);\n                }\n            }\n        } else {\n            int c = cur_target;\n            int r = id_to_row[c];\n            if (container_pos[c] >= 0) {\n                int pos = container_pos[c];\n                int tr = pos / 5, tc = pos % 5;\n                if (L_r == tr && L_c == tc) {\n                    act = 'P';\n                } else {\n                    act = move_towards(tr, tc);\n                }\n            } else {\n                // not on ground\n                if (ground[r][0] == c) {\n                    if (L_r == r && L_c == 0) {\n                        act = 'P';\n                    } else {\n                        act = move_towards(r, 0);\n                    }\n                } else if (ground[r][0] != -1) {\n                    // gate blocked by another container\n                    if (L_r == r && L_c == 0) {\n                        act = 'P';\n                    } else {\n                        act = move_towards(r, 0);\n                    }\n                } else {\n                    // wait near the gate\n                    int tr = r, tc = 1;\n                    if (L_r == tr && L_c == tc) {\n                        act = '.';\n                    } else {\n                        act = move_towards(tr, tc);\n                    }\n                }\n            }\n        }\n\n        // Apply L action\n        if (act == 'U') L_r--;\n        else if (act == 'D') L_r++;\n        else if (act == 'L') L_c--;\n        else if (act == 'R') L_c++;\n        else if (act == 'P') {\n            int cont = ground[L_r][L_c];\n            ground[L_r][L_c] = -1;\n            L_holding = cont;\n            container_pos[cont] = -1;\n        } else if (act == 'Q') {\n            ground[L_r][L_c] = L_holding;\n            container_pos[L_holding] = L_r * 5 + L_c;\n            L_holding = -1;\n        }\n        L_actions.push_back(act);\n\n        // ---------- Step 3 : Dispatching ----------\n        for (int i = 0; i < N; ++i) {\n            if (ground[i][4] != -1) {\n                int cont = ground[i][4];\n                ground[i][4] = -1;\n                container_pos[cont] = -2;\n                if (cont == cur_target) {\n                    ++cur_target;\n                }\n            }\n        }\n\n        ++turn;\n    }\n\n    // Output\n    cout << L_actions << \"\\n\";\n    for (int i = 1; i < N; ++i) {\n        cout << \"B\\n\";\n    }\n\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Task {\n    int r, c, h;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N; // N = 20\n    vector<vector<int>> H(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> H[i][j];\n        }\n    }\n\n    // Collect non-zero cells as tasks\n    vector<Task> tasks;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (H[i][j] != 0) {\n                tasks.push_back({i, j, H[i][j]});\n            }\n        }\n    }\n    int S = tasks.size();\n    if (S == 0) {\n        // All zero, no operations\n        return 0;\n    }\n\n    // Manhattan distance\n    auto manhattan = [&](int r1, int c1, int r2, int c2) {\n        return abs(r1 - r2) + abs(c1 - c2);\n    };\n\n    // Precompute distances\n    vector<int> start_dist(S);\n    for (int i = 0; i < S; ++i) {\n        start_dist[i] = manhattan(0, 0, tasks[i].r, tasks[i].c);\n    }\n    vector<vector<int>> dist(S, vector<int>(S));\n    for (int i = 0; i < S; ++i) {\n        for (int j = 0; j < S; ++j) {\n            dist[i][j] = manhattan(tasks[i].r, tasks[i].c, tasks[j].r, tasks[j].c);\n        }\n    }\n\n    // Evaluate a permutation (movement cost only, infeasible if load < 0 at any point)\n    auto evaluate = [&](const vector<int>& perm) -> pair<long long, bool> {\n        long long cost = 0;\n        int load = 0;\n        int pos = -1; // -1 means (0,0)\n        for (int idx : perm) {\n            int d = (pos == -1) ? start_dist[idx] : dist[pos][idx];\n            cost += d * (100LL + load);\n            load += tasks[idx].h;\n            if (load < 0) return {0, false};\n            pos = idx;\n        }\n        // load should be 0 at the end because sum of h = 0, but we don't strictly check\n        return {cost, true};\n    };\n\n    // Build initial solution: all positives first, then negatives\n    vector<int> pos_idx, neg_idx;\n    for (int i = 0; i < S; ++i) {\n        if (tasks[i].h > 0) pos_idx.push_back(i);\n        else neg_idx.push_back(i);\n    }\n\n    // Greedy construction for positives (nearest neighbor from (0,0))\n    auto build_greedy_positives = [&]() {\n        vector<int> order;\n        vector<bool> used(S, false);\n        int cur_r = 0, cur_c = 0;\n        while ((int)order.size() < (int)pos_idx.size()) {\n            int best = -1;\n            int best_d = 1e9;\n            for (int i : pos_idx) {\n                if (used[i]) continue;\n                int d = manhattan(cur_r, cur_c, tasks[i].r, tasks[i].c);\n                if (d < best_d) {\n                    best_d = d;\n                    best = i;\n                }\n            }\n            order.push_back(best);\n            used[best] = true;\n            cur_r = tasks[best].r;\n            cur_c = tasks[best].c;\n        }\n        return order;\n    };\n\n    // Greedy construction for negatives (nearest neighbor from last positive)\n    auto build_greedy_negatives = [&](int start_r, int start_c) {\n        vector<int> order;\n        vector<bool> used(S, false);\n        // mark positives as used (they are already in the positive order, but we just need to pick negatives)\n        // simpler: just pass used negatives\n        int cur_r = start_r, cur_c = start_c;\n        while ((int)order.size() < (int)neg_idx.size()) {\n            int best = -1;\n            int best_d = 1e9;\n            for (int i : neg_idx) {\n                // we don't have a global used here; we just pick from neg_idx each time\n                // Use a local bool array or just ensure we don't pick already chosen\n                // We'll use a vector<bool> local_used(neg_idx.size(), false) manually.\n                // But easier: just iterate over neg_idx and skip already in order.\n                if (find(order.begin(), order.end(), i) != order.end()) continue;\n                int d = manhattan(cur_r, cur_c, tasks[i].r, tasks[i].c);\n                if (d < best_d) {\n                    best_d = d;\n                    best = i;\n                }\n            }\n            order.push_back(best);\n            cur_r = tasks[best].r;\n            cur_c = tasks[best].c;\n        }\n        return order;\n    };\n\n    int last_pos_r = 0, last_pos_c = 0;\n    vector<int> best_perm;\n    if (!pos_idx.empty()) {\n        vector<int> pos_order = build_greedy_positives();\n        last_pos_r = tasks[pos_order.back()].r;\n        last_pos_c = tasks[pos_order.back()].c;\n        vector<int> neg_order = build_greedy_negatives(last_pos_r, last_pos_c);\n        best_perm = pos_order;\n        best_perm.insert(best_perm.end(), neg_order.begin(), neg_order.end());\n    } else {\n        // All negatives? Should not happen with sum=0 and non-zero tasks, but just in case.\n        // Start from (0,0) with load 0, cannot unload, so put negatives first would be infeasible.\n        // Actually if all negatives, sum != 0, so impossible.\n        // We'll leave best_perm empty; program will likely fail but won't happen.\n    }\n\n    auto [best_cost, feasible] = evaluate(best_perm);\n    // If the greedy result is infeasible (shouldn't be), fallback to simple all positives first by sorting.\n    if (!feasible) {\n        // Just concatenate positives then negatives in arbitrary order\n        best_perm = pos_idx;\n        best_perm.insert(best_perm.end(), neg_idx.begin(), neg_idx.end());\n        auto res = evaluate(best_perm);\n        best_cost = res.first;\n    }\n\n    // Try a few random shuffles of positives and negatives separately to improve initial solution\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto rand_int = [&](int lo, int hi) {\n        return uniform_int_distribution<int>(lo, hi)(rng);\n    };\n    auto shuffle_vec = [&](vector<int>& v) {\n        shuffle(v.begin(), v.end(), rng);\n    };\n\n    int initial_trials = 50;\n    for (int t = 0; t < initial_trials; ++t) {\n        vector<int> pos = pos_idx, neg = neg_idx;\n        shuffle_vec(pos);\n        shuffle_vec(neg);\n        vector<int> cand = pos;\n        cand.insert(cand.end(), neg.begin(), neg.end());\n        auto [cst, ok] = evaluate(cand);\n        if (ok && cst < best_cost) {\n            best_cost = cst;\n            best_perm = move(cand);\n        }\n    }\n\n    // SA parameters\n    auto start_time = chrono::steady_clock::now();\n    double T = 1000000.0;\n    double T_min = 0.1;\n    double alpha = 0.9999;\n    int iter = 0;\n    vector<int> cur_perm = best_perm;\n    long long cur_cost = best_cost;\n\n    uniform_real_distribution<double> rand_double(0.0, 1.0);\n\n    while (true) {\n        int move_type = rand_int(0, 2); // 0:swap, 1:reverse, 2:insert\n        bool improved = false;\n        if (move_type == 0) { // swap\n            int i = rand_int(0, S - 1);\n            int j = rand_int(0, S - 1);\n            if (i == j) continue;\n            swap(cur_perm[i], cur_perm[j]);\n            auto [new_cost, feas] = evaluate(cur_perm);\n            if (feas && (new_cost < cur_cost || rand_double(rng) < exp((cur_cost - new_cost) / T))) {\n                cur_cost = new_cost;\n                improved = true;\n            } else {\n                swap(cur_perm[i], cur_perm[j]); // revert\n            }\n        } else if (move_type == 1) { // reverse\n            if (S < 2) continue;\n            int i = rand_int(0, S - 2);\n            int j = rand_int(i + 1, S - 1);\n            reverse(cur_perm.begin() + i, cur_perm.begin() + j + 1);\n            auto [new_cost, feas] = evaluate(cur_perm);\n            if (feas && (new_cost < cur_cost || rand_double(rng) < exp((cur_cost - new_cost) / T))) {\n                cur_cost = new_cost;\n                improved = true;\n            } else {\n                reverse(cur_perm.begin() + i, cur_perm.begin() + j + 1); // revert\n            }\n        } else { // insert\n            int i = rand_int(0, S - 1);\n            int j = rand_int(0, S - 1);\n            if (i == j) continue;\n            vector<int> new_perm = cur_perm;\n            int val = new_perm[i];\n            new_perm.erase(new_perm.begin() + i);\n            new_perm.insert(new_perm.begin() + j, val);\n            auto [new_cost, feas] = evaluate(new_perm);\n            if (feas && (new_cost < cur_cost || rand_double(rng) < exp((cur_cost - new_cost) / T))) {\n                cur_perm = move(new_perm);\n                cur_cost = new_cost;\n                improved = true;\n            }\n        }\n\n        if (improved && cur_cost < best_cost) {\n            best_cost = cur_cost;\n            best_perm = cur_perm;\n        }\n\n        T *= alpha;\n        if (T < T_min) T = T_min;\n        ++iter;\n        if (iter % 1000 == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > 1.9) break;\n        }\n    }\n\n    // Final hill-climbing (T=0)\n    for (int rep = 0; rep < 5000; ++rep) {\n        int move_type = rand_int(0, 2);\n        if (move_type == 0) {\n            int i = rand_int(0, S - 1), j = rand_int(0, S - 1);\n            if (i == j) continue;\n            swap(cur_perm[i], cur_perm[j]);\n            auto [new_cost, feas] = evaluate(cur_perm);\n            if (feas && new_cost < cur_cost) {\n                cur_cost = new_cost;\n                if (cur_cost < best_cost) {\n                    best_cost = cur_cost;\n                    best_perm = cur_perm;\n                }\n            } else {\n                swap(cur_perm[i], cur_perm[j]);\n            }\n        } else if (move_type == 1) {\n            if (S < 2) continue;\n            int i = rand_int(0, S - 2), j = rand_int(i + 1, S - 1);\n            reverse(cur_perm.begin() + i, cur_perm.begin() + j + 1);\n            auto [new_cost, feas] = evaluate(cur_perm);\n            if (feas && new_cost < cur_cost) {\n                cur_cost = new_cost;\n                if (cur_cost < best_cost) {\n                    best_cost = cur_cost;\n                    best_perm = cur_perm;\n                }\n            } else {\n                reverse(cur_perm.begin() + i, cur_perm.begin() + j + 1);\n            }\n        } else {\n            int i = rand_int(0, S - 1), j = rand_int(0, S - 1);\n            if (i == j) continue;\n            vector<int> new_perm = cur_perm;\n            int val = new_perm[i];\n            new_perm.erase(new_perm.begin() + i);\n            new_perm.insert(new_perm.begin() + j, val);\n            auto [new_cost, feas] = evaluate(new_perm);\n            if (feas && new_cost < cur_cost) {\n                cur_perm = move(new_perm);\n                cur_cost = new_cost;\n                if (cur_cost < best_cost) {\n                    best_cost = cur_cost;\n                    best_perm = cur_perm;\n                }\n            }\n        }\n    }\n\n    // Generate output\n    vector<string> ops;\n    int cur_r = 0, cur_c = 0;\n    for (int idx : best_perm) {\n        int tr = tasks[idx].r, tc = tasks[idx].c;\n        while (cur_r < tr) { ops.push_back(\"D\"); cur_r++; }\n        while (cur_r > tr) { ops.push_back(\"U\"); cur_r--; }\n        while (cur_c < tc) { ops.push_back(\"R\"); cur_c++; }\n        while (cur_c > tc) { ops.push_back(\"L\"); cur_c--; }\n        if (tasks[idx].h > 0) {\n            ops.push_back(\"+\" + to_string(tasks[idx].h));\n        } else {\n            ops.push_back(\"-\" + to_string(-tasks[idx].h));\n        }\n    }\n\n    for (auto& s : ops) cout << s << '\\n';\n\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <chrono>\n#include <cstdint>\n\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, T;\n    cin >> N >> M >> T;\n    const int seed_count = 2 * N * (N - 1); // 60\n\n    vector<vector<int>> seeds(seed_count, vector<int>(M));\n    for (int i = 0; i < seed_count; ++i) {\n        for (int j = 0; j < M; ++j) {\n            cin >> seeds[i][j];\n        }\n    }\n\n    // initial global maximums\n    vector<int> global_max(M, 0);\n    for (int i = 0; i < seed_count; ++i) {\n        for (int j = 0; j < M; ++j) {\n            if (seeds[i][j] > global_max[j]) global_max[j] = seeds[i][j];\n        }\n    }\n\n    // random generator\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    // precompute edge list (as cell indices r*N+c)\n    vector<pair<int,int>> edges;\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            if (r + 1 < N) edges.push_back({r*N+c, (r+1)*N+c});\n            if (c + 1 < N) edges.push_back({r*N+c, r*N+c+1});\n        }\n    }\n\n    // cell degrees\n    vector<int> cell_deg(N*N);\n    for (int r=0; r<N; ++r) {\n        for (int c=0; c<N; ++c) {\n            int d = 0;\n            if (r > 0) d++;\n            if (r < N-1) d++;\n            if (c > 0) d++;\n            if (c < N-1) d++;\n            cell_deg[r*N+c] = d;\n        }\n    }\n\n    // order cells by degree descending\n    vector<int> cell_order(N*N);\n    iota(cell_order.begin(), cell_order.end(), 0);\n    sort(cell_order.begin(), cell_order.end(), [&](int a, int b) {\n        if (cell_deg[a] != cell_deg[b]) return cell_deg[a] > cell_deg[b];\n        return a < b;\n    });\n\n    for (int t = 0; t < T; ++t) {\n        // recompute current maximums\n        vector<int> cur_max(M, 0);\n        for (int i = 0; i < seed_count; ++i)\n            for (int j = 0; j < M; ++j)\n                if (seeds[i][j] > cur_max[j]) cur_max[j] = seeds[i][j];\n\n        // feature masks and scores\n        vector<uint16_t> mask(seed_count, 0);\n        vector<int> max_cnt(seed_count, 0);\n        vector<int> sum_val(seed_count, 0);\n        for (int i = 0; i < seed_count; ++i) {\n            uint16_t m = 0;\n            int cnt = 0;\n            for (int j = 0; j < M; ++j) {\n                if (seeds[i][j] == cur_max[j]) {\n                    m |= (1 << j);\n                    ++cnt;\n                }\n            }\n            mask[i] = m;\n            max_cnt[i] = cnt;\n            sum_val[i] = accumulate(seeds[i].begin(), seeds[i].end(), 0);\n        }\n\n        // select 36 seeds with greedy set cover for maximum features\n        vector<int> selected;\n        selected.reserve(36);\n        uint16_t uncovered = (1 << M) - 1;\n        vector<bool> used(seed_count, false);\n\n        // coverage phase\n        while (uncovered) {\n            int best_idx = -1;\n            int best_cover = -1;\n            int best_score = -1;\n            for (int i = 0; i < seed_count; ++i) {\n                if (used[i]) continue;\n                int cover = __builtin_popcount((unsigned int)(mask[i] & uncovered));\n                if (cover == 0) continue;\n                int score = max_cnt[i] * 1000 + sum_val[i];\n                if (cover > best_cover || (cover == best_cover && score > best_score)) {\n                    best_cover = cover;\n                    best_score = score;\n                    best_idx = i;\n                }\n            }\n            if (best_idx == -1) break; // should not happen\n            used[best_idx] = true;\n            selected.push_back(best_idx);\n            uncovered &= ~mask[best_idx];\n        }\n\n        // fill remaining with best score\n        vector<pair<int,int>> rest; // (score, idx)\n        for (int i = 0; i < seed_count; ++i) {\n            if (!used[i]) {\n                rest.push_back({max_cnt[i] * 1000 + sum_val[i], i});\n            }\n        }\n        sort(rest.begin(), rest.end(), greater<>());\n        for (auto &p : rest) {\n            if ((int)selected.size() >= 36) break;\n            selected.push_back(p.second);\n        }\n\n        // sort selected by score descending (for initial placement)\n        vector<pair<int,int>> ranked_sel;\n        for (int idx : selected) {\n            ranked_sel.push_back({max_cnt[idx] * 1000 + sum_val[idx], idx});\n        }\n        sort(ranked_sel.begin(), ranked_sel.end(), greater<>());\n        selected.clear();\n        for (auto &p : ranked_sel) selected.push_back(p.second);\n\n        // initial assignment: highest score to highest degree cells\n        int grid_seed[6][6];\n        for (int i = 0; i < N*N; ++i) {\n            int r = cell_order[i] / N;\n            int c = cell_order[i] % N;\n            grid_seed[r][c] = selected[i];\n        }\n\n        // score function for a pair of seeds\n        auto score2 = [&](int s1, int s2) -> int {\n            uint16_t m1 = mask[s1];\n            uint16_t m2 = mask[s2];\n            uint16_t both = m1 & m2;\n            uint16_t either = m1 ^ m2;\n            return 2 * __builtin_popcount((unsigned int)both) + __builtin_popcount((unsigned int)either);\n        };\n\n        auto total_score = [&]() -> int {\n            int total = 0;\n            for (auto &e : edges) {\n                int r1 = e.first / N, c1 = e.first % N;\n                int r2 = e.second / N, c2 = e.second % N;\n                total += score2(grid_seed[r1][c1], grid_seed[r2][c2]);\n            }\n            return total;\n        };\n\n        int cur_total = total_score();\n        uniform_int_distribution<int> cell_dist(0, N*N-1);\n\n        // hill climbing (greedy swaps)\n        const int MAX_ITER = 70000;\n        for (int it = 0; it < MAX_ITER; ++it) {\n            int c1 = cell_dist(rng);\n            int c2 = cell_dist(rng);\n            if (c1 == c2) continue;\n            int r1 = c1 / N, c1c = c1 % N;\n            int r2 = c2 / N, c2c = c2 % N;\n            swap(grid_seed[r1][c1c], grid_seed[r2][c2c]);\n            int new_total = total_score();\n            if (new_total > cur_total) {\n                cur_total = new_total;\n            } else {\n                swap(grid_seed[r1][c1c], grid_seed[r2][c2c]); // revert\n            }\n        }\n\n        // output grid\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                if (c) cout << ' ';\n                cout << grid_seed[r][c];\n            }\n            cout << '\\n';\n        }\n        cout.flush();\n\n        // read new seeds\n        for (int i = 0; i < seed_count; ++i) {\n            for (int j = 0; j < M; ++j) {\n                cin >> seeds[i][j];\n            }\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    int N, M, V;\n    cin >> N >> M >> V;\n    vector<string> s_str(N), t_str(N);\n    for (int i = 0; i < N; ++i) cin >> s_str[i];\n    for (int i = 0; i < N; ++i) cin >> t_str[i];\n    \n    vector<vector<bool>> s(N, vector<bool>(N, false));\n    vector<vector<bool>> t(N, vector<bool>(N, false));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (s_str[i][j] == '1') s[i][j] = true;\n            if (t_str[i][j] == '1') t[i][j] = true;\n        }\n    }\n    \n    // Design a star-shaped tree: root 0 with V-1 leaves\n    int Vp = V;\n    int C = Vp - 1;                   // number of leaves\n    vector<int> dirs(C), lens(C);\n    for (int i = 0; i < C; ++i) {\n        dirs[i] = i % 4;               // permanent direction: 0:right, 1:down, 2:left, 3:up\n        lens[i] = i + 1;               // different lengths\n    }\n    \n    // Output tree and initial root position\n    cout << Vp << \"\\n\";\n    for (int i = 0; i < C; ++i) {\n        cout << 0 << \" \" << lens[i] << \"\\n\";\n    }\n    cout << \"0 0\\n\";                   // root starts at (0,0)\n    \n    const int ddx[4] = {0, 1, 0, -1}; // row change per direction\n    const int ddy[4] = {1, 0, -1, 0}; // col change per direction\n    \n    vector<int> dx(C), dy(C);\n    for (int i = 0; i < C; ++i) {\n        dx[i] = ddx[dirs[i]] * lens[i];\n        dy[i] = ddy[dirs[i]] * lens[i];\n    }\n    \n    // Initial two turns to rotate leaves into their permanent directions\n    auto get_rot = [&](int leaf, int turn) -> char {\n        int target = dirs[leaf];\n        if (target == 0) return '.';\n        if (target == 1) return (turn == 0) ? 'R' : '.';\n        if (target == 2) return (turn == 0 || turn == 1) ? 'R' : '.';\n        if (target == 3) return (turn == 0) ? 'L' : '.';\n        return '.';\n    };\n    \n    string turn0(2 * Vp, '.'), turn1(2 * Vp, '.');\n    for (int i = 0; i < C; ++i) {\n        turn0[1 + i] = get_rot(i, 0);\n        turn1[1 + i] = get_rot(i, 1);\n    }\n    int turn_count = 2;\n    cout << turn0 << \"\\n\";\n    cout << turn1 << \"\\n\";\n    \n    vector<bool> occ(C, false);        // true if leaf i is holding a takoyaki\n    int rx = 0, ry = 0;                // current root position\n    \n    const int MAX_TURNS = 100000;\n    \n    // Output a single turn\n    auto do_turn = [&](char move_char, const string& rot_part, const string& act_part) {\n        string S(2 * Vp, '.');\n        S[0] = move_char;\n        for (int i = 0; i < C; ++i) S[1 + i] = rot_part[i];\n        for (int i = 0; i < Vp; ++i) S[Vp + i] = act_part[i];\n        cout << S << \"\\n\";\n        ++turn_count;\n    };\n    \n    // Compute possible actions at a given root position (initial state of the turn)\n    auto compute_actions = [&](int x, int y) -> string {\n        string act(Vp, '.');\n        for (int i = 0; i < C; ++i) {\n            int tx = x + dx[i];\n            int ty = y + dy[i];\n            if (tx < 0 || tx >= N || ty < 0 || ty >= N) continue;\n            if (!occ[i] && s[tx][ty] && !t[tx][ty]) {\n                act[i + 1] = 'P';\n            } else if (occ[i] && t[tx][ty] && !s[tx][ty]) {\n                act[i + 1] = 'P';\n            }\n        }\n        return act;\n    };\n    \n    // Apply actions sequentially (same order as the judge) and skip illegal ones\n    auto apply_actions = [&](int x, int y, const string& act) {\n        for (int i = 0; i < C; ++i) {\n            if (act[i + 1] != 'P') continue;\n            int tx = x + dx[i];\n            int ty = y + dy[i];\n            if (tx < 0 || tx >= N || ty < 0 || ty >= N) continue;\n            if (!occ[i] && s[tx][ty] && !t[tx][ty]) {\n                occ[i] = true;\n                s[tx][ty] = false;\n            } else if (occ[i] && t[tx][ty] && !s[tx][ty]) {\n                occ[i] = false;\n                s[tx][ty] = true;\n            }\n            // else action is invalid and will be ignored by the judge; we do nothing\n        }\n    };\n    \n    // Main loop\n    while (turn_count < MAX_TURNS) {\n        // Find best root position (maximise immediate actions, tie-break by distance)\n        int best_A = -1, best_x = -1, best_y = -1, min_dist = 1e9;\n        for (int nx = 0; nx < N; ++nx) {\n            for (int ny = 0; ny < N; ++ny) {\n                int A = 0;\n                for (int i = 0; i < C; ++i) {\n                    int tx = nx + dx[i];\n                    int ty = ny + dy[i];\n                    if (tx >= 0 && tx < N && ty >= 0 && ty < N) {\n                        if (!occ[i] && s[tx][ty] && !t[tx][ty]) ++A;\n                        else if (occ[i] && t[tx][ty] && !s[tx][ty]) ++A;\n                    }\n                }\n                if (A > best_A) {\n                    best_A = A;\n                    best_x = nx; best_y = ny;\n                    min_dist = abs(nx - rx) + abs(ny - ry);\n                } else if (A == best_A) {\n                    int d = abs(nx - rx) + abs(ny - ry);\n                    if (d < min_dist) {\n                        min_dist = d;\n                        best_x = nx; best_y = ny;\n                    }\n                }\n            }\n        }\n        if (best_A <= 0) break;   // no useful actions exist\n        \n        // Build a Manhattan path from current root to best root\n        vector<pair<int,int>> path;\n        int cur_x = rx, cur_y = ry;\n        while (cur_x != best_x) {\n            cur_x += (best_x > cur_x) ? 1 : -1;\n            path.emplace_back(cur_x, cur_y);\n        }\n        while (cur_y != best_y) {\n            cur_y += (best_y > cur_y) ? 1 : -1;\n            path.emplace_back(cur_x, cur_y);\n        }\n        \n        // If we are already at the best position, just perform the actions\n        if (path.empty()) {\n            string act_part = compute_actions(rx, ry);\n            if (turn_count < MAX_TURNS) {\n                do_turn('.', string(C, '.'), act_part);\n                apply_actions(rx, ry, act_part);\n            }\n            continue;\n        }\n        \n        // Execute the path step by step\n        cur_x = rx; cur_y = ry;\n        for (size_t k = 0; k < path.size(); ++k) {\n            if (turn_count >= MAX_TURNS) break;\n            int nx = path[k].first;\n            int ny = path[k].second;\n            char move_char = '.';\n            if (nx > cur_x) move_char = 'D';\n            else if (nx < cur_x) move_char = 'U';\n            else if (ny > cur_y) move_char = 'R';\n            else if (ny < cur_y) move_char = 'L';\n            \n            string rot_part(C, '.');\n            string act_part;\n            bool is_last = (k == path.size() - 1);\n            if (is_last) {\n                act_part = compute_actions(nx, ny);\n            } else {\n                act_part.assign(Vp, '.');\n            }\n            \n            do_turn(move_char, rot_part, act_part);\n            if (is_last) {\n                apply_actions(nx, ny, act_part);\n            }\n            cur_x = nx;\n            cur_y = ny;\n        }\n        rx = cur_x;\n        ry = cur_y;\n    }\n    \n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <unordered_map>\n#include <utility>\nusing namespace std;\n\nconst int S = 800;                     // cell size\nconst int W = 125;                     // grid width  (100000 / 800)\nconst int H = 125;                     // grid height\nconst int MAX_PERIMETER = 400000;\n\nstruct Edge {\n    int to, rev;\n    long long cap;\n};\n\nstruct Dinic {\n    int N;\n    vector<vector<Edge>> g;\n    vector<int> level, iter;\n\n    Dinic(int n) : N(n), g(n), level(n), iter(n) {}\n\n    void add_edge(int from, int to, long long cap) {\n        g[from].push_back({to, (int)g[to].size(), cap});\n        g[to].push_back({from, (int)g[from].size() - 1, 0});\n    }\n\n    void add_undirected(int u, int v, long long cap) {\n        add_edge(u, v, cap);\n        add_edge(v, u, cap);\n    }\n\n    bool bfs(int s, int t) {\n        fill(level.begin(), level.end(), -1);\n        queue<int> q;\n        level[s] = 0;\n        q.push(s);\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (auto &e : g[v]) {\n                if (e.cap > 0 && level[e.to] == -1) {\n                    level[e.to] = level[v] + 1;\n                    q.push(e.to);\n                }\n            }\n        }\n        return level[t] != -1;\n    }\n\n    long long dfs(int s, int t, long long f) {\n        vector<pair<int, long long>> st;\n        vector<int> prev(N, -1), prev_edge(N, -1);\n        st.push({s, f});\n        prev[s] = s;\n        while (!st.empty()) {\n            auto [v, flow] = st.top();\n            if (v == t) {\n                // augment\n                for (int u = t; u != s; u = prev[u]) {\n                    int ei = prev_edge[u];\n                    Edge &e = g[prev[u]][ei];\n                    e.cap -= flow;\n                    g[u][e.rev].cap += flow;\n                }\n                return flow;\n            }\n            bool found = false;\n            for (int &i = iter[v]; i < (int)g[v].size(); i++) {\n                Edge &e = g[v][i];\n                if (e.cap > 0 && level[v] + 1 == level[e.to]) {\n                    prev[e.to] = v;\n                    prev_edge[e.to] = i;\n                    st.push({e.to, min(flow, e.cap)});\n                    found = true;\n                    break;\n                }\n            }\n            if (!found) {\n                st.pop();\n            }\n        }\n        return 0;\n    }\n\n    long long max_flow(int s, int t) {\n        long long flow = 0;\n        while (bfs(s, t)) {\n            fill(iter.begin(), iter.end(), 0);\n            long long f;\n            while ((f = dfs(s, t, 1e18)) > 0) {\n                flow += f;\n            }\n        }\n        return flow;\n    }\n\n    vector<bool> get_source_set(int s) {\n        vector<bool> vis(N, false);\n        queue<int> q;\n        q.push(s);\n        vis[s] = true;\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (auto &e : g[v]) {\n                if (e.cap > 0 && !vis[e.to]) {\n                    vis[e.to] = true;\n                    q.push(e.to);\n                }\n            }\n        }\n        return vis;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    cin >> N;\n    vector<int> x(2*N), y(2*N);\n    for (int i = 0; i < 2*N; i++) cin >> x[i] >> y[i];\n    \n    // assign each point to a cell and compute cell weight (mackerels - sardines)\n    vector<vector<int>> weight(H, vector<int>(W, 0));\n    for (int i = 0; i < N; i++) {\n        int cx = min(x[i] / S, W - 1);\n        int cy = min(y[i] / S, H - 1);\n        weight[cy][cx]++;\n    }\n    for (int i = N; i < 2*N; i++) {\n        int cx = min(x[i] / S, W - 1);\n        int cy = min(y[i] / S, H - 1);\n        weight[cy][cx]--;\n    }\n    \n    // different trade-off parameters (lambda)\n    vector<int> lambdas = {0, 1, 3, 7, 15, 30, 60, 120, 250, 500};\n    \n    int best_score = -1;\n    vector<vector<bool>> best_inside(H, vector<bool>(W, false));\n    \n    const int dx[4] = {1, -1, 0, 0};\n    const int dy[4] = {0, 0, 1, -1};\n    \n    for (int lambda : lambdas) {\n        Dinic dinic(W * H + 2);\n        int source = W * H, sink = source + 1;\n        \n        // unary terms\n        for (int j = 0; j < H; j++) {\n            for (int i = 0; i < W; i++) {\n                int id = i + j * W;\n                int w = weight[j][i];\n                if (w > 0) dinic.add_edge(source, id, w);\n                else if (w < 0) dinic.add_edge(id, sink, -w);\n            }\n        }\n        \n        // pairwise terms (perimeter penalty)\n        for (int j = 0; j < H; j++) {\n            for (int i = 0; i < W; i++) {\n                int id = i + j * W;\n                if (i + 1 < W) dinic.add_undirected(id, id + 1, lambda);\n                if (j + 1 < H) dinic.add_undirected(id, id + W, lambda);\n            }\n        }\n        \n        dinic.max_flow(source, sink);\n        auto vis = dinic.get_source_set(source);\n        vector<vector<bool>> inside(H, vector<bool>(W, false));\n        for (int j = 0; j < H; j++)\n            for (int i = 0; i < W; i++)\n                inside[j][i] = vis[i + j * W];\n        \n        // find connected components of the inside set\n        vector<vector<int>> comp_id(H, vector<int>(W, -1));\n        int comp_cnt = 0;\n        for (int j = 0; j < H; j++) {\n            for (int i = 0; i < W; i++) {\n                if (inside[j][i] && comp_id[j][i] == -1) {\n                    queue<pair<int,int>> q;\n                    q.push({i, j});\n                    comp_id[j][i] = comp_cnt;\n                    while (!q.empty()) {\n                        auto [cx, cy] = q.front(); q.pop();\n                        for (int d = 0; d < 4; d++) {\n                            int nx = cx + dx[d], ny = cy + dy[d];\n                            if (nx >= 0 && nx < W && ny >= 0 && ny < H && inside[ny][nx] && comp_id[ny][nx] == -1) {\n                                comp_id[ny][nx] = comp_cnt;\n                                q.push({nx, ny});\n                            }\n                        }\n                    }\n                    comp_cnt++;\n                }\n            }\n        }\n        \n        // evaluate each component after filling holes\n        for (int c = 0; c < comp_cnt; c++) {\n            int min_i = W, max_i = -1, min_j = H, max_j = -1;\n            for (int j = 0; j < H; j++) {\n                for (int i = 0; i < W; i++) {\n                    if (comp_id[j][i] == c) {\n                        min_i = min(min_i, i); max_i = max(max_i, i);\n                        min_j = min(min_j, j); max_j = max(max_j, j);\n                    }\n                }\n            }\n            int lw = max_i - min_i + 3;\n            int lh = max_j - min_j + 3;\n            vector<vector<bool>> local(lh, vector<bool>(lw, false));\n            for (int j = min_j; j <= max_j; j++)\n                for (int i = min_i; i <= max_i; i++)\n                    if (comp_id[j][i] == c)\n                        local[j - min_j + 1][i - min_i + 1] = true;\n            \n            // flood fill the outside from the borders of the local grid\n            vector<vector<bool>> vis_local(lh, vector<bool>(lw, false));\n            queue<pair<int,int>> q;\n            for (int y = 0; y < lh; y++) {\n                if (!local[y][0]) { q.push({0, y}); vis_local[y][0] = true; }\n                if (!local[y][lw-1]) { q.push({lw-1, y}); vis_local[y][lw-1] = true; }\n            }\n            for (int x = 0; x < lw; x++) {\n                if (!local[0][x]) { q.push({x, 0}); vis_local[0][x] = true; }\n                if (!local[lh-1][x]) { q.push({x, lh-1}); vis_local[lh-1][x] = true; }\n            }\n            while (!q.empty()) {\n                auto [cx, cy] = q.front(); q.pop();\n                for (int d = 0; d < 4; d++) {\n                    int nx = cx + dx[d], ny = cy + dy[d];\n                    if (nx >= 0 && nx < lw && ny >= 0 && ny < lh && !vis_local[ny][nx] && !local[ny][nx]) {\n                        vis_local[ny][nx] = true;\n                        q.push({nx, ny});\n                    }\n                }\n            }\n            // fill holes (any outside cell not reached by the flood fill)\n            for (int y = 0; y < lh; y++)\n                for (int x = 0; x < lw; x++)\n                    if (!vis_local[y][x] && !local[y][x])\n                        local[y][x] = true;\n            \n            // test if a global cell belongs to the filled component\n            auto is_inside_local = [&](int i, int j) -> bool {\n                if (i < min_i || i > max_i || j < min_j || j > max_j) return false;\n                return local[j - min_j + 1][i - min_i + 1];\n            };\n            \n            long long cur_w = 0;\n            int cur_perim = 0;\n            for (int j = min_j; j <= max_j; j++) {\n                for (int i = min_i; i <= max_i; i++) {\n                    if (is_inside_local(i, j)) {\n                        cur_w += weight[j][i];\n                        if (!is_inside_local(i+1, j)) cur_perim++;\n                        if (!is_inside_local(i-1, j)) cur_perim++;\n                        if (!is_inside_local(i, j+1)) cur_perim++;\n                        if (!is_inside_local(i, j-1)) cur_perim++;\n                    }\n                }\n            }\n            \n            // check perimeter constraint\n            if ((long long)cur_perim * S <= MAX_PERIMETER) {\n                int score = max(0LL, cur_w + 1);\n                if (score > best_score) {\n                    best_score = score;\n                    best_inside.assign(H, vector<bool>(W, false));\n                    for (int j = min_j; j <= max_j; j++)\n                        for (int i = min_i; i <= max_i; i++)\n                            if (is_inside_local(i, j))\n                                best_inside[j][i] = true;\n                }\n            }\n        }\n    }\n    \n    // if no valid component found, fall back to a tiny polygon around a single mackerel\n    if (best_score <= 0) {\n        int best_px = x[0], best_py = y[0];\n        // try to find a mackerel whose 1x1 cell contains no sardine\n        for (int i = 0; i < N; i++) {\n            int px = x[i], py = y[i];\n            bool ok = true;\n            for (int j = N; j < 2*N; j++) {\n                if (x[j] >= px && x[j] <= px+1 && y[j] >= py && y[j] <= py+1) {\n                    ok = false;\n                    break;\n                }\n            }\n            if (ok) {\n                best_px = px; best_py = py;\n                break;\n            }\n        }\n        if (best_px == 100000) best_px = 99999;\n        if (best_py == 100000) best_py = 99999;\n        cout << \"4\\n\";\n        cout << best_px << \" \" << best_py << \"\\n\";\n        cout << best_px+1 << \" \" << best_py << \"\\n\";\n        cout << best_px+1 << \" \" << best_py+1 << \"\\n\";\n        cout << best_px << \" \" << best_py+1 << \"\\n\";\n        return 0;\n    }\n    \n    // trace the outer boundary of best_inside\n    struct Seg {\n        int x1, y1, x2, y2;\n    };\n    vector<Seg> segs;\n    for (int j = 0; j < H; j++) {\n        for (int i = 0; i < W; i++) {\n            if (!best_inside[j][i]) continue;\n            int x = i * S, y = j * S;\n            // top edge\n            if (j == 0 || !best_inside[j-1][i])\n                segs.push_back({x, y, x + S, y});\n            // bottom edge\n            if (j == H-1 || !best_inside[j+1][i])\n                segs.push_back({x, y + S, x + S, y + S});\n            // left edge\n            if (i == 0 || !best_inside[j][i-1])\n                segs.push_back({x, y, x, y + S});\n            // right edge\n            if (i == W-1 || !best_inside[j][i+1])\n                segs.push_back({x + S, y, x + S, y + S});\n        }\n    }\n    \n    // link segments via their endpoints\n    unordered_map<long long, vector<int>> vmap;\n    for (int idx = 0; idx < (int)segs.size(); idx++) {\n        long long k1 = (long long)segs[idx].x1 << 32 | segs[idx].y1;\n        long long k2 = (long long)segs[idx].x2 << 32 | segs[idx].y2;\n        vmap[k1].push_back(idx);\n        vmap[k2].push_back(idx);\n    }\n    \n    // trace the boundary loop\n    vector<pair<int,int>> poly;\n    int start_x = segs[0].x1, start_y = segs[0].y1;\n    poly.push_back({start_x, start_y});\n    int cur_x = segs[0].x2, cur_y = segs[0].y2;\n    poly.push_back({cur_x, cur_y});\n    int prev_seg = 0;\n    while (true) {\n        long long key = (long long)cur_x << 32 | cur_y;\n        int next_seg = -1;\n        for (int sid : vmap[key]) {\n            if (sid != prev_seg) {\n                next_seg = sid;\n                break;\n            }\n        }\n        if (next_seg == -1) break;  // should not happen\n        int nx, ny;\n        if (segs[next_seg].x1 == cur_x && segs[next_seg].y1 == cur_y) {\n            nx = segs[next_seg].x2;\n            ny = segs[next_seg].y2;\n        } else {\n            nx = segs[next_seg].x1;\n            ny = segs[next_seg].y1;\n        }\n        if (nx == start_x && ny == start_y) break;\n        poly.push_back({nx, ny});\n        cur_x = nx; cur_y = ny;\n        prev_seg = next_seg;\n    }\n    \n    // remove collinear vertices\n    vector<pair<int,int>> simple = poly;\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        for (size_t i = 0; i < simple.size(); i++) {\n            size_t prv = (i == 0) ? simple.size() - 1 : i - 1;\n            size_t nxt = (i + 1) % simple.size();\n            if (simple[prv].first == simple[i].first && simple[i].first == simple[nxt].first) {\n                simple.erase(simple.begin() + i);\n                changed = true;\n                break;\n            }\n            if (simple[prv].second == simple[i].second && simple[i].second == simple[nxt].second) {\n                simple.erase(simple.begin() + i);\n                changed = true;\n                break;\n            }\n        }\n    }\n    \n    // output\n    cout << simple.size() << \"\\n\";\n    for (auto [xx, yy] : simple)\n        cout << xx << \" \" << yy << \"\\n\";\n    \n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <string>\n#include <utility>\nusing namespace std;\n\nstruct PlacedRect {\n    int index;          // original index (0..N-1)\n    long long x, y;     // position\n    long long w, h;     // size after rotation\n    int rot;            // 0 or 1\n    char dir;           // 'U' or 'L'\n    int base;           // -1 or original index of reference\n};\n\nstruct State {\n    vector<PlacedRect> rects;\n    long long W, H;\n    long long sum_skipped;   // sum of (w+h) for skipped indices\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int N, T, sigma;\n    cin >> N >> T >> sigma;\n    vector<int> w_obs(N), h_obs(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> w_obs[i] >> h_obs[i];\n    }\n\n    // current estimates for true sizes (double for averaging)\n    vector<double> sum_w(N), sum_h(N);\n    vector<int> cnt(N);\n    for (int i = 0; i < N; ++i) {\n        sum_w[i] = w_obs[i];\n        sum_h[i] = h_obs[i];\n        cnt[i] = 1;\n    }\n\n    int turns_done = 0;\n\n    auto update_est = [&](int i, long long w_meas, long long h_meas) {\n        sum_w[i] += w_meas;\n        sum_h[i] += h_meas;\n        cnt[i]++;\n    };\n\n    // If enough turns, spend 2N turns to measure each rectangle twice.\n    if (T >= 2 * N + 10) {\n        for (int i = 0; i < N; ++i) {\n            // r = 0\n            cout << 1 << \"\\n\";\n            cout << i << \" 0 U -1\\n\" << flush;\n            long long Wp, Hp;\n            cin >> Wp >> Hp;\n            update_est(i, Wp, Hp);\n            ++turns_done;\n\n            // r = 1\n            cout << 1 << \"\\n\";\n            cout << i << \" 1 U -1\\n\" << flush;\n            cin >> Wp >> Hp;\n            update_est(i, Hp, Wp);  // swapped\n            ++turns_done;\n        }\n    }\n\n    // final integer estimates\n    vector<long long> ew(N), eh(N);\n    for (int i = 0; i < N; ++i) {\n        ew[i] = (long long)round(sum_w[i] / cnt[i]);\n        eh[i] = (long long)round(sum_h[i] / cnt[i]);\n    }\n\n    // suffix sums for the beam search heuristic\n    vector<long long> suffix_sum(N + 1, 0);\n    for (int i = N - 1; i >= 0; --i) suffix_sum[i] = suffix_sum[i + 1] + ew[i] + eh[i];\n\n    // Beam search for a good placement sequence\n    const int BEAM = 30;\n    vector<State> beam;\n    beam.push_back(State{ {}, 0LL, 0LL, 0LL });\n\n    for (int i = 0; i < N; ++i) {\n        vector<State> next_beams;\n        next_beams.reserve(BEAM * (5 + 4 * N)); // rough upper bound\n\n        for (const auto& s : beam) {\n            // option: skip rectangle i\n            {\n                State skip_s = s;\n                skip_s.sum_skipped += ew[i] + eh[i];\n                next_beams.push_back(move(skip_s));\n            }\n\n            long long w = ew[i];\n            long long h = eh[i];\n\n            for (int rot = 0; rot <= 1; ++rot) {\n                long long cur_w = rot ? h : w;\n                long long cur_h = rot ? w : h;\n\n                // U with base = -1\n                {\n                    long long x = 0, y = 0;\n                    for (const auto& pr : s.rects) {\n                        if (x + cur_w > pr.x && pr.x + pr.w > x)\n                            y = max(y, pr.y + pr.h);\n                    }\n                    State ns = s;\n                    ns.rects.push_back({i, x, y, cur_w, cur_h, rot, 'U', -1});\n                    ns.W = max(ns.W, x + cur_w);\n                    ns.H = max(ns.H, y + cur_h);\n                    next_beams.push_back(move(ns));\n                }\n\n                // L with base = -1\n                {\n                    long long y = 0, x = 0;\n                    for (const auto& pr : s.rects) {\n                        if (y + cur_h > pr.y && pr.y + pr.h > y)\n                            x = max(x, pr.x + pr.w);\n                    }\n                    State ns = s;\n                    ns.rects.push_back({i, x, y, cur_w, cur_h, rot, 'L', -1});\n                    ns.W = max(ns.W, x + cur_w);\n                    ns.H = max(ns.H, y + cur_h);\n                    next_beams.push_back(move(ns));\n                }\n\n                // attach to each already placed rectangle\n                for (const auto& pr : s.rects) {\n                    int base = pr.index;\n\n                    // U\n                    {\n                        long long x = pr.x + pr.w;\n                        long long y = 0;\n                        for (const auto& pr2 : s.rects) {\n                            if (x + cur_w > pr2.x && pr2.x + pr2.w > x)\n                                y = max(y, pr2.y + pr2.h);\n                        }\n                        State ns = s;\n                        ns.rects.push_back({i, x, y, cur_w, cur_h, rot, 'U', base});\n                        ns.W = max(ns.W, x + cur_w);\n                        ns.H = max(ns.H, y + cur_h);\n                        next_beams.push_back(move(ns));\n                    }\n\n                    // L\n                    {\n                        long long y = pr.y + pr.h;\n                        long long x = 0;\n                        for (const auto& pr2 : s.rects) {\n                            if (y + cur_h > pr2.y && pr2.y + pr2.h > y)\n                                x = max(x, pr2.x + pr2.w);\n                        }\n                        State ns = s;\n                        ns.rects.push_back({i, x, y, cur_w, cur_h, rot, 'L', base});\n                        ns.W = max(ns.W, x + cur_w);\n                        ns.H = max(ns.H, y + cur_h);\n                        next_beams.push_back(move(ns));\n                    }\n                }\n            }\n        }\n\n        // keep top BEAM states according to the heuristic\n        vector<pair<long long, int>> costs;\n        costs.reserve(next_beams.size());\n        for (int idx = 0; idx < (int)next_beams.size(); ++idx) {\n            const auto& ns = next_beams[idx];\n            long long cost = ns.W + ns.H + ns.sum_skipped + suffix_sum[i + 1];\n            costs.emplace_back(cost, idx);\n        }\n        sort(costs.begin(), costs.end());\n        beam.clear();\n        for (int j = 0; j < min(BEAM, (int)costs.size()); ++j)\n            beam.push_back(move(next_beams[costs[j].second]));\n    }\n\n    // select the absolute best state (final score = W+H+sum_skipped)\n    const State* best = &beam[0];\n    long long best_cost = best->W + best->H + best->sum_skipped;\n    for (const auto& s : beam) {\n        long long c = s.W + s.H + s.sum_skipped;\n        if (c < best_cost) {\n            best_cost = c;\n            best = &s;\n        }\n    }\n\n    int n = best->rects.size();\n    int rem = T - turns_done;\n    for (int t = 0; t < rem; ++t) {\n        cout << n << \"\\n\";\n        for (const auto& pr : best->rects)\n            cout << pr.index << \" \" << pr.rot << \" \" << pr.dir << \" \" << pr.base << \"\\n\";\n        cout << flush;\n        long long Wp, Hp;\n        cin >> Wp >> Hp;   // read and ignore the measurements\n    }\n\n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <stack>\n#include <ctime>\n#include <cmath>\n#include <cstdint>\n#include <random>\n\nusing namespace std;\n\n// fast random number generator\nuint32_t xor_state;\nvoid init_random() {\n    random_device rd;\n    xor_state = rd();\n    if(xor_state == 0) xor_state = 123456789;\n}\nuint32_t xorshift32() {\n    uint32_t x = xor_state;\n    x ^= x << 13;\n    x ^= x >> 17;\n    x ^= x << 5;\n    return xor_state = x;\n}\ninline double random_double() {\n    return (xorshift32() >> 8) / double(1 << 24);\n}\ninline int random_int(int n) {\n    return xorshift32() % n;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    init_random();\n\n    int N, M, H;\n    cin >> N >> M >> H;\n    vector<int> A(N);\n    for(int i=0; i<N; i++) cin >> A[i];\n    vector<vector<int>> adj(N);\n    for(int i=0; i<M; i++){\n        int u, v; cin >> u >> v;\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n    // skip coordinates\n    for(int i=0; i<N; i++){\n        int x, y; cin >> x >> y;\n    }\n\n    // state\n    vector<int> parent(N, -1);\n    vector<int> depth(N, 0);\n    vector<vector<int>> children(N);\n    vector<int> subtree_sum_A = A;\n    vector<int> subtree_max_depth(N, 0);\n    vector<int> root_of(N);\n    iota(root_of.begin(), root_of.end(), 0);\n\n    // greedy initialization (process vertices in descending A)\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int i, int j){ return A[i] > A[j]; });\n\n    for(int v : order){\n        if(parent[v] != -1) continue;\n        int best_u = -1;\n        int best_udepth = -1;\n        for(int u : adj[v]){\n            if(root_of[u] == v) continue;\n            int new_d = depth[u] + 1;\n            if(new_d + subtree_max_depth[v] <= H){\n                if(depth[u] > best_udepth){\n                    best_udepth = depth[u];\n                    best_u = u;\n                }\n            }\n        }\n        if(best_u != -1){\n            int delta = depth[best_u] + 1;\n            int new_root = root_of[best_u];\n            parent[v] = best_u;\n            children[best_u].push_back(v);\n            stack<int> st;\n            st.push(v);\n            while(!st.empty()){\n                int node = st.top(); st.pop();\n                depth[node] += delta;\n                root_of[node] = new_root;\n                for(int child : children[node]){\n                    st.push(child);\n                }\n            }\n            // update ancestors\n            vector<int> to_update;\n            int cur = best_u;\n            while(cur != -1){\n                to_update.push_back(cur);\n                cur = parent[cur];\n            }\n            sort(to_update.begin(), to_update.end(), [&](int a, int b){ return depth[a] > depth[b]; });\n            for(int node : to_update){\n                int sum = A[node];\n                int max_d = 0;\n                for(int child : children[node]){\n                    sum += subtree_sum_A[child];\n                    max_d = max(max_d, subtree_max_depth[child] + 1);\n                }\n                subtree_sum_A[node] = sum;\n                subtree_max_depth[node] = max_d;\n            }\n        }\n    }\n\n    // initial score\n    long long score = 0;\n    for(int i=0; i<N; i++){\n        score += (depth[i] + 1LL) * A[i];\n    }\n    long long best_score = score;\n    vector<int> best_parent = parent;\n\n    // helper functions for SA\n    auto is_descendant = [&](int anc, int desc) -> bool {\n        if(depth[desc] < depth[anc]) return false;\n        int cur = desc;\n        while(cur != -1 && depth[cur] > depth[anc]){\n            cur = parent[cur];\n        }\n        return cur == anc;\n    };\n\n    auto apply_move = [&](int v, int new_p, int delta) {\n        int old_p = parent[v];\n        int old_d = depth[v];\n        int new_d = (new_p == -1) ? 0 : depth[new_p] + 1;\n        int depth_delta = new_d - old_d;\n        // remove from old parent\n        if(old_p != -1){\n            auto it = find(children[old_p].begin(), children[old_p].end(), v);\n            if(it != children[old_p].end()) children[old_p].erase(it);\n        }\n        // add to new parent\n        if(new_p != -1){\n            children[new_p].push_back(v);\n        }\n        parent[v] = new_p;\n        // update depths in subtree of v\n        if(depth_delta != 0){\n            stack<int> st;\n            st.push(v);\n            while(!st.empty()){\n                int node = st.top(); st.pop();\n                depth[node] += depth_delta;\n                for(int child : children[node]){\n                    st.push(child);\n                }\n            }\n        }\n        // update subtree properties for affected ancestors\n        vector<int> to_update;\n        if(old_p != -1){\n            int cur = old_p;\n            while(cur != -1){\n                to_update.push_back(cur);\n                cur = parent[cur];\n            }\n        }\n        if(new_p != -1){\n            int cur = new_p;\n            while(cur != -1){\n                to_update.push_back(cur);\n                cur = parent[cur];\n            }\n        }\n        sort(to_update.begin(), to_update.end(), [&](int a, int b){ return depth[a] > depth[b]; });\n        to_update.erase(unique(to_update.begin(), to_update.end()), to_update.end());\n        for(int node : to_update){\n            int sum = A[node];\n            int max_d = 0;\n            for(int child : children[node]){\n                sum += subtree_sum_A[child];\n                max_d = max(max_d, subtree_max_depth[child] + 1);\n            }\n            subtree_sum_A[node] = sum;\n            subtree_max_depth[node] = max_d;\n        }\n    };\n\n    // simulated annealing\n    clock_t start_clock = clock();\n    double time_limit_sec = 1.95;\n    double T_start = 20000.0;\n    double T_end = 0.1;\n    double T = T_start;\n    int iter_count = 0;\n\n    while(true){\n        if(iter_count % 1000 == 0){\n            double elapsed = double(clock() - start_clock) / CLOCKS_PER_SEC;\n            if(elapsed >= time_limit_sec) break;\n            T = T_start * pow(T_end / T_start, elapsed / time_limit_sec);\n        }\n        iter_count++;\n        bool moved = false;\n        for(int attempt = 0; attempt < 5; attempt++){\n            int v = random_int(N);\n            int old_p = parent[v];\n            int u;\n            if(old_p != -1 && random_double() < 0.1){\n                u = -1;  // make root\n            } else {\n                if(adj[v].empty()) continue;\n                u = adj[v][random_int(adj[v].size())];\n            }\n            if(u == old_p) continue;\n            int new_d;\n            if(u == -1){\n                new_d = 0;\n            } else {\n                if(is_descendant(v, u) || is_descendant(u, v)) continue;\n                new_d = depth[u] + 1;\n                if(new_d + subtree_max_depth[v] > H) continue;\n            }\n            int delta = (new_d - depth[v]) * subtree_sum_A[v];\n            if(delta >= 0 || random_double() < exp(delta / T)){\n                apply_move(v, u, delta);\n                score += delta;\n                moved = true;\n                if(score > best_score){\n                    best_score = score;\n                    best_parent = parent;\n                }\n                break;\n            }\n        }\n    }\n\n    for(int i=0; i<N; i++){\n        cout << best_parent[i] << (i==N-1 ? \"\\n\" : \" \");\n    }\n\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <cstring>\nusing namespace std;\n\nconst int N = 20;\nconst int INF = 1e9;\n\nenum Mode { ROWS_ONE_WAY, COLS_ONE_WAY, NONE };\n\nstruct Solver {\n    vector<string> C;\n    bool fuku[N][N];\n    bool row_has_fuku[N], col_has_fuku[N];\n    int L_max[N], R_min[N], U_max[N], D_min[N];\n    vector<pair<int,int>> oni;\n    int K;\n    bool allowed_row[2*N], allowed_col[2*N];\n    vector<int> forced_row, forced_col, optional;\n\n    // working state\n    vector<int> row_cols[N], col_rows[N];\n    bool assign_row[2*N];\n    int total_cost;\n\n    void init() {\n        memset(row_has_fuku, 0, sizeof row_has_fuku);\n        memset(col_has_fuku, 0, sizeof col_has_fuku);\n        oni.clear();\n        for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) fuku[i][j] = false;\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (C[i][j] == 'x') oni.push_back({i,j});\n                else if (C[i][j] == 'o') {\n                    fuku[i][j] = true;\n                    row_has_fuku[i] = true;\n                    col_has_fuku[j] = true;\n                }\n            }\n        }\n        K = oni.size();\n        for (int i = 0; i < N; ++i) {\n            L_max[i] = N-1;\n            for (int j = 0; j < N; ++j) if (fuku[i][j]) { L_max[i] = j-1; break; }\n            R_min[i] = 0;\n            for (int j = N-1; j >= 0; --j) if (fuku[i][j]) { R_min[i] = j+1; break; }\n        }\n        for (int j = 0; j < N; ++j) {\n            U_max[j] = N-1;\n            for (int i = 0; i < N; ++i) if (fuku[i][j]) { U_max[j] = i-1; break; }\n            D_min[j] = 0;\n            for (int i = N-1; i >= 0; --i) if (fuku[i][j]) { D_min[j] = i+1; break; }\n        }\n        forced_row.clear(); forced_col.clear(); optional.clear();\n        for (int k = 0; k < K; ++k) {\n            int i = oni[k].first, j = oni[k].second;\n            allowed_row[k] = (j <= L_max[i]) || (j >= R_min[i]);\n            allowed_col[k] = (i <= U_max[j]) || (i >= D_min[j]);\n            if (allowed_row[k] && allowed_col[k]) optional.push_back(k);\n            else if (allowed_row[k]) forced_row.push_back(k);\n            else forced_col.push_back(k);\n        }\n    }\n\n    void clear_state() {\n        for (int i = 0; i < N; ++i) { row_cols[i].clear(); col_rows[i].clear(); }\n    }\n\n    void add_to_row(int i, int j) {\n        auto& v = row_cols[i];\n        v.insert(lower_bound(v.begin(), v.end(), j), j);\n    }\n    void add_to_col(int j, int i) {\n        auto& v = col_rows[j];\n        v.insert(lower_bound(v.begin(), v.end(), i), i);\n    }\n    void remove_from_row(int i, int j) {\n        auto& v = row_cols[i];\n        v.erase(lower_bound(v.begin(), v.end(), j));\n    }\n    void remove_from_col(int j, int i) {\n        auto& v = col_rows[j];\n        v.erase(lower_bound(v.begin(), v.end(), i));\n    }\n\n    // symmetric cost for a row\n    int cost_row_sym(int i) const {\n        const auto& cols = row_cols[i];\n        int m = cols.size();\n        if (m == 0) return 0;\n        int L_safe = L_max[i] + 1;\n        int R_safe = N - R_min[i];\n        vector<int> suf(m+1, 0);\n        for (int idx = m-1; idx >= 0; --idx) suf[idx] = max(suf[idx+1], N - cols[idx]);\n        int best = INF;\n        for (int L = 0; L <= L_safe; ++L) {\n            int idx = lower_bound(cols.begin(), cols.end(), L) - cols.begin();\n            int R = suf[idx];\n            if (R <= R_safe) {\n                int cost = 2 * (L + R);\n                if (cost < best) best = cost;\n            }\n        }\n        return best;\n    }\n    // symmetric cost for a column\n    int cost_col_sym(int j) const {\n        const auto& rows = col_rows[j];\n        int m = rows.size();\n        if (m == 0) return 0;\n        int U_safe = U_max[j] + 1;\n        int D_safe = N - D_min[j];\n        vector<int> suf(m+1, 0);\n        for (int idx = m-1; idx >= 0; --idx) suf[idx] = max(suf[idx+1], N - rows[idx]);\n        int best = INF;\n        for (int U = 0; U <= U_safe; ++U) {\n            int idx = lower_bound(rows.begin(), rows.end(), U) - rows.begin();\n            int D = suf[idx];\n            if (D <= D_safe) {\n                int cost = 2 * (U + D);\n                if (cost < best) best = cost;\n            }\n        }\n        return best;\n    }\n\n    // one\u2011way possible & cost for a row (only if all oni are on the same side of fuku)\n    bool one_way_possible_row(int i) const {\n        const auto& cols = row_cols[i];\n        if (cols.empty()) return true;\n        if (!row_has_fuku[i]) return true;\n        bool left = false, right = false;\n        for (int j : cols) {\n            if (j <= L_max[i]) left = true;\n            else if (j >= R_min[i]) right = true;\n        }\n        return !(left && right);\n    }\n    int one_way_cost_row(int i) const {\n        const auto& cols = row_cols[i];\n        if (cols.empty()) return 0;\n        if (!row_has_fuku[i]) {\n            // just push everything left (or right) whichever is smaller\n            int d_left = cols.back() + 1;\n            int d_right = N - cols[0];\n            return min(d_left, d_right);\n        }\n        int L = 0, R = 0;\n        for (int j : cols) {\n            if (j <= L_max[i]) L = max(L, j+1);\n            else if (j >= R_min[i]) R = max(R, N - j);\n        }\n        return L + R; // one direction is 0\n    }\n\n    bool one_way_possible_col(int j) const {\n        const auto& rows = col_rows[j];\n        if (rows.empty()) return true;\n        if (!col_has_fuku[j]) return true;\n        bool up = false, down = false;\n        for (int i : rows) {\n            if (i <= U_max[j]) up = true;\n            else if (i >= D_min[j]) down = true;\n        }\n        return !(up && down);\n    }\n    int one_way_cost_col(int j) const {\n        const auto& rows = col_rows[j];\n        if (rows.empty()) return 0;\n        if (!col_has_fuku[j]) {\n            int d_up = rows.back() + 1;\n            int d_down = N - rows[0];\n            return min(d_up, d_down);\n        }\n        int U = 0, D = 0;\n        for (int i : rows) {\n            if (i <= U_max[j]) U = max(U, i+1);\n            else if (i >= D_min[j]) D = max(D, N - i);\n        }\n        return U + D;\n    }\n\n    // mode aware costs\n    int cost_row_mode(int i, Mode mode) const {\n        if (mode == ROWS_ONE_WAY && one_way_possible_row(i))\n            return one_way_cost_row(i);\n        return cost_row_sym(i);\n    }\n    int cost_col_mode(int j, Mode mode) const {\n        if (mode == COLS_ONE_WAY && one_way_possible_col(j))\n            return one_way_cost_col(j);\n        return cost_col_sym(j);\n    }\n\n    int compute_total_cost(Mode mode) const {\n        int sum = 0;\n        for (int i = 0; i < N; ++i) sum += cost_row_mode(i, mode);\n        for (int j = 0; j < N; ++j) sum += cost_col_mode(j, mode);\n        return sum;\n    }\n\n    void apply_flip(int k, Mode mode) {\n        int i = oni[k].first, j = oni[k].second;\n        int old_r = cost_row_mode(i, mode);\n        int old_c = cost_col_mode(j, mode);\n        if (assign_row[k]) {\n            remove_from_row(i, j);\n            add_to_col(j, i);\n            assign_row[k] = false;\n        } else {\n            remove_from_col(j, i);\n            add_to_row(i, j);\n            assign_row[k] = true;\n        }\n        int new_r = cost_row_mode(i, mode);\n        int new_c = cost_col_mode(j, mode);\n        total_cost += (new_r - old_r) + (new_c - old_c);\n    }\n\n    void initialize_assignment(mt19937& rng) {\n        // forced\n        for (int k : forced_row) {\n            assign_row[k] = true;\n            add_to_row(oni[k].first, oni[k].second);\n        }\n        for (int k : forced_col) {\n            assign_row[k] = false;\n            add_to_col(oni[k].second, oni[k].first);\n        }\n        // greedy for optional\n        auto row_dist = [&](int k) {\n            int i = oni[k].first, j = oni[k].second;\n            int best = INF;\n            if (j <= L_max[i]) best = min(best, j+1);\n            if (j >= R_min[i]) best = min(best, N-j);\n            return best;\n        };\n        auto col_dist = [&](int k) {\n            int i = oni[k].first, j = oni[k].second;\n            int best = INF;\n            if (i <= U_max[j]) best = min(best, i+1);\n            if (i >= D_min[j]) best = min(best, N-i);\n            return best;\n        };\n        vector<int> opt = optional;\n        shuffle(opt.begin(), opt.end(), rng);\n        for (int k : opt) {\n            int rd = row_dist(k);\n            int cd = col_dist(k);\n            if (rd < cd) {\n                assign_row[k] = true;\n                add_to_row(oni[k].first, oni[k].second);\n            } else {\n                assign_row[k] = false;\n                add_to_col(oni[k].second, oni[k].first);\n            }\n        }\n    }\n\n    void hill_climb(Mode mode) {\n        if (optional.empty()) return;\n        mt19937 rng(random_device{}());\n        auto shuf = optional;\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            shuffle(shuf.begin(), shuf.end(), rng);\n            for (int k : shuf) {\n                int old = total_cost;\n                apply_flip(k, mode);\n                if (total_cost < old) improved = true;\n                else apply_flip(k, mode); // revert\n            }\n        }\n    }\n\n    void sa_run(Mode mode, double time_limit) {\n        if (optional.empty()) return;\n        mt19937 rng(random_device{}());\n        uniform_real_distribution<double> dist01(0.0, 1.0);\n        auto start_time = chrono::steady_clock::now();\n        int best_cost_local = total_cost;\n        bool best_assign_local[2*N];\n        for (int k = 0; k < K; ++k) best_assign_local[k] = assign_row[k];\n\n        while (true) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed >= time_limit) break;\n            double T = 5.0 * exp(-elapsed / time_limit * 10.0);\n            for (int b = 0; b < 100; ++b) {\n                int k = optional[rng() % optional.size()];\n                int old = total_cost;\n                apply_flip(k, mode);\n                int delta = total_cost - old;\n                if (delta <= 0 || dist01(rng) < exp(-delta / T)) {\n                    if (total_cost < best_cost_local) {\n                        best_cost_local = total_cost;\n                        for (int kk = 0; kk < K; ++kk) best_assign_local[kk] = assign_row[kk];\n                    }\n                } else {\n                    apply_flip(k, mode); // revert\n                }\n            }\n        }\n        // restore best found in this SA\n        clear_state();\n        for (int k = 0; k < K; ++k) {\n            assign_row[k] = best_assign_local[k];\n            if (assign_row[k]) add_to_row(oni[k].first, oni[k].second);\n            else add_to_col(oni[k].second, oni[k].first);\n        }\n        total_cost = best_cost_local;\n    }\n\n    // output the solution for a given partition and mode\n    void output_solution(Mode mode) {\n        // symmetric moves for lines not using one-way\n        auto row_sym = [&](int i) {\n            const auto& cols = row_cols[i];\n            if (cols.empty()) return;\n            int L_safe = L_max[i] + 1;\n            int R_safe = N - R_min[i];\n            int m = cols.size();\n            vector<int> suf(m+1,0);\n            for (int idx = m-1; idx >= 0; --idx) suf[idx] = max(suf[idx+1], N - cols[idx]);\n            int best_c = INF, best_L = 0, best_R = 0;\n            for (int L = 0; L <= L_safe; ++L) {\n                int idx = lower_bound(cols.begin(), cols.end(), L) - cols.begin();\n                int R = suf[idx];\n                if (R <= R_safe) {\n                    int cost = 2*(L+R);\n                    if (cost < best_c) { best_c = cost; best_L = L; best_R = R; }\n                }\n            }\n            for (int t = 0; t < best_L; ++t) cout << \"L \" << i << \"\\n\";\n            for (int t = 0; t < best_L; ++t) cout << \"R \" << i << \"\\n\";\n            for (int t = 0; t < best_R; ++t) cout << \"R \" << i << \"\\n\";\n            for (int t = 0; t < best_R; ++t) cout << \"L \" << i << \"\\n\";\n        };\n        auto col_sym = [&](int j) {\n            const auto& rows = col_rows[j];\n            if (rows.empty()) return;\n            int U_safe = U_max[j] + 1;\n            int D_safe = N - D_min[j];\n            int m = rows.size();\n            vector<int> suf(m+1,0);\n            for (int idx = m-1; idx >= 0; --idx) suf[idx] = max(suf[idx+1], N - rows[idx]);\n            int best_c = INF, best_U = 0, best_D = 0;\n            for (int U = 0; U <= U_safe; ++U) {\n                int idx = lower_bound(rows.begin(), rows.end(), U) - rows.begin();\n                int D = suf[idx];\n                if (D <= D_safe) {\n                    int cost = 2*(U+D);\n                    if (cost < best_c) { best_c = cost; best_U = U; best_D = D; }\n                }\n            }\n            for (int t = 0; t < best_U; ++t) cout << \"U \" << j << \"\\n\";\n            for (int t = 0; t < best_U; ++t) cout << \"D \" << j << \"\\n\";\n            for (int t = 0; t < best_D; ++t) cout << \"D \" << j << \"\\n\";\n            for (int t = 0; t < best_D; ++t) cout << \"U \" << j << \"\\n\";\n        };\n\n        // symmetric phase\n        if (mode != ROWS_ONE_WAY) {\n            for (int i = 0; i < N; ++i) row_sym(i);\n        } else {\n            // rows that cannot use one-way must be symmetric\n            for (int i = 0; i < N; ++i) if (!one_way_possible_row(i)) row_sym(i);\n        }\n        if (mode != COLS_ONE_WAY) {\n            for (int j = 0; j < N; ++j) col_sym(j);\n        } else {\n            for (int j = 0; j < N; ++j) if (!one_way_possible_col(j)) col_sym(j);\n        }\n\n        // one-way phase at the end\n        if (mode == ROWS_ONE_WAY) {\n            for (int i = 0; i < N; ++i) {\n                if (!one_way_possible_row(i) || row_cols[i].empty()) continue;\n                int cost = one_way_cost_row(i);\n                if (cost == 0) continue;\n                if (!row_has_fuku[i]) {\n                    int d_left = row_cols[i].back() + 1;\n                    int d_right = N - row_cols[i][0];\n                    if (d_left <= d_right) for (int t=0; t<d_left; ++t) cout << \"L \" << i << \"\\n\";\n                    else for (int t=0; t<d_right; ++t) cout << \"R \" << i << \"\\n\";\n                } else {\n                    int L = 0, R = 0;\n                    for (int j : row_cols[i]) {\n                        if (j <= L_max[i]) L = max(L, j+1);\n                        else if (j >= R_min[i]) R = max(R, N - j);\n                    }\n                    // only one of L,R >0\n                    if (L) for (int t=0; t<L; ++t) cout << \"L \" << i << \"\\n\";\n                    else for (int t=0; t<R; ++t) cout << \"R \" << i << \"\\n\";\n                }\n            }\n        }\n        if (mode == COLS_ONE_WAY) {\n            for (int j = 0; j < N; ++j) {\n                if (!one_way_possible_col(j) || col_rows[j].empty()) continue;\n                int cost = one_way_cost_col(j);\n                if (cost == 0) continue;\n                if (!col_has_fuku[j]) {\n                    int d_up = col_rows[j].back() + 1;\n                    int d_down = N - col_rows[j][0];\n                    if (d_up <= d_down) for (int t=0; t<d_up; ++t) cout << \"U \" << j << \"\\n\";\n                    else for (int t=0; t<d_down; ++t) cout << \"D \" << j << \"\\n\";\n                } else {\n                    int U = 0, D = 0;\n                    for (int i : col_rows[j]) {\n                        if (i <= U_max[j]) U = max(U, i+1);\n                        else if (i >= D_min[j]) D = max(D, N - i);\n                    }\n                    if (U) for (int t=0; t<U; ++t) cout << \"U \" << j << \"\\n\";\n                    else for (int t=0; t<D; ++t) cout << \"D \" << j << \"\\n\";\n                }\n            }\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    int n;\n    cin >> n;\n    solver.C.resize(n);\n    for (int i = 0; i < n; ++i) cin >> solver.C[i];\n    solver.init();\n\n    int best_cost_overall = INF;\n    bool best_assign_overall[2*N];\n    Mode best_mode = NONE;\n    auto copy_assign = [&](bool* src) {\n        for (int k = 0; k < solver.K; ++k) best_assign_overall[k] = src[k];\n    };\n\n    auto start_total = chrono::steady_clock::now();\n    mt19937 rng_init(random_device{}());\n\n    // try all three modes with multiple restarts within time\n    const Mode modes[3] = {ROWS_ONE_WAY, COLS_ONE_WAY, NONE};\n    double total_time_budget = 1.9;\n    double time_per_mode = total_time_budget / 3.0;\n    auto run_mode = [&](Mode mode, double time_limit) {\n        auto mode_start = chrono::steady_clock::now();\n        int best_local = INF;\n        bool best_assign_local[2*N];\n        while (true) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - mode_start).count();\n            if (elapsed >= time_limit) break;\n            double sa_time = min(0.25, time_limit - elapsed);\n            solver.clear_state();\n            solver.initialize_assignment(rng_init);\n            solver.total_cost = solver.compute_total_cost(mode);\n            solver.hill_climb(mode);\n            solver.sa_run(mode, sa_time);\n            if (solver.total_cost < best_local) {\n                best_local = solver.total_cost;\n                for (int k = 0; k < solver.K; ++k) best_assign_local[k] = solver.assign_row[k];\n            }\n        }\n        // restore best for this mode\n        solver.clear_state();\n        for (int k = 0; k < solver.K; ++k) {\n            solver.assign_row[k] = best_assign_local[k];\n            if (solver.assign_row[k]) solver.add_to_row(solver.oni[k].first, solver.oni[k].second);\n            else solver.add_to_col(solver.oni[k].second, solver.oni[k].first);\n        }\n        solver.total_cost = best_local;\n        return best_local;\n    };\n\n    for (int mi = 0; mi < 3; ++mi) {\n        Mode mode = modes[mi];\n        int cost = run_mode(mode, time_per_mode);\n        if (cost < best_cost_overall) {\n            best_cost_overall = cost;\n            best_mode = mode;\n            copy_assign(solver.assign_row);\n        }\n    }\n\n    // restore overall best\n    solver.clear_state();\n    for (int k = 0; k < solver.K; ++k) {\n        solver.assign_row[k] = best_assign_overall[k];\n        if (solver.assign_row[k]) solver.add_to_row(solver.oni[k].first, solver.oni[k].second);\n        else solver.add_to_col(solver.oni[k].second, solver.oni[k].first);\n    }\n    solver.total_cost = best_cost_overall;\n\n    solver.output_solution(best_mode);\n    return 0;\n}","ahc044":"#include <iostream>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n#include <cstring>\n#include <random>\n#include <vector>\nusing namespace std;\n\nconst int N = 100;\nconst int L = 500000;\nint T[N];\n\n// fast simulation: we need this many times, keep it simple\nint real_error(const int a[N], const int b[N]) {\n    int t[N] = {0};\n    int cur = 0;\n    t[0] = 1;\n    for (int step = 1; step < L; ++step) {\n        cur = (t[cur] & 1) ? a[cur] : b[cur];\n        t[cur]++;\n    }\n    int err = 0;\n    for (int i = 0; i < N; ++i) {\n        int diff = t[i] - T[i];\n        if (diff < 0) diff = -diff;\n        err += diff;\n    }\n    return err;\n}\n\n// surrogate: stationary distribution of the random walk (a_i and b_i with equal probability)\ndouble surrogate_error(const int a[N], const int b[N]) {\n    double pi[N], new_pi[N];\n    for (int i = 0; i < N; ++i) pi[i] = 1.0 / N;\n    const int max_iter = 100;\n    for (int iter = 0; iter < max_iter; ++iter) {\n        for (int i = 0; i < N; ++i) new_pi[i] = 0.0;\n        for (int i = 0; i < N; ++i) {\n            if (a[i] == b[i]) {\n                new_pi[a[i]] += pi[i];\n            } else {\n                new_pi[a[i]] += pi[i] * 0.5;\n                new_pi[b[i]] += pi[i] * 0.5;\n            }\n        }\n        for (int i = 0; i < N; ++i) pi[i] = new_pi[i];\n    }\n    double err = 0.0;\n    for (int i = 0; i < N; ++i) err += fabs(pi[i] * L - T[i]);\n    return err;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    int N_in, L_in;\n    cin >> N_in >> L_in;\n    for (int i = 0; i < N; ++i) cin >> T[i];\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto rand_int = [&](int max) { return uniform_int_distribution<int>(0, max-1)(rng); };\n    auto rand_double = [&]() { return uniform_real_distribution<double>(0.0, 1.0)(rng); };\n\n    // ---------- greedy initial solution (approximate balance) ----------\n    vector<int> caps(N, 0);\n    for (int i = 0; i < N; ++i) caps[i] = 2 * T[i];\n    vector<pair<int,int>> items; // (weight, node_i)\n    for (int i = 0; i < N; ++i) {\n        items.emplace_back(T[i], i);\n        items.emplace_back(T[i], i);\n    }\n    sort(items.begin(), items.end(), greater<pair<int,int>>());\n\n    int init_a[N], init_b[N];\n    for (int i = 0; i < N; ++i) init_a[i] = init_b[i] = -1;\n\n    for (auto &p : items) {\n        int w = p.first;\n        int i = p.second;\n        int best_j = 0;\n        int best_cap = -1;\n        for (int j = 0; j < N; ++j) {\n            if (caps[j] > best_cap) {\n                best_cap = caps[j];\n                best_j = j;\n            }\n        }\n        if (init_a[i] == -1) init_a[i] = best_j;\n        else init_b[i] = best_j;\n        caps[best_j] -= w;\n    }\n    for (int i = 0; i < N; ++i) {\n        if (init_a[i] == -1) init_a[i] = i;\n        if (init_b[i] == -1) init_b[i] = i;\n    }\n\n    int best_a[N], best_b[N];\n    memcpy(best_a, init_a, sizeof(best_a));\n    memcpy(best_b, init_b, sizeof(best_b));\n    int best_err = real_error(best_a, best_b);\n\n    // fallback: if greedy yields huge error, start from a simple cycle\n    if (best_err > 1000000) {\n        for (int i = 0; i < N; ++i) {\n            best_a[i] = (i + 1) % N;\n            best_b[i] = (i + 1) % N;\n        }\n        best_err = real_error(best_a, best_b);\n    }\n\n    int cur_a[N], cur_b[N];\n    memcpy(cur_a, best_a, sizeof(cur_a));\n    memcpy(cur_b, best_b, sizeof(cur_b));\n    int cur_real_err = best_err;\n    double cur_surr_err = surrogate_error(cur_a, cur_b);\n    double best_surr_err = cur_surr_err;\n\n    auto start = chrono::steady_clock::now();\n    double elapsed = 0.0;\n    const double time_limit_surr = 1.3;\n    const double time_limit_total = 1.95;\n\n    // ---------- Stage 1: Surrogate SA ----------\n    double temp_surr = 200.0;\n    double temp_surr_end = 0.1;\n    int iter = 0;\n    while (true) {\n        if (iter % 100 == 0) {\n            auto now = chrono::steady_clock::now();\n            elapsed = chrono::duration<double>(now - start).count();\n            if (elapsed > time_limit_surr) break;\n            double progress = elapsed / time_limit_surr;\n            temp_surr = 200.0 * pow(temp_surr_end / 200.0, progress);\n        }\n        int type = rand_int(10);\n        int i = rand_int(N);\n        int old_a = cur_a[i], old_b = cur_b[i];\n        if (type < 4) {\n            cur_a[i] = rand_int(N);\n        } else if (type < 8) {\n            cur_b[i] = rand_int(N);\n        } else if (type == 8) {\n            swap(cur_a[i], cur_b[i]);\n        } else {\n            cur_a[i] = rand_int(N);\n            cur_b[i] = rand_int(N);\n        }\n        double new_surr_err = surrogate_error(cur_a, cur_b);\n        double delta = new_surr_err - cur_surr_err;\n        bool accepted = false;\n        if (delta <= 0) {\n            accepted = true;\n        } else if (rand_double() < exp(-delta / temp_surr)) {\n            accepted = true;\n        }\n        if (accepted) {\n            cur_surr_err = new_surr_err;\n            if (cur_surr_err < best_surr_err) {\n                best_surr_err = cur_surr_err;\n                int real_err = real_error(cur_a, cur_b);\n                if (real_err < best_err) {\n                    best_err = real_err;\n                    memcpy(best_a, cur_a, sizeof(cur_a));\n                    memcpy(best_b, cur_b, sizeof(cur_b));\n                }\n            }\n        } else {\n            cur_a[i] = old_a;\n            cur_b[i] = old_b;\n        }\n        ++iter;\n    }\n\n    // restore best found\n    memcpy(cur_a, best_a, sizeof(cur_a));\n    memcpy(cur_b, best_b, sizeof(cur_b));\n    cur_real_err = best_err;\n\n    // ---------- Stage 2: Real SA ----------\n    double temp_real = max(cur_real_err * 0.25, 10.0);\n    double temp_real_end = 0.1;\n    iter = 0;\n    while (true) {\n        if (iter % 10 == 0) {\n            auto now = chrono::steady_clock::now();\n            elapsed = chrono::duration<double>(now - start).count();\n            if (elapsed > time_limit_total) break;\n            double progress = max(0.0, min(1.0, (elapsed - time_limit_surr) / (time_limit_total - time_limit_surr)));\n            temp_real = max(cur_real_err * 0.25, 10.0) * pow(temp_real_end / max(cur_real_err * 0.25, 10.0), progress);\n        }\n        int type = rand_int(10);\n        int i = rand_int(N);\n        int old_a = cur_a[i], old_b = cur_b[i];\n        if (type < 4) {\n            cur_a[i] = rand_int(N);\n        } else if (type < 8) {\n            cur_b[i] = rand_int(N);\n        } else if (type == 8) {\n            swap(cur_a[i], cur_b[i]);\n        } else {\n            cur_a[i] = rand_int(N);\n            cur_b[i] = rand_int(N);\n        }\n        int new_err = real_error(cur_a, cur_b);\n        int delta = new_err - cur_real_err;\n        bool accepted = false;\n        if (delta <= 0) {\n            accepted = true;\n        } else if (rand_double() < exp(-delta / temp_real)) {\n            accepted = true;\n        }\n        if (accepted) {\n            cur_real_err = new_err;\n            if (new_err < best_err) {\n                best_err = new_err;\n                memcpy(best_a, cur_a, sizeof(cur_a));\n                memcpy(best_b, cur_b, sizeof(cur_b));\n            }\n        } else {\n            cur_a[i] = old_a;\n            cur_b[i] = old_b;\n        }\n        ++iter;\n        if (best_err == 0) break;\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << best_a[i] << \" \" << best_b[i] << \"\\n\";\n    }\n\n    return 0;\n}","ahc045":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n#include <cstdint>\n#include <climits>\n\nusing namespace std;\n\nconst int INF = 1e9;\n\n// ---------- DSU (not needed for final tree, but useful) ----------\nstruct DSU {\n    vector<int> parent;\n    DSU(int n) { parent.assign(n, -1); }\n    int find(int x) { return parent[x] < 0 ? x : parent[x] = find(parent[x]); }\n    bool unite(int x, int y) {\n        x = find(x); y = find(y);\n        if (x == y) return false;\n        if (parent[x] > parent[y]) swap(x, y);\n        parent[x] += parent[y];\n        parent[y] = x;\n        return true;\n    }\n};\n\n// ---------- global state ----------\nint N, M, Q, L, W;\nint q_used = 0;\nvector<int> cx, cy;\n\n// ---------- query function ----------\nvector<pair<int, int>> query_subset(const vector<int>& C) {\n    if (q_used >= Q) return {};\n    ++q_used;\n    int l = (int)C.size();\n    cout << \"? \" << l;\n    for (int c : C) cout << \" \" << c;\n    cout << endl;\n    vector<pair<int, int>> res(l - 1);\n    for (int i = 0; i < l - 1; ++i) {\n        cin >> res[i].first >> res[i].second;\n    }\n    return res;\n}\n\n// ---------- Morton code ----------\nuint64_t morton(int x, int y) {\n    // 14 bits per coordinate (0..16383) > 10000, so safe\n    uint64_t z = 0;\n    for (int i = 13; i >= 0; --i) {\n        z = (z << 2) | ((((x >> i) & 1) << 1) | ((y >> i) & 1));\n    }\n    return z;\n}\n\n// ---------- build tree for a group using a given ordering ----------\nvector<pair<int, int>> build_group_tree(const vector<int>& group_cities) {\n    int sz = (int)group_cities.size();\n    if (sz <= 1) return {};\n    if (sz == 2) {\n        return { {group_cities[0], group_cities[1]} };\n    }\n\n    vector<pair<int, int>> edges;\n    int pos = 0;\n    while (pos < sz && q_used < Q) {\n        if (pos == 0) {\n            int take = min(L, sz - pos);\n            vector<int> subset(group_cities.begin(), group_cities.begin() + take);\n            auto res = query_subset(subset);\n            edges.insert(edges.end(), res.begin(), res.end());\n            pos += take;\n        } else {\n            int anchor = group_cities[pos - 1];\n            int take = min(L - 1, sz - pos);\n            vector<int> subset = {anchor};\n            subset.insert(subset.end(), group_cities.begin() + pos,\n                          group_cities.begin() + pos + take);\n            auto res = query_subset(subset);\n            edges.insert(edges.end(), res.begin(), res.end());\n            pos += take;\n        }\n    }\n    // if queries exhausted, connect remaining cities linearly\n    while (pos < sz) {\n        edges.emplace_back(group_cities[pos - 1], group_cities[pos]);\n        ++pos;\n    }\n    return edges;\n}\n\n// ---------- nearest neighbour TSP path (centres) ----------\nvector<int> tsp_nearest_neighbour(const vector<int>& cities) {\n    int k = (int)cities.size();\n    if (k <= 2) return cities;\n    vector<bool> used(k, false);\n    vector<int> path;\n    path.reserve(k);\n    // start from first city (can be improved)\n    int cur = 0;\n    used[cur] = true;\n    path.push_back(cities[cur]);\n    for (int step = 1; step < k; ++step) {\n        int best = -1;\n        long long best_dist = LLONG_MAX;\n        for (int nxt = 0; nxt < k; ++nxt) {\n            if (used[nxt]) continue;\n            long long dx = cx[cities[cur]] - cx[cities[nxt]];\n            long long dy = cy[cities[cur]] - cy[cities[nxt]];\n            long long d = dx * dx + dy * dy;\n            if (d < best_dist) {\n                best_dist = d;\n                best = nxt;\n            }\n        }\n        cur = best;\n        used[cur] = true;\n        path.push_back(cities[cur]);\n    }\n    return path;\n}\n\n// ---------- main ----------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    cin >> N >> M >> Q >> L >> W;\n    vector<int> G(M);\n    for (int i = 0; i < M; ++i) cin >> G[i];\n\n    vector<int> lx(N), rx(N), ly(N), ry(N);\n    cx.resize(N);\n    cy.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n        cx[i] = (lx[i] + rx[i]) / 2;\n        cy[i] = (ly[i] + ry[i]) / 2;\n    }\n\n    // global order: Morton curve\n    vector<uint64_t> mort(N);\n    for (int i = 0; i < N; ++i) mort[i] = morton(cx[i], cy[i]);\n\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int i, int j) { return mort[i] < mort[j]; });\n\n    // assign groups as contiguous blocks in global order\n    vector<vector<int>> groups(M);\n    int cur = 0;\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < G[i]; ++j) {\n            groups[i].push_back(order[cur++]);\n        }\n    }\n\n    // build trees for groups using reordering within each group\n    vector<vector<int>> group_cities(M);\n    vector<vector<pair<int, int>>> group_edges(M);\n\n    for (int k = 0; k < M; ++k) {\n        if (groups[k].empty()) continue;\n        // reorder the cities inside the group using TSP nearest neighbour\n        vector<int> tsp_order = tsp_nearest_neighbour(groups[k]);\n        group_cities[k] = tsp_order;          // store the actual cities in final order\n        // build the tree using queries along this order\n        group_edges[k] = build_group_tree(tsp_order);\n    }\n\n    // output answer\n    cout << \"!\" << endl;\n    for (int k = 0; k < M; ++k) {\n        const auto &cities = group_cities[k];\n        for (int i = 0; i < (int)cities.size(); ++i) {\n            if (i) cout << \" \";\n            cout << cities[i];\n        }\n        cout << endl;\n        for (const auto &e : group_edges[k]) {\n            cout << e.first << \" \" << e.second << endl;\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <string>\n\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int N, M;\n    cin >> N >> M;\n    vector<int> R(M), C(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> R[i] >> C[i];\n    }\n\n    int total = N * N;\n    int S = total;          // represents \"no block\"\n    int state_size = total + 1;\n    int MAX_STATE = total * state_size;\n\n    // precompute row and column for each cell\n    vector<int> pr(total), pc(total);\n    for (int i = 0; i < total; ++i) {\n        pr[i] = i / N;\n        pc[i] = i % N;\n    }\n\n    vector<int> vis(MAX_STATE, 0);\n    vector<int> ps(MAX_STATE);\n    vector<int> pa(MAX_STATE);\n    vector<int> q(MAX_STATE);\n    int tok = 0;\n\n    vector<int> total_actions;\n\n    // process each segment: start -> target1, target1 -> target2, ...\n    for (int seg = 0; seg < M - 1; ++seg) {\n        int start_pos = R[seg] * N + C[seg];\n        int target_pos = R[seg+1] * N + C[seg+1];\n\n        ++tok;\n        int head = 0, tail = 0;\n        int start_state = start_pos * state_size + S;\n        vis[start_state] = tok;\n        ps[start_state] = -1;\n        q[tail++] = start_state;\n        int goal_state = -1;\n\n        while (head < tail) {\n            int s = q[head++];\n            int pos = s / state_size;\n            int block = s % state_size;\n            if (pos == target_pos && block == S) {\n                goal_state = s;\n                break;\n            }\n            int r = pr[pos], c = pc[pos];\n\n            for (int d = 0; d < 4; ++d) {\n                // --- Move ---\n                int nr = r, nc = c;\n                if (d == 0) nr--;\n                else if (d == 1) nr++;\n                else if (d == 2) nc--;\n                else nc++;\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                    int npos = nr * N + nc;\n                    if (npos != block) {\n                        int nstate = npos * state_size + block;\n                        if (vis[nstate] != tok) {\n                            vis[nstate] = tok;\n                            ps[nstate] = s;\n                            pa[nstate] = 0 * 4 + d;  // Move\n                            q[tail++] = nstate;\n                        }\n                    }\n                }\n\n                // --- Slide ---\n                int slide_pos;\n                if (block == S) {\n                    if (d == 0) slide_pos = c;                     // (0, c)\n                    else if (d == 1) slide_pos = (N-1)*N + c;      // (N-1, c)\n                    else if (d == 2) slide_pos = r * N;            // (r, 0)\n                    else slide_pos = r * N + (N-1);                // (r, N-1)\n                } else {\n                    int br = block / N, bc = block % N;\n                    if (d == 0) {  // up\n                        if (bc == c && br < r) slide_pos = (br + 1) * N + c;\n                        else slide_pos = c;\n                    } else if (d == 1) {  // down\n                        if (bc == c && br > r) slide_pos = (br - 1) * N + c;\n                        else slide_pos = (N-1)*N + c;\n                    } else if (d == 2) {  // left\n                        if (br == r && bc < c) slide_pos = r * N + (bc + 1);\n                        else slide_pos = r * N;\n                    } else {  // right\n                        if (br == r && bc > c) slide_pos = r * N + (bc - 1);\n                        else slide_pos = r * N + (N-1);\n                    }\n                }\n                int nstate_s = slide_pos * state_size + block;\n                if (vis[nstate_s] != tok) {\n                    vis[nstate_s] = tok;\n                    ps[nstate_s] = s;\n                    pa[nstate_s] = 1 * 4 + d;  // Slide\n                    q[tail++] = nstate_s;\n                }\n\n                // --- Alter ---\n                int adj_r = r, adj_c = c;\n                if (d == 0) adj_r--;\n                else if (d == 1) adj_r++;\n                else if (d == 2) adj_c--;\n                else adj_c++;\n                if (adj_r >= 0 && adj_r < N && adj_c >= 0 && adj_c < N) {\n                    int adj_id = adj_r * N + adj_c;\n                    if (block == S) {\n                        // place block\n                        int nstate = pos * state_size + adj_id;\n                        if (vis[nstate] != tok) {\n                            vis[nstate] = tok;\n                            ps[nstate] = s;\n                            pa[nstate] = 2 * 4 + d;  // Alter (place)\n                            q[tail++] = nstate;\n                        }\n                    } else {\n                        if (adj_id == block) {\n                            // remove block\n                            int nstate = pos * state_size + S;\n                            if (vis[nstate] != tok) {\n                                vis[nstate] = tok;\n                                ps[nstate] = s;\n                                pa[nstate] = 2 * 4 + d;  // Alter (remove)\n                                q[tail++] = nstate;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        // reconstruct action sequence for this segment\n        vector<int> seg_actions;\n        for (int s = goal_state; s != start_state; s = ps[s]) {\n            seg_actions.push_back(pa[s]);\n        }\n        reverse(seg_actions.begin(), seg_actions.end());\n        total_actions.insert(total_actions.end(), seg_actions.begin(), seg_actions.end());\n    }\n\n    // cancel consecutive identical Alter actions (place/remove pairs that do nothing)\n    vector<int> opt_actions;\n    for (int aid : total_actions) {\n        if (!opt_actions.empty() && opt_actions.back() == aid && (aid / 4) == 2) {\n            opt_actions.pop_back();\n        } else {\n            opt_actions.push_back(aid);\n        }\n    }\n    total_actions = move(opt_actions);\n\n    const char act_chars[3] = {'M', 'S', 'A'};\n    const char dir_chars[4] = {'U', 'D', 'L', 'R'};\n    for (int aid : total_actions) {\n        cout << act_chars[aid / 4] << ' ' << dir_chars[aid % 4] << '\\n';\n    }\n\n    return 0;\n}"},"8":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\nusing namespace chrono;\n\nstruct XorShift {\n    uint32_t x, y, z, w;\n    XorShift(uint32_t seed = 123456789) : x(seed), y(362436069), z(521288629), w(88675123) {\n        for (int i = 0; i < 10; i++) next();\n    }\n    uint32_t next() {\n        uint32_t t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = w ^ (w >> 19) ^ t ^ (t >> 8);\n    }\n    int nextInt(int max) {\n        return next() % (max + 1);\n    }\n    double nextDouble() {\n        return (next() & 0xFFFFFF) / 16777216.0;\n    }\n};\n\nstruct Node {\n    int type;   // 0:leaf, 1:vertical, 2:horizontal\n    int leaf_id;\n    int k;\n    int left, right;\n    int parent;\n    int min_k, max_k;\n    int x1, y1, x2, y2;\n    double score;\n};\n\nint n;\nvector<int> x, y, r;\nvector<Node> nodes;\nint root;\nXorShift rng(system_clock::now().time_since_epoch().count());\n\ndouble leaf_score(long long area, int req) {\n    double rat = (area <= req) ? (double)area / req : (double)req / area;\n    return 2.0 * rat - rat * rat;\n}\n\ndouble eval_subtree(int idx) {\n    Node& node = nodes[idx];\n    if (node.type == 0) {\n        long long area = (long long)(node.x2 - node.x1) * (node.y2 - node.y1);\n        node.score = leaf_score(area, r[node.leaf_id]);\n        return node.score;\n    }\n    int k = node.k;\n    if (node.type == 1) {\n        nodes[node.left].x1 = node.x1; nodes[node.left].y1 = node.y1;\n        nodes[node.left].x2 = k;       nodes[node.left].y2 = node.y2;\n        nodes[node.right].x1 = k;      nodes[node.right].y1 = node.y1;\n        nodes[node.right].x2 = node.x2; nodes[node.right].y2 = node.y2;\n    } else {\n        nodes[node.left].x1 = node.x1; nodes[node.left].y1 = node.y1;\n        nodes[node.left].x2 = node.x2; nodes[node.left].y2 = k;\n        nodes[node.right].x1 = node.x1; nodes[node.right].y1 = k;\n        nodes[node.right].x2 = node.x2; nodes[node.right].y2 = node.y2;\n    }\n    double ls = eval_subtree(node.left);\n    double rs = eval_subtree(node.right);\n    node.score = ls + rs;\n    return node.score;\n}\n\nvoid full_eval() {\n    nodes[root].x1 = 0; nodes[root].y1 = 0;\n    nodes[root].x2 = 10000; nodes[root].y2 = 10000;\n    eval_subtree(root);\n}\n\nvoid get_points_minmax(int idx, int& min_x, int& max_x, int& min_y, int& max_y) {\n    Node& nd = nodes[idx];\n    if (nd.type == 0) {\n        min_x = max_x = x[nd.leaf_id];\n        min_y = max_y = y[nd.leaf_id];\n    } else {\n        int lx_min, lx_max, ly_min, ly_max;\n        get_points_minmax(nd.left, lx_min, lx_max, ly_min, ly_max);\n        int rx_min, rx_max, ry_min, ry_max;\n        get_points_minmax(nd.right, rx_min, rx_max, ry_min, ry_max);\n        min_x = min(lx_min, rx_min);\n        max_x = max(lx_max, rx_max);\n        min_y = min(ly_min, ry_min);\n        max_y = max(ly_max, ry_max);\n    }\n}\n\nbool try_reorient(int idx) {\n    Node& node = nodes[idx];\n    if (node.type == 0) return false;\n    int lx_min, lx_max, ly_min, ly_max;\n    int rx_min, rx_max, ry_min, ry_max;\n    get_points_minmax(node.left, lx_min, lx_max, ly_min, ly_max);\n    get_points_minmax(node.right, rx_min, rx_max, ry_min, ry_max);\n\n    if (node.type == 1) { // vertical -> horizontal\n        if (ly_max < ry_min) {\n            node.type = 2;\n            node.min_k = ly_max + 1;\n            node.max_k = ry_min;\n            node.k = node.min_k + rng.nextInt(node.max_k - node.min_k);\n            return true;\n        }\n        if (ry_max < ly_min) {\n            swap(node.left, node.right);\n            node.type = 2;\n            node.min_k = ry_max + 1;\n            node.max_k = ly_min;\n            node.k = node.min_k + rng.nextInt(node.max_k - node.min_k);\n            return true;\n        }\n    } else {\n        if (lx_max < rx_min) {\n            node.type = 1;\n            node.min_k = lx_max + 1;\n            node.max_k = rx_min;\n            node.k = node.min_k + rng.nextInt(node.max_k - node.min_k);\n            return true;\n        }\n        if (rx_max < lx_min) {\n            swap(node.left, node.right);\n            node.type = 1;\n            node.min_k = rx_max + 1;\n            node.max_k = lx_min;\n            node.k = node.min_k + rng.nextInt(node.max_k - node.min_k);\n            return true;\n        }\n    }\n    return false;\n}\n\nbool try_swap_children(int idx) {\n    Node& node = nodes[idx];\n    if (node.type == 0) return false;\n    int lx_min, lx_max, ly_min, ly_max;\n    int rx_min, rx_max, ry_min, ry_max;\n    get_points_minmax(node.left, lx_min, lx_max, ly_min, ly_max);\n    get_points_minmax(node.right, rx_min, rx_max, ry_min, ry_max);\n    int new_min_k, new_max_k;\n    if (node.type == 1) {\n        new_min_k = rx_max + 1;\n        new_max_k = lx_min;\n    } else {\n        new_min_k = ry_max + 1;\n        new_max_k = ly_min;\n    }\n    if (new_min_k > new_max_k) return false;\n    swap(node.left, node.right);\n    node.min_k = new_min_k;\n    node.max_k = new_max_k;\n    node.k = new_min_k + rng.nextInt(new_max_k - new_min_k);\n    return true;\n}\n\nvoid collect_leaves(int idx, vector<int>& out) {\n    Node& nd = nodes[idx];\n    if (nd.type == 0) out.push_back(nd.leaf_id);\n    else {\n        collect_leaves(nd.left, out);\n        collect_leaves(nd.right, out);\n    }\n}\n\nint build_greedy_tree(const vector<int>& pts, int x1, int y1, int x2, int y2, int parent);\nint build_random_tree(const vector<int>& pts, int x1, int y1, int x2, int y2, int parent);\n\nint build_greedy_tree(const vector<int>& pts, int x1, int y1, int x2, int y2, int parent) {\n    if (pts.size() == 1) {\n        int id = pts[0];\n        nodes.push_back({0, id, 0, -1, -1, parent, 0, 0, 0, 0, 0, 0, 0.0});\n        return (int)nodes.size() - 1;\n    }\n    long long sumR = 0;\n    for (int id : pts) sumR += r[id];\n\n    struct Candidate { int orient; int k; vector<int> left, right; double err; };\n    vector<Candidate> cands;\n\n    vector<int> sorted = pts;\n    sort(sorted.begin(), sorted.end(), [&](int a, int b) { return x[a] < x[b]; });\n    long long left_sum = 0;\n    for (size_t i = 0; i + 1 < sorted.size(); i++) {\n        left_sum += r[sorted[i]];\n        double ideal = (double)left_sum / sumR;\n        int min_k = x[sorted[i]] + 1;\n        int max_k = x[sorted[i+1]];\n        if (min_k > max_k) continue;\n        int k = clamp((int)round(x1 + ideal * (x2 - x1)), min_k, max_k);\n        double actual = (double)(k - x1) / (x2 - x1);\n        double err = fabs(actual - ideal);\n        cands.push_back({1, k, \n            vector<int>(sorted.begin(), sorted.begin()+i+1),\n            vector<int>(sorted.begin()+i+1, sorted.end()), err});\n    }\n\n    sort(sorted.begin(), sorted.end(), [&](int a, int b) { return y[a] < y[b]; });\n    left_sum = 0;\n    for (size_t i = 0; i + 1 < sorted.size(); i++) {\n        left_sum += r[sorted[i]];\n        double ideal = (double)left_sum / sumR;\n        int min_k = y[sorted[i]] + 1;\n        int max_k = y[sorted[i+1]];\n        if (min_k > max_k) continue;\n        int k = clamp((int)round(y1 + ideal * (y2 - y1)), min_k, max_k);\n        double actual = (double)(k - y1) / (y2 - y1);\n        double err = fabs(actual - ideal);\n        cands.push_back({2, k, \n            vector<int>(sorted.begin(), sorted.begin()+i+1),\n            vector<int>(sorted.begin()+i+1, sorted.end()), err});\n    }\n\n    double min_err = 1e9;\n    for (auto& c : cands) if (c.err < min_err) min_err = c.err;\n    vector<double> w(cands.size());\n    double sum_w = 0;\n    for (size_t i = 0; i < cands.size(); i++) {\n        w[i] = exp(-(cands[i].err - min_err) * 100.0);\n        sum_w += w[i];\n    }\n    double rv = rng.nextDouble() * sum_w;\n    size_t chosen = 0;\n    double cum = 0;\n    for (size_t i = 0; i < cands.size(); i++) {\n        cum += w[i];\n        if (cum >= rv) { chosen = i; break; }\n    }\n    Candidate& best = cands[chosen];\n\n    nodes.push_back({best.orient, -1, best.k, -1, -1, parent, 0, 0, 0, 0, 0, 0, 0.0});\n    int idx = (int)nodes.size() - 1;\n    int lchild, rchild;\n    if (best.orient == 1) {\n        lchild = build_greedy_tree(best.left, x1, y1, best.k, y2, idx);\n        rchild = build_greedy_tree(best.right, best.k, y1, x2, y2, idx);\n        int max_x_left = 0, min_x_right = 10000;\n        for (int id : best.left) max_x_left = max(max_x_left, x[id]);\n        for (int id : best.right) min_x_right = min(min_x_right, x[id]);\n        nodes[idx].min_k = max_x_left + 1;\n        nodes[idx].max_k = min_x_right;\n    } else {\n        lchild = build_greedy_tree(best.left, x1, y1, x2, best.k, idx);\n        rchild = build_greedy_tree(best.right, x1, best.k, x2, y2, idx);\n        int max_y_bottom = 0, min_y_top = 10000;\n        for (int id : best.left) max_y_bottom = max(max_y_bottom, y[id]);\n        for (int id : best.right) min_y_top = min(min_y_top, y[id]);\n        nodes[idx].min_k = max_y_bottom + 1;\n        nodes[idx].max_k = min_y_top;\n    }\n    nodes[idx].left = lchild;\n    nodes[idx].right = rchild;\n    return idx;\n}\n\nint build_random_tree(const vector<int>& pts, int x1, int y1, int x2, int y2, int parent) {\n    if (pts.size() == 1) {\n        int id = pts[0];\n        nodes.push_back({0, id, 0, -1, -1, parent, 0, 0, 0, 0, 0, 0, 0.0});\n        return (int)nodes.size() - 1;\n    }\n    vector<int> xsorted = pts, ysorted = pts;\n    sort(xsorted.begin(), xsorted.end(), [&](int a, int b) { return x[a] < x[b]; });\n    sort(ysorted.begin(), ysorted.end(), [&](int a, int b) { return y[a] < y[b]; });\n\n    vector<int> v_splits;\n    for (size_t i = 0; i + 1 < xsorted.size(); i++) {\n        if (x[xsorted[i]] + 1 <= x[xsorted[i+1]]) v_splits.push_back(i);\n    }\n    vector<int> h_splits;\n    for (size_t i = 0; i + 1 < ysorted.size(); i++) {\n        if (y[ysorted[i]] + 1 <= y[ysorted[i+1]]) h_splits.push_back(i);\n    }\n    if (v_splits.empty() && h_splits.empty()) {\n        return build_greedy_tree(pts, x1, y1, x2, y2, parent);\n    }\n    int orient, split_idx;\n    if (v_splits.empty()) {\n        orient = 2;\n        split_idx = h_splits[rng.nextInt((int)h_splits.size() - 1)];\n    } else if (h_splits.empty()) {\n        orient = 1;\n        split_idx = v_splits[rng.nextInt((int)v_splits.size() - 1)];\n    } else {\n        if (rng.nextDouble() < 0.5) {\n            orient = 1;\n            split_idx = v_splits[rng.nextInt((int)v_splits.size() - 1)];\n        } else {\n            orient = 2;\n            split_idx = h_splits[rng.nextInt((int)h_splits.size() - 1)];\n        }\n    }\n    vector<int> left_pts, right_pts;\n    int min_k, max_k;\n    if (orient == 1) {\n        left_pts.assign(xsorted.begin(), xsorted.begin() + split_idx + 1);\n        right_pts.assign(xsorted.begin() + split_idx + 1, xsorted.end());\n        min_k = x[xsorted[split_idx]] + 1;\n        max_k = x[xsorted[split_idx+1]];\n    } else {\n        left_pts.assign(ysorted.begin(), ysorted.begin() + split_idx + 1);\n        right_pts.assign(ysorted.begin() + split_idx + 1, ysorted.end());\n        min_k = y[ysorted[split_idx]] + 1;\n        max_k = y[ysorted[split_idx+1]];\n    }\n    int k = min_k + rng.nextInt(max_k - min_k);\n    nodes.push_back({orient, -1, k, -1, -1, parent, min_k, max_k, 0, 0, 0, 0, 0.0});\n    int idx = (int)nodes.size() - 1;\n    int lchild, rchild;\n    if (orient == 1) {\n        lchild = build_random_tree(left_pts, x1, y1, k, y2, idx);\n        rchild = build_random_tree(right_pts, k, y1, x2, y2, idx);\n    } else {\n        lchild = build_random_tree(left_pts, x1, y1, x2, k, idx);\n        rchild = build_random_tree(right_pts, x1, k, x2, y2, idx);\n    }\n    nodes[idx].left = lchild;\n    nodes[idx].right = rchild;\n    return idx;\n}\n\nvector<int> get_internal_nodes() {\n    vector<int> res;\n    function<void(int)> dfs = [&](int u) {\n        if (nodes[u].type != 0) res.push_back(u);\n        if (nodes[u].type != 0) {\n            dfs(nodes[u].left);\n            dfs(nodes[u].right);\n        }\n    };\n    dfs(root);\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n;\n    x.resize(n); y.resize(n); r.resize(n);\n    for (int i = 0; i < n; i++) cin >> x[i] >> y[i] >> r[i];\n\n    double global_best_score = -1e9;\n    vector<Node> best_nodes;\n    int best_root = -1;\n    auto start_time = steady_clock::now();\n    auto time_left = [&]() { return duration<double>(steady_clock::now() - start_time).count() > 4.7; };\n\n    while (!time_left()) {\n        nodes.clear();\n        vector<int> all(n);\n        iota(all.begin(), all.end(), 0);\n        root = build_greedy_tree(all, 0, 0, 10000, 10000, -1);\n        full_eval();\n        double current_score = nodes[root].score;\n\n        double best_restart_score = current_score;\n        vector<Node> best_restart_nodes = nodes;\n        int best_restart_root = root;\n\n        const int max_iter = 200000;\n        const double T_start = 1.0;\n        const double T_end = 1e-6;\n\n        for (int iter = 0; iter < max_iter; iter++) {\n            if (iter % 100 == 0 && time_left()) break;\n\n            double progress = (double)iter / max_iter;\n            double T = T_start * pow(T_end / T_start, progress);\n\n            vector<int> internals = get_internal_nodes();\n            if (internals.empty()) continue;\n\n            int move_type = rng.nextInt(99);\n            if (move_type < 60) {\n                // change cut coordinate\n                int idx = internals[rng.nextInt((int)internals.size() - 1)];\n                if (nodes[idx].min_k == nodes[idx].max_k) continue;\n                int old_k = nodes[idx].k;\n                double old_sub_score = nodes[idx].score;\n                int new_k = nodes[idx].min_k + rng.nextInt(nodes[idx].max_k - nodes[idx].min_k);\n                if (new_k == old_k) continue;\n                nodes[idx].k = new_k;\n                double new_sub_score = eval_subtree(idx);\n                double diff = new_sub_score - old_sub_score;\n                if (diff > 0 || rng.nextDouble() < exp(diff / T)) {\n                    if (abs(diff) > 1e-12) {\n                        int p = nodes[idx].parent;\n                        while (p != -1) { nodes[p].score += diff; p = nodes[p].parent; }\n                    }\n                    current_score += diff;\n                    if (current_score > best_restart_score) {\n                        best_restart_score = current_score;\n                        best_restart_nodes = nodes;\n                        best_restart_root = root;\n                    }\n                } else {\n                    nodes[idx].k = old_k;\n                    eval_subtree(idx);\n                }\n            } else if (move_type < 80) {\n                // reorient (20%)\n                bool accepted = false;\n                for (int attempt = 0; attempt < 5; attempt++) {\n                    int idx = internals[rng.nextInt((int)internals.size() - 1)];\n                    Node saved = nodes[idx];\n                    int sl = nodes[idx].left, sr = nodes[idx].right;\n                    if (!try_reorient(idx)) continue;\n                    double old_sub_score = nodes[idx].score;\n                    double new_sub_score = eval_subtree(idx);\n                    double diff = new_sub_score - old_sub_score;\n                    if (diff > 0 || rng.nextDouble() < exp(diff / T)) {\n                        if (abs(diff) > 1e-12) {\n                            int p = nodes[idx].parent;\n                            while (p != -1) { nodes[p].score += diff; p = nodes[p].parent; }\n                        }\n                        current_score += diff;\n                        if (current_score > best_restart_score) {\n                            best_restart_score = current_score;\n                            best_restart_nodes = nodes;\n                            best_restart_root = root;\n                        }\n                        accepted = true;\n                        break;\n                    } else {\n                        nodes[idx] = saved;\n                        nodes[idx].left = sl; nodes[idx].right = sr;\n                        eval_subtree(idx);\n                    }\n                }\n            } else if (move_type < 85) {\n                // swap children (5%)\n                bool accepted = false;\n                for (int attempt = 0; attempt < 5; attempt++) {\n                    int idx = internals[rng.nextInt((int)internals.size() - 1)];\n                    Node saved = nodes[idx];\n                    int sl = nodes[idx].left, sr = nodes[idx].right;\n                    if (!try_swap_children(idx)) continue;\n                    double old_sub_score = nodes[idx].score;\n                    double new_sub_score = eval_subtree(idx);\n                    double diff = new_sub_score - old_sub_score;\n                    if (diff > 0 || rng.nextDouble() < exp(diff / T)) {\n                        if (abs(diff) > 1e-12) {\n                            int p = nodes[idx].parent;\n                            while (p != -1) { nodes[p].score += diff; p = nodes[p].parent; }\n                        }\n                        current_score += diff;\n                        if (current_score > best_restart_score) {\n                            best_restart_score = current_score;\n                            best_restart_nodes = nodes;\n                            best_restart_root = root;\n                        }\n                        accepted = true;\n                        break;\n                    } else {\n                        nodes[idx] = saved;\n                        nodes[idx].left = sl; nodes[idx].right = sr;\n                        eval_subtree(idx);\n                    }\n                }\n            } else {\n                // local rebuild (15%)\n                int idx = internals[rng.nextInt((int)internals.size() - 1)];\n                Node& nd = nodes[idx];\n                vector<int> leaves;\n                collect_leaves(idx, leaves);\n                int px1 = nd.x1, py1 = nd.y1, px2 = nd.x2, py2 = nd.y2;\n                double old_sub_score = nd.score;\n                int p = nd.parent;\n                bool is_left = (p != -1 && nodes[p].left == idx);\n\n                vector<Node> backup_nodes = nodes;\n                int backup_root = root;\n                double backup_score = current_score;\n\n                int new_subroot;\n                if (rng.nextDouble() < 0.5)\n                    new_subroot = build_greedy_tree(leaves, px1, py1, px2, py2, p);\n                else\n                    new_subroot = build_random_tree(leaves, px1, py1, px2, py2, p);\n                nodes[new_subroot].x1 = px1; nodes[new_subroot].y1 = py1;\n                nodes[new_subroot].x2 = px2; nodes[new_subroot].y2 = py2;\n                if (p != -1) {\n                    if (is_left) nodes[p].left = new_subroot;\n                    else nodes[p].right = new_subroot;\n                } else {\n                    root = new_subroot;\n                }\n                double new_sub_score = eval_subtree(new_subroot);\n                double diff = new_sub_score - old_sub_score;\n                if (abs(diff) > 1e-12) {\n                    int par = p;\n                    while (par != -1) { nodes[par].score += diff; par = nodes[par].parent; }\n                }\n                current_score += diff;\n                if (diff > 0 || rng.nextDouble() < exp(diff / T)) {\n                    if (current_score > best_restart_score) {\n                        best_restart_score = current_score;\n                        best_restart_nodes = nodes;\n                        best_restart_root = root;\n                    }\n                } else {\n                    nodes = move(backup_nodes);\n                    root = backup_root;\n                    current_score = backup_score;\n                }\n            }\n        }\n\n        if (best_restart_score > global_best_score) {\n            global_best_score = best_restart_score;\n            best_nodes = best_restart_nodes;\n            best_root = best_restart_root;\n        }\n    }\n\n    // Final polishing\n    nodes = move(best_nodes);\n    root = best_root;\n    full_eval();\n    vector<int> internals = get_internal_nodes();\n    for (int idx : internals) {\n        if (nodes[idx].min_k >= nodes[idx].max_k) continue;\n        int old_k = nodes[idx].k;\n        double best_local = nodes[root].score;\n        int best_k = old_k;\n        for (int k = nodes[idx].min_k; k <= nodes[idx].max_k; k++) {\n            if (k == old_k) continue;\n            nodes[idx].k = k;\n            full_eval();\n            double sc = nodes[root].score;\n            if (sc > best_local) {\n                best_local = sc;\n                best_k = k;\n            }\n        }\n        if (best_k != old_k) {\n            nodes[idx].k = best_k;\n            full_eval();\n        } else {\n            nodes[idx].k = old_k;\n            full_eval();\n        }\n    }\n\n    // Output\n    full_eval();\n    vector<array<int,4>> ans(n);\n    function<void(int)> collect = [&](int u) {\n        Node& nd = nodes[u];\n        if (nd.type == 0) {\n            ans[nd.leaf_id] = {nd.x1, nd.y1, nd.x2, nd.y2};\n        } else {\n            collect(nd.left);\n            collect(nd.right);\n        }\n    };\n    collect(root);\n    for (auto [a,b,c,d] : ans) cout << a << \" \" << b << \" \" << c << \" \" << d << \"\\n\";\n\n    return 0;\n}","ahc002":"#include <iostream>\n#include <vector>\n#include <bitset>\n#include <algorithm>\n#include <chrono>\n#include <numeric>\n#include <string>\nusing namespace std;\n\nconstexpr int N = 50;\nconstexpr int MAX_TILES = 2500;\n\nstruct State {\n    int parent_id;\n    unsigned char move;   // 0: none, 1:U,2:D,3:L,4:R\n    unsigned short x, y;\n    unsigned short tile;\n    int score;\n    int potential;        // sum of max_p of remaining unvisited tiles\n    bitset<MAX_TILES> visited;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj;\n    cin >> si >> sj;\n\n    vector tile(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> tile[i][j];\n\n    vector p(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> p[i][j];\n\n    int M = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (tile[i][j] > M) M = tile[i][j];\n    M += 1;\n\n    vector<int> max_p(M, 0);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (p[i][j] > max_p[tile[i][j]])\n                max_p[tile[i][j]] = p[i][j];\n\n    long long total_max = 0;\n    for (int v : max_p) total_max += v;\n\n    const int dirs[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};\n    const char move_chars[4] = {'U', 'D', 'L', 'R'};\n\n    int start_tile = tile[si][sj];\n    int start_potential = (int)(total_max - max_p[start_tile]);\n\n    vector<State> states;\n    states.reserve(2000000);\n    State init;\n    init.parent_id = -1;\n    init.move = 0;\n    init.x = (unsigned short)si;\n    init.y = (unsigned short)sj;\n    init.tile = (unsigned short)start_tile;\n    init.score = p[si][sj];\n    init.potential = start_potential;\n    init.visited.reset();\n    init.visited.set(start_tile);\n    states.push_back(init);\n\n    vector<int> cur = {0};\n    int best_id = 0;\n\n    const int BEAM_WIDTH = 300;\n    auto start_time = chrono::steady_clock::now();\n\n    while (!cur.empty()) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - start_time).count() > 1950) break;\n        if (states.size() > 2000000) break;\n\n        vector<int> nxt;\n        nxt.reserve(cur.size() * 4);\n        for (int id : cur) {\n            const State& st = states[id];\n            int x = st.x, y = st.y;\n            for (int d = 0; d < 4; ++d) {\n                int nx = x + dirs[d][0], ny = y + dirs[d][1];\n                if (nx < 0 || nx >= N || ny < 0 || ny >= N) continue;\n                int nxt_tile = tile[nx][ny];\n                if (st.visited[nxt_tile]) continue;   // cannot step on same tile\n                State ns = st;\n                ns.x = (unsigned short)nx;\n                ns.y = (unsigned short)ny;\n                ns.tile = (unsigned short)nxt_tile;\n                ns.score = st.score + p[nx][ny];\n                ns.potential = st.potential - max_p[nxt_tile];\n                ns.visited.set(nxt_tile);\n                ns.parent_id = id;\n                ns.move = (unsigned char)(d + 1);\n                nxt.push_back((int)states.size());\n                states.push_back(move(ns));\n                if (states.back().score > states[best_id].score) {\n                    best_id = (int)states.size() - 1;\n                }\n            }\n        }\n        if (nxt.empty()) break;\n\n        if ((int)nxt.size() > BEAM_WIDTH) {\n            vector<long long> h(nxt.size());\n            for (size_t i = 0; i < nxt.size(); ++i) {\n                const State& s = states[nxt[i]];\n                h[i] = (long long)s.score + s.potential;\n            }\n            vector<int> idx(nxt.size());\n            iota(idx.begin(), idx.end(), 0);\n            sort(idx.begin(), idx.end(), [&](int i, int j) { return h[i] > h[j]; });\n            cur.clear();\n            cur.reserve(BEAM_WIDTH);\n            for (int i = 0; i < BEAM_WIDTH; ++i) {\n                cur.push_back(nxt[idx[i]]);\n            }\n        } else {\n            cur = move(nxt);\n        }\n    }\n\n    // reconstruct path\n    string ans;\n    for (int id = best_id; id > 0; id = states[id].parent_id) {\n        int m = states[id].move - 1;\n        ans.push_back(move_chars[m]);\n    }\n    reverse(ans.begin(), ans.end());\n\n    // verify\n    vector<int> tile_vis(M, 0);\n    int cx = si, cy = sj;\n    int ct = start_tile;\n    tile_vis[ct] = 1;\n    bool ok = true;\n    for (char c : ans) {\n        if (c == 'U') cx--;\n        else if (c == 'D') cx++;\n        else if (c == 'L') cy--;\n        else if (c == 'R') cy++;\n        else { ok = false; break; }\n        if (cx < 0 || cx >= N || cy < 0 || cy >= N) { ok = false; break; }\n        int nt = tile[cx][cy];\n        if (nt == ct) {\n            // step on same tile twice in a row (intra-tile move) -> invalid\n            ok = false; break;\n        }\n        if (tile_vis[nt]) { ok = false; break; }\n        tile_vis[nt] = 1;\n        ct = nt;\n    }\n    if (!ok) {\n        // fallback: empty path (stay at start)\n        ans.clear();\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int N = 30;\nconstexpr int H_EDGES = N * (N - 1);   // 870\nconstexpr int V_EDGES = (N - 1) * N;   // 870\nconstexpr int E = H_EDGES + V_EDGES;   // 1740\n\n// Edge index helpers\ninline int edge_idx_horiz(int i, int j) { return i * (N - 1) + j; }\ninline int edge_idx_vert(int i, int j) { return H_EDGES + i * N + j; }\n\n// Dijkstra with exploration bonus and tiny noise\nstring dijkstra(int si, int sj, int ti, int tj,\n                const vector<double>& w_plan,\n                const vector<int>& cnt,\n                double alpha_explore,\n                mt19937& rng,\n                vector<int>& path_edges) {\n    int start = si * N + sj;\n    int goal = ti * N + tj;\n\n    vector<double> dist(N * N, 1e18);\n    vector<int> parent(N * N, -1);\n    vector<int> parent_edge(N * N, -1);\n    dist[start] = 0;\n\n    using P = pair<double, int>;\n    priority_queue<P, vector<P>, greater<P>> pq;\n    pq.push({0, start});\n\n    uniform_real_distribution<double> noise(-0.5, 0.5);\n\n    static vector<vector<pair<int, int>>> adj;\n    if (adj.empty()) {\n        adj.resize(N * N);\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (j < N - 1) {\n                    int u = i * N + j, v = i * N + j + 1;\n                    int e = edge_idx_horiz(i, j);\n                    adj[u].push_back({v, e});\n                    adj[v].push_back({u, e});\n                }\n                if (i < N - 1) {\n                    int u = i * N + j, v = (i + 1) * N + j;\n                    int e = edge_idx_vert(i, j);\n                    adj[u].push_back({v, e});\n                    adj[v].push_back({u, e});\n                }\n            }\n        }\n    }\n\n    while (!pq.empty()) {\n        auto [d, u] = pq.top(); pq.pop();\n        if (d != dist[u]) continue;\n        if (u == goal) break;\n        for (auto [v, e] : adj[u]) {\n            double w_used = w_plan[e] - alpha_explore / sqrt(cnt[e] + 1.0);\n            if (w_used < 1.0) w_used = 1.0;\n            double nd = d + w_used + noise(rng) * 0.1;\n            if (nd < dist[v]) {\n                dist[v] = nd;\n                parent[v] = u;\n                parent_edge[v] = e;\n                pq.push({nd, v});\n            }\n        }\n    }\n\n    path_edges.clear();\n    vector<int> nodes;\n    for (int cur = goal; cur != start; cur = parent[cur]) {\n        nodes.push_back(cur);\n        path_edges.push_back(parent_edge[cur]);\n    }\n    nodes.push_back(start);\n    reverse(nodes.begin(), nodes.end());\n    reverse(path_edges.begin(), path_edges.end());\n\n    string moves;\n    for (size_t i = 0; i + 1 < nodes.size(); ++i) {\n        int u = nodes[i], v = nodes[i + 1];\n        int ui = u / N, uj = u % N;\n        int vi = v / N, vj = v % N;\n        if (vi == ui - 1) moves += 'U';\n        else if (vi == ui + 1) moves += 'D';\n        else if (vj == uj - 1) moves += 'L';\n        else moves += 'R';\n    }\n    return moves;\n}\n\n// Hard segmentation: replace w with two-constant model if it reduces weighted SSE significantly\nvoid hard_segment_rows(vector<double>& w, const vector<int>& cnt) {\n    for (int i = 0; i < N; ++i) {\n        vector<double> vals(N - 1);\n        vector<double> weight(N - 1);\n        double total_weight = 0.0, total_wsum = 0.0, total_wsum2 = 0.0;\n        for (int j = 0; j < N - 1; ++j) {\n            int e = edge_idx_horiz(i, j);\n            vals[j] = w[e];\n            double wgt = cnt[e] + 1.0;\n            weight[j] = wgt;\n            total_weight += wgt;\n            total_wsum += wgt * vals[j];\n            total_wsum2 += wgt * vals[j] * vals[j];\n        }\n\n        double mean_all = total_wsum / total_weight;\n        double base_sse = total_wsum2 - 2.0 * mean_all * total_wsum + mean_all * mean_all * total_weight;\n        double best_sse = base_sse;\n        int best_x = -1;\n        double best_meanL = mean_all, best_meanR = mean_all;\n\n        double wsum_left = 0.0, wsum2_left = 0.0, wgt_left = 0.0;\n        for (int x = 1; x < N - 1; ++x) {\n            int j = x - 1;\n            double wgt = weight[j];\n            double v = vals[j];\n            wsum_left += wgt * v;\n            wsum2_left += wgt * v * v;\n            wgt_left += wgt;\n\n            double meanL = wsum_left / wgt_left;\n            double wgt_right = total_weight - wgt_left;\n            double wsum_right = total_wsum - wsum_left;\n            double meanR = wsum_right / wgt_right;\n            double wsum2_right = total_wsum2 - wsum2_left;\n\n            double sseL = wsum2_left - 2.0 * meanL * wsum_left + meanL * meanL * wgt_left;\n            double sseR = wsum2_right - 2.0 * meanR * wsum_right + meanR * meanR * wgt_right;\n            double sse = sseL + sseR;\n\n            if (sse < best_sse) {\n                best_sse = sse;\n                best_x = x;\n                best_meanL = meanL;\n                best_meanR = meanR;\n            }\n        }\n\n        if (best_sse < base_sse * 0.95) {\n            for (int j = 0; j < N - 1; ++j) {\n                int e = edge_idx_horiz(i, j);\n                w[e] = (j < best_x) ? best_meanL : best_meanR;\n            }\n        } else {\n            for (int j = 0; j < N - 1; ++j) {\n                int e = edge_idx_horiz(i, j);\n                w[e] = mean_all;\n            }\n        }\n    }\n}\n\nvoid hard_segment_cols(vector<double>& w, const vector<int>& cnt) {\n    for (int j = 0; j < N; ++j) {\n        vector<double> vals(N - 1);\n        vector<double> weight(N - 1);\n        double total_weight = 0.0, total_wsum = 0.0, total_wsum2 = 0.0;\n        for (int i = 0; i < N - 1; ++i) {\n            int e = edge_idx_vert(i, j);\n            vals[i] = w[e];\n            double wgt = cnt[e] + 1.0;\n            weight[i] = wgt;\n            total_weight += wgt;\n            total_wsum += wgt * vals[i];\n            total_wsum2 += wgt * vals[i] * vals[i];\n        }\n\n        double mean_all = total_wsum / total_weight;\n        double base_sse = total_wsum2 - 2.0 * mean_all * total_wsum + mean_all * mean_all * total_weight;\n        double best_sse = base_sse;\n        int best_x = -1;\n        double best_meanL = mean_all, best_meanR = mean_all;\n\n        double wsum_left = 0.0, wsum2_left = 0.0, wgt_left = 0.0;\n        for (int x = 1; x < N - 1; ++x) {\n            int i = x - 1;\n            double wgt = weight[i];\n            double v = vals[i];\n            wsum_left += wgt * v;\n            wsum2_left += wgt * v * v;\n            wgt_left += wgt;\n\n            double meanL = wsum_left / wgt_left;\n            double wgt_right = total_weight - wgt_left;\n            double wsum_right = total_wsum - wsum_left;\n            double meanR = wsum_right / wgt_right;\n            double wsum2_right = total_wsum2 - wsum2_left;\n\n            double sseL = wsum2_left - 2.0 * meanL * wsum_left + meanL * meanL * wgt_left;\n            double sseR = wsum2_right - 2.0 * meanR * wsum_right + meanR * meanR * wgt_right;\n            double sse = sseL + sseR;\n\n            if (sse < best_sse) {\n                best_sse = sse;\n                best_x = x;\n                best_meanL = meanL;\n                best_meanR = meanR;\n            }\n        }\n\n        if (best_sse < base_sse * 0.95) {\n            for (int i = 0; i < N - 1; ++i) {\n                int e = edge_idx_vert(i, j);\n                w[e] = (i < best_x) ? best_meanL : best_meanR;\n            }\n        } else {\n            for (int i = 0; i < N - 1; ++i) {\n                int e = edge_idx_vert(i, j);\n                w[e] = mean_all;\n            }\n        }\n    }\n}\n\n// Soft segmentation: gently pull edges toward inferred block means\nvoid soft_segment_rows(vector<double>& w, const vector<int>& cnt, double lr_soft) {\n    for (int i = 0; i < N; ++i) {\n        int total_cnt = 0;\n        for (int j = 0; j < N - 1; ++j) total_cnt += cnt[edge_idx_horiz(i, j)];\n        if (total_cnt < 10) continue;   // less data -> skip\n\n        vector<double> vals(N - 1);\n        vector<double> weight(N - 1);\n        double total_weight = 0.0, total_wsum = 0.0, total_wsum2 = 0.0;\n        for (int j = 0; j < N - 1; ++j) {\n            int e = edge_idx_horiz(i, j);\n            vals[j] = w[e];\n            double wgt = cnt[e] + 1.0;\n            weight[j] = wgt;\n            total_weight += wgt;\n            total_wsum += wgt * vals[j];\n            total_wsum2 += wgt * vals[j] * vals[j];\n        }\n\n        double mean_all = total_wsum / total_weight;\n        double base_sse = total_wsum2 - 2.0 * mean_all * total_wsum + mean_all * mean_all * total_weight;\n        double best_sse = base_sse;\n        int best_x = -1;\n        double best_meanL = mean_all, best_meanR = mean_all;\n\n        double wsum_left = 0.0, wsum2_left = 0.0, wgt_left = 0.0;\n        for (int x = 1; x < N - 1; ++x) {\n            int j = x - 1;\n            double wgt = weight[j];\n            double v = vals[j];\n            wsum_left += wgt * v;\n            wsum2_left += wgt * v * v;\n            wgt_left += wgt;\n\n            double meanL = wsum_left / wgt_left;\n            double wgt_right = total_weight - wgt_left;\n            double wsum_right = total_wsum - wsum_left;\n            double meanR = wsum_right / wgt_right;\n            double wsum2_right = total_wsum2 - wsum2_left;\n\n            double sseL = wsum2_left - 2.0 * meanL * wsum_left + meanL * meanL * wgt_left;\n            double sseR = wsum2_right - 2.0 * meanR * wsum_right + meanR * meanR * wgt_right;\n            double sse = sseL + sseR;\n\n            if (sse < best_sse) {\n                best_sse = sse;\n                best_x = x;\n                best_meanL = meanL;\n                best_meanR = meanR;\n            }\n        }\n\n        double split_meanL = (best_x == -1) ? mean_all : best_meanL;\n        double split_meanR = (best_x == -1) ? mean_all : best_meanR;\n        int x_split = (best_x == -1) ? N - 1 : best_x;\n\n        for (int j = 0; j < N - 1; ++j) {\n            int e = edge_idx_horiz(i, j);\n            double target = (j < x_split) ? split_meanL : split_meanR;\n            w[e] += lr_soft * (target - w[e]);\n        }\n    }\n}\n\nvoid soft_segment_cols(vector<double>& w, const vector<int>& cnt, double lr_soft) {\n    for (int j = 0; j < N; ++j) {\n        int total_cnt = 0;\n        for (int i = 0; i < N - 1; ++i) total_cnt += cnt[edge_idx_vert(i, j)];\n        if (total_cnt < 10) continue;\n\n        vector<double> vals(N - 1);\n        vector<double> weight(N - 1);\n        double total_weight = 0.0, total_wsum = 0.0, total_wsum2 = 0.0;\n        for (int i = 0; i < N - 1; ++i) {\n            int e = edge_idx_vert(i, j);\n            vals[i] = w[e];\n            double wgt = cnt[e] + 1.0;\n            weight[i] = wgt;\n            total_weight += wgt;\n            total_wsum += wgt * vals[i];\n            total_wsum2 += wgt * vals[i] * vals[i];\n        }\n\n        double mean_all = total_wsum / total_weight;\n        double base_sse = total_wsum2 - 2.0 * mean_all * total_wsum + mean_all * mean_all * total_weight;\n        double best_sse = base_sse;\n        int best_x = -1;\n        double best_meanL = mean_all, best_meanR = mean_all;\n\n        double wsum_left = 0.0, wsum2_left = 0.0, wgt_left = 0.0;\n        for (int x = 1; x < N - 1; ++x) {\n            int i = x - 1;\n            double wgt = weight[i];\n            double v = vals[i];\n            wsum_left += wgt * v;\n            wsum2_left += wgt * v * v;\n            wgt_left += wgt;\n\n            double meanL = wsum_left / wgt_left;\n            double wgt_right = total_weight - wgt_left;\n            double wsum_right = total_wsum - wsum_left;\n            double meanR = wsum_right / wgt_right;\n            double wsum2_right = total_wsum2 - wsum2_left;\n\n            double sseL = wsum2_left - 2.0 * meanL * wsum_left + meanL * meanL * wgt_left;\n            double sseR = wsum2_right - 2.0 * meanR * wsum_right + meanR * meanR * wgt_right;\n            double sse = sseL + sseR;\n\n            if (sse < best_sse) {\n                best_sse = sse;\n                best_x = x;\n                best_meanL = meanL;\n                best_meanR = meanR;\n            }\n        }\n\n        double split_meanL = (best_x == -1) ? mean_all : best_meanL;\n        double split_meanR = (best_x == -1) ? mean_all : best_meanR;\n        int y_split = (best_x == -1) ? N - 1 : best_x;\n\n        for (int i = 0; i < N - 1; ++i) {\n            int e = edge_idx_vert(i, j);\n            double target = (i < y_split) ? split_meanL : split_meanR;\n            w[e] += lr_soft * (target - w[e]);\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    vector<double> w(E, 5000.0);\n    vector<double> w_plan = w;\n    vector<int> cnt(E, 0);\n\n    mt19937 rng(12345);\n\n    double alpha_explore = 2000.0;\n    double base_lr = 1200.0;            // slightly increased\n    double lr_decay_factor = 0.005;\n\n    auto clamp_w = [](double v) { return max(1000.0, min(9000.0, v)); };\n\n    for (int k = 0; k < 1000; ++k) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n\n        vector<int> path_edges;\n        string moves = dijkstra(si, sj, ti, tj, w_plan, cnt, alpha_explore, rng, path_edges);\n        cout << moves << endl;   // flush\n\n        int obs;\n        cin >> obs;\n\n        double pred = 0;\n        for (int e : path_edges) pred += w[e];\n\n        double grad = pred - obs;\n        double lr_decay = 1.0 / (1.0 + k * lr_decay_factor);\n        double lr_abs = base_lr / (pred + 1.0) * lr_decay;\n\n        // Pure gradient update, no explicit regularization\n        for (int e : path_edges) {\n            w[e] -= lr_abs * grad;\n            w[e] = clamp_w(w[e]);\n            cnt[e]++;\n        }\n\n        // Soft segmentation (structural prior)\n        if (k >= 15) {\n            double lr_soft = min(0.2, 0.0012 * (k - 15));   // ramp up quicker\n            soft_segment_rows(w, cnt, lr_soft);\n            soft_segment_cols(w, cnt, lr_soft);\n            for (int e = 0; e < E; ++e) w[e] = clamp_w(w[e]);\n        }\n\n        // Dynamically increase smoothness of planning weights\n        double rho = min(0.3, 0.02 + k / 3000.0);  // more aggressive later\n        for (int e = 0; e < E; ++e)\n            w_plan[e] = (1 - rho) * w_plan[e] + rho * w[e];\n\n        // Exploration decay\n        alpha_explore = max(0.0, alpha_explore - 1.8);   // keep positive for longer\n\n        // Periodic hard reset using the estimated segment structure\n        if ((k + 1) % 50 == 0 && k >= 49) {\n            hard_segment_rows(w, cnt);\n            hard_segment_cols(w, cnt);\n            for (int e = 0; e < E; ++e) {\n                w[e] = clamp_w(w[e]);\n                w_plan[e] = w[e];   // fully adopt the cleaned model\n            }\n        }\n    }\n\n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n#include <cstring>\n#include <chrono>\n#include <cstdint>\n\nusing namespace std;\nusing namespace std::chrono;\n\nconstexpr int N = 20;               // grid size\nconstexpr int LETTERS = 8;\nconst char letters[LETTERS] = {'A','B','C','D','E','F','G','H'};\n\n// ---- random number generator ----\nstruct XorShift {\n    uint32_t x;\n    XorShift(uint32_t seed) : x(seed) {}\n    uint32_t next() {\n        x ^= x << 13;\n        x ^= x >> 17;\n        x ^= x << 5;\n        return x;\n    }\n    int nextInt(int max) {        // [0, max)\n        return next() % max;\n    }\n    double nextDouble() {         // [0, 1)\n        return (next() >> 8) * 0x1p-24;\n    }\n};\n\n// ---- global problem data ----\nint M;\nvector<string> strs;\nvector<int> len;\n\n// ---- incremental match structures ----\nvector<int> h_match;   // [i*N*N + r*N + start]\nvector<int> v_match;   // [i*N*N + c*N + start]\nvector<int> h_count;   // [i*N + r]   how many starts in row r give full match\nvector<int> v_count;   // [i*N + c]\nvector<int> s_count;   // [i]         number of occurrences of string i in grid\nint c_total = 0;       // number of fully matched strings\nint d_total = 0;       // number of '.' cells\nchar grid[N][N];\n\n// ---- unmatched string management ----\nvector<bool> matched;         // matched[i] = (s_count[i] > 0)\nvector<int> um;               // list of unmatched indices\nvector<int> um_pos;           // position in um for each i, -1 if matched\n\nvoid add_unmatched(int i) {\n    if (!matched[i]) return;   // already unmatched\n    matched[i] = false;\n    um_pos[i] = (int)um.size();\n    um.push_back(i);\n}\nvoid remove_unmatched(int i) {\n    if (matched[i]) return;    // already matched\n    matched[i] = true;\n    int pos = um_pos[i];\n    int last = um.back();\n    um[pos] = last;\n    um_pos[last] = pos;\n    um.pop_back();\n}\n\n// ---- rebuild all incremental structures from scratch ----\nvoid rebuild_all() {\n    h_match.assign(M * N * N, 0);\n    v_match.assign(M * N * N, 0);\n    h_count.assign(M * N, 0);\n    v_count.assign(M * N, 0);\n    s_count.assign(M, 0);\n    c_total = 0;\n    d_total = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (grid[i][j] == '.') ++d_total;\n\n    for (int i = 0; i < M; ++i) {\n        int L = len[i];\n        const string& s = strs[i];\n        // horizontal\n        for (int r = 0; r < N; ++r) {\n            for (int start = 0; start < N; ++start) {\n                int cnt = 0;\n                for (int pos = 0; pos < L; ++pos)\n                    if (grid[r][(start+pos)%N] == s[pos]) ++cnt;\n                h_match[i*N*N + r*N + start] = cnt;\n                if (cnt == L) {\n                    ++h_count[i*N + r];\n                    ++s_count[i];\n                }\n            }\n        }\n        // vertical\n        for (int c = 0; c < N; ++c) {\n            for (int start = 0; start < N; ++start) {\n                int cnt = 0;\n                for (int pos = 0; pos < L; ++pos)\n                    if (grid[(start+pos)%N][c] == s[pos]) ++cnt;\n                v_match[i*N*N + c*N + start] = cnt;\n                if (cnt == L) {\n                    ++v_count[i*N + c];\n                    ++s_count[i];\n                }\n            }\n        }\n        if (s_count[i] > 0) ++c_total;\n    }\n\n    // rebuild unmatched list\n    matched.assign(M, false);\n    um.clear();\n    um_pos.assign(M, -1);\n    for (int i = 0; i < M; ++i) {\n        if (s_count[i] > 0) {\n            matched[i] = true;\n        } else {\n            matched[i] = false;\n            um_pos[i] = (int)um.size();\n            um.push_back(i);\n        }\n    }\n}\n\n// ---- change one cell, update all incremental data ----\nvoid set_cell(int r, int c, char nc) {\n    char oc = grid[r][c];\n    if (oc == nc) return;\n\n    // dots counter\n    if (oc == '.') --d_total;\n    if (nc == '.') ++d_total;\n\n    for (int i = 0; i < M; ++i) {\n        int L = len[i];\n        const string& s = strs[i];\n\n        // ----- horizontal -----\n        int h_base = i * N * N + r * N;\n        int h_cnt_base = i * N + r;\n        for (int off = 0; off < L; ++off) {\n            int start = (c - off + N) % N;\n            int idx = h_base + start;\n            bool oc_eq = (oc == s[off]);\n            bool nc_eq = (nc == s[off]);\n            if (oc_eq == nc_eq) continue;\n            if (oc_eq) {\n                --h_match[idx];\n                if (h_match[idx] == L - 1) {\n                    --h_count[h_cnt_base];\n                    --s_count[i];\n                    if (s_count[i] == 0) {\n                        --c_total;\n                        add_unmatched(i);\n                    }\n                }\n            } else {\n                ++h_match[idx];\n                if (h_match[idx] == L) {\n                    ++h_count[h_cnt_base];\n                    ++s_count[i];\n                    if (s_count[i] == 1) {\n                        ++c_total;\n                        remove_unmatched(i);\n                    }\n                }\n            }\n        }\n\n        // ----- vertical -----\n        int v_base = i * N * N + c * N;\n        int v_cnt_base = i * N + c;\n        for (int off = 0; off < L; ++off) {\n            int start = (r - off + N) % N;\n            int idx = v_base + start;\n            bool oc_eq = (oc == s[off]);\n            bool nc_eq = (nc == s[off]);\n            if (oc_eq == nc_eq) continue;\n            if (oc_eq) {\n                --v_match[idx];\n                if (v_match[idx] == L - 1) {\n                    --v_count[v_cnt_base];\n                    --s_count[i];\n                    if (s_count[i] == 0) {\n                        --c_total;\n                        add_unmatched(i);\n                    }\n                }\n            } else {\n                ++v_match[idx];\n                if (v_match[idx] == L) {\n                    ++v_count[v_cnt_base];\n                    ++s_count[i];\n                    if (s_count[i] == 1) {\n                        ++c_total;\n                        remove_unmatched(i);\n                    }\n                }\n            }\n        }\n    }\n    grid[r][c] = nc;\n}\n\n// ---- brute force count of matched strings (used during greedy) ----\nint count_matched(const char g[N][N]) {\n    int cnt = 0;\n    for (int i = 0; i < M; ++i) {\n        const string& s = strs[i];\n        int L = len[i];\n        bool found = false;\n        for (int r = 0; r < N && !found; ++r) {\n            for (int start = 0; start < N && !found; ++start) {\n                bool ok = true;\n                for (int pos = 0; pos < L; ++pos)\n                    if (g[r][(start+pos)%N] != s[pos]) { ok = false; break; }\n                if (ok) found = true;\n            }\n        }\n        for (int c = 0; c < N && !found; ++c) {\n            for (int start = 0; start < N && !found; ++start) {\n                bool ok = true;\n                for (int pos = 0; pos < L; ++pos)\n                    if (g[(start+pos)%N][c] != s[pos]) { ok = false; break; }\n                if (ok) found = true;\n            }\n        }\n        if (found) ++cnt;\n    }\n    return cnt;\n}\n\n// ---- greedy construction with random orders ----\nvoid greedy_construction(char best_grid[N][N], int& best_c, XorShift& rng,\n                         double time_limit, steady_clock::time_point start_time) {\n    auto get_time = [&]() {\n        return duration<double>(steady_clock::now() - start_time).count();\n    };\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n\n    char cur[N][N];\n    best_c = -1;\n    int best_d = 0;\n\n    struct Placement {\n        int ori;      // 0 horizontal, 1 vertical\n        int rc;       // row or column index\n        int start;\n        int overlap;\n    };\n    vector<Placement> valid;\n    valid.reserve(800);\n\n    while (get_time() < time_limit) {\n        memset(cur, '.', sizeof(cur));\n        for (int i = M-1; i > 0; --i) swap(order[i], order[rng.nextInt(i+1)]);\n\n        for (int idx : order) {\n            const string& s = strs[idx];\n            int L = len[idx];\n            valid.clear();\n\n            // horizontal\n            for (int r = 0; r < N; ++r) {\n                for (int start = 0; start < N; ++start) {\n                    int overlap = 0;\n                    bool ok = true;\n                    for (int pos = 0; pos < L; ++pos) {\n                        int col = (start + pos) % N;\n                        char cell = cur[r][col];\n                        if (cell != '.' && cell != s[pos]) { ok = false; break; }\n                        if (cell != '.') ++overlap;\n                    }\n                    if (ok) valid.push_back({0, r, start, overlap});\n                }\n            }\n            // vertical\n            for (int c = 0; c < N; ++c) {\n                for (int start = 0; start < N; ++start) {\n                    int overlap = 0;\n                    bool ok = true;\n                    for (int pos = 0; pos < L; ++pos) {\n                        int row = (start + pos) % N;\n                        char cell = cur[row][c];\n                        if (cell != '.' && cell != s[pos]) { ok = false; break; }\n                        if (cell != '.') ++overlap;\n                    }\n                    if (ok) valid.push_back({1, c, start, overlap});\n                }\n            }\n\n            if (valid.empty()) continue;\n            int max_overlap = -1;\n            for (auto& p : valid) if (p.overlap > max_overlap) max_overlap = p.overlap;\n            vector<Placement*> candidates;\n            for (auto& p : valid) if (p.overlap == max_overlap) candidates.push_back(&p);\n            Placement& chosen = *candidates[rng.nextInt(candidates.size())];\n\n            if (chosen.ori == 0) {\n                int r = chosen.rc, st = chosen.start;\n                for (int pos = 0; pos < L; ++pos) cur[r][(st+pos)%N] = s[pos];\n            } else {\n                int c = chosen.rc, st = chosen.start;\n                for (int pos = 0; pos < L; ++pos) cur[(st+pos)%N][c] = s[pos];\n            }\n        }\n\n        int actual_c = count_matched(cur);\n        int actual_d = 0;\n        for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) if (cur[i][j] == '.') ++actual_d;\n        if (actual_c > best_c || (actual_c == best_c && actual_d > best_d)) {\n            best_c = actual_c;\n            best_d = actual_d;\n            memcpy(best_grid, cur, sizeof(cur));\n            if (best_c == M) break;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false); cin.tie(0);\n    auto start_time = steady_clock::now();\n    auto get_time = [&]() {\n        return duration<double>(steady_clock::now() - start_time).count();\n    };\n\n    // ----- read input -----\n    int dummy_n;\n    cin >> dummy_n >> M;\n    strs.resize(M);\n    len.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> strs[i];\n        len[i] = strs[i].size();\n    }\n\n    // ----- random generator -----\n    auto seed = steady_clock::now().time_since_epoch().count();\n    XorShift rng((uint32_t)(seed & 0xFFFFFFFF));\n\n    // ----- greedy phase -----\n    double greedy_time = 0.35;\n    char best_grid[N][N];\n    int greedy_c;\n    greedy_construction(best_grid, greedy_c, rng, greedy_time, start_time);\n\n    // ----- prepare for SA -----\n    memcpy(grid, best_grid, sizeof(grid));\n    // fill '.' with random letters to start SA from a non\u2011dot grid\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (grid[i][j] == '.')\n                grid[i][j] = letters[rng.nextInt(LETTERS)];\n\n    rebuild_all();\n\n    char best_sa_grid[N][N];\n    memcpy(best_sa_grid, grid, sizeof(grid));\n    int best_c = c_total;\n    int best_d = d_total;\n    // energy function: if c<M then c, else M + (N*N - d)/(N*N)\n    auto energy = [&](int c, int d) {\n        if (c < M) return (double)c;\n        return (double)M + (double)(N*N - d) / (N*N);\n    };\n    double cur_energy = energy(c_total, d_total);\n    double best_energy = cur_energy;\n\n    // ----- simulated annealing -----\n    double sa_start = get_time();\n    double sa_limit = 2.80;               // leave room for dot optimisation\n    double T_start = 0.4;\n    double T_end   = 0.0001;\n\n    while (get_time() < sa_limit) {\n        double elapsed = get_time() - sa_start;\n        double progress = min(elapsed / (sa_limit - sa_start), 1.0);\n        double T = T_start * pow(T_end / T_start, progress);\n\n        // occasionally use a targeted move for unmatched strings\n        if (!um.empty() && rng.nextDouble() < 0.3) {\n            // pick a random unmatched string\n            int i = um[rng.nextInt((int)um.size())];\n            int L = len[i];\n            const string& s = strs[i];\n            bool horiz = rng.nextInt(2);\n            int rc = rng.nextInt(N);\n            int start = rng.nextInt(N);\n            int off = rng.nextInt(L);\n            int r, c;\n            if (horiz) { r = rc; c = (start + off) % N; }\n            else       { r = (start + off) % N; c = rc; }\n            char desired = s[off];\n            if (grid[r][c] == desired) continue;   // nothing to do\n            char old_char = grid[r][c];\n            double old_energy = cur_energy;\n            set_cell(r, c, desired);\n            double new_energy = energy(c_total, d_total);\n            double delta = new_energy - old_energy;\n\n            if (delta >= 0) {\n                cur_energy = new_energy;\n                if (new_energy > best_energy) {\n                    best_energy = new_energy;\n                    best_c = c_total;\n                    best_d = d_total;\n                    memcpy(best_sa_grid, grid, sizeof(grid));\n                }\n            } else {\n                double prob = exp(delta / T);\n                if (rng.nextDouble() < prob) {\n                    cur_energy = new_energy;\n                } else {\n                    set_cell(r, c, old_char);\n                }\n            }\n        } else {\n            // single cell flip\n            int r = rng.nextInt(N);\n            int c = rng.nextInt(N);\n            char cur_char = grid[r][c];\n            char nxt_char;\n            if (rng.nextInt(9) == 0) nxt_char = '.';\n            else nxt_char = letters[rng.nextInt(LETTERS)];\n            if (nxt_char == cur_char) continue;\n\n            double old_energy = cur_energy;\n            set_cell(r, c, nxt_char);\n            double new_energy = energy(c_total, d_total);\n            double delta = new_energy - old_energy;\n\n            if (delta >= 0) {\n                cur_energy = new_energy;\n                if (new_energy > best_energy) {\n                    best_energy = new_energy;\n                    best_c = c_total;\n                    best_d = d_total;\n                    memcpy(best_sa_grid, grid, sizeof(grid));\n                }\n            } else {\n                double prob = exp(delta / T);\n                if (rng.nextDouble() < prob) {\n                    cur_energy = new_energy;\n                } else {\n                    set_cell(r, c, cur_char);\n                }\n            }\n        }\n        if (c_total == M) break;   // all matched, stop SA\n    }\n\n    // restore best found state\n    memcpy(grid, best_sa_grid, sizeof(grid));\n    rebuild_all();\n\n    // ----- final dot maximisation (only when all strings are matched) -----\n    if (c_total == M) {\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    if (grid[r][c] == '.') continue;\n                    char old = grid[r][c];\n                    set_cell(r, c, '.');\n                    if (c_total == M) {\n                        changed = true;\n                    } else {\n                        set_cell(r, c, old);\n                    }\n                }\n            }\n        }\n        memcpy(best_sa_grid, grid, sizeof(grid));\n    }\n\n    // ----- output -----\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) cout << best_sa_grid[i][j];\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int INF = 1e9;\n\n// Dial's algorithm for directed graph with small integer weights (5..9)\nvoid dial(const vector<vector<pair<int, int>>> &adj, int src,\n          vector<int> &dist, vector<int> &prev) {\n    int n = (int)adj.size();\n    dist.assign(n, INF);\n    prev.assign(n, -1);\n    dist[src] = 0;\n    vector<queue<int>> buckets(10);\n    buckets[0].push(src);\n    int cur_d = 0, max_d = 0;\n    while (cur_d <= max_d) {\n        int idx = cur_d % 10;\n        if (!buckets[idx].empty()) {\n            int u = buckets[idx].front();\n            buckets[idx].pop();\n            if (dist[u] < cur_d) continue;\n            for (auto &p : adj[u]) {\n                int v = p.first, w = p.second;\n                int nd = cur_d + w;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    prev[v] = u;\n                    buckets[nd % 10].push(v);\n                    if (nd > max_d) max_d = nd;\n                }\n            }\n        } else {\n            cur_d++;\n        }\n    }\n}\n\nint main() {\n    // Start timing\n    auto start_time = chrono::steady_clock::now();\n    auto time_limit = 2.9; // seconds\n\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int N, si, sj;\n    cin >> N >> si >> sj;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n\n    // map cells to IDs\n    vector<vector<int>> id(N, vector<int>(N, -1));\n    vector<pair<int, int>> cells;\n    vector<int> cell_cost;\n    int r = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (grid[i][j] != '#') {\n                id[i][j] = r++;\n                cells.push_back({i, j});\n                cell_cost.push_back(grid[i][j] - '0');\n            }\n\n    // adjacency (directed, cost = weight of target cell)\n    vector<vector<pair<int, int>>> adj(r);\n    const int di[4] = {-1, 1, 0, 0};\n    const int dj[4] = {0, 0, -1, 1};\n    for (int u = 0; u < r; ++u) {\n        int i = cells[u].first, j = cells[u].second;\n        for (int d = 0; d < 4; ++d) {\n            int ni = i + di[d], nj = j + dj[d];\n            if (ni >= 0 && ni < N && nj >= 0 && nj < N && id[ni][nj] != -1) {\n                int v = id[ni][nj];\n                adj[u].push_back({v, cell_cost[v]});\n            }\n        }\n    }\n\n    // horizontal segments\n    vector<int> h_id(r, -1);\n    vector<vector<int>> h_seg;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N;) {\n            if (id[i][j] != -1) {\n                int st = j;\n                while (j < N && id[i][j] != -1) ++j;\n                int en = j - 1;\n                vector<int> seg;\n                for (int jj = st; jj <= en; ++jj) seg.push_back(id[i][jj]);\n                for (int u : seg) h_id[u] = (int)h_seg.size();\n                h_seg.push_back(seg);\n            } else {\n                ++j;\n            }\n        }\n    }\n    int H = (int)h_seg.size();\n\n    // vertical segments\n    vector<int> v_id(r, -1);\n    vector<vector<int>> v_seg;\n    for (int j = 0; j < N; ++j) {\n        for (int i = 0; i < N;) {\n            if (id[i][j] != -1) {\n                int st = i;\n                while (i < N && id[i][j] != -1) ++i;\n                int en = i - 1;\n                vector<int> seg;\n                for (int ii = st; ii <= en; ++ii) seg.push_back(id[ii][j]);\n                for (int u : seg) v_id[u] = (int)v_seg.size();\n                v_seg.push_back(seg);\n            } else {\n                ++i;\n            }\n        }\n    }\n    int V = (int)v_seg.size();\n    int S = H + V; // total segments\n\n    // Candidate waypoints: start + both ends + middle of every segment\n    int start_cell = id[si][sj];\n    vector<int> P;\n    P.push_back(start_cell);\n    set<int> seen;\n    seen.insert(start_cell);\n    for (auto &seg : h_seg) {\n        for (int u : {seg.front(), seg.back(), seg[seg.size() / 2]}) {\n            if (seen.insert(u).second) P.push_back(u);\n        }\n    }\n    for (auto &seg : v_seg) {\n        for (int u : {seg.front(), seg.back(), seg[seg.size() / 2]}) {\n            if (seen.insert(u).second) P.push_back(u);\n        }\n    }\n    int Psz = (int)P.size();\n\n    // segment coverage of each candidate\n    vector<array<int, 2>> seg_cover(Psz);\n    for (int i = 0; i < Psz; ++i) {\n        int u = P[i];\n        // if cell is not in a segment, h_id or v_id could be -1, treat as no segment\n        seg_cover[i] = {h_id[u], v_id[u]};\n    }\n\n    // distance from start (tie-breaker for set cover)\n    vector<int> dist_start, prv_dummy;\n    dial(adj, start_cell, dist_start, prv_dummy);\n\n    int start_idx = find(P.begin(), P.end(), start_cell) - P.begin();\n\n    vector<bool> cov_seg(S, false);\n    if (h_id[start_cell] != -1) cov_seg[h_id[start_cell]] = true;\n    if (v_id[start_cell] != -1) cov_seg[H + v_id[start_cell]] = true;\n    int uncovered = 0;\n    for (bool b : cov_seg) if (!b) ++uncovered;\n\n    vector<int> selected;\n    vector<bool> in_sel(Psz, false);\n    selected.push_back(start_idx);\n    in_sel[start_idx] = true;\n\n    // greedy set cover (prefer closer cells)\n    while (uncovered > 0) {\n        int best_gain = 0, best_idx = -1, best_dist = INF;\n        for (int i = 0; i < Psz; ++i) {\n            if (in_sel[i]) continue;\n            int gain = 0;\n            for (int seg : seg_cover[i])\n                if (seg != -1 && !cov_seg[seg]) ++gain;\n            if (gain == 0) continue;\n            int d = dist_start[P[i]];\n            if (gain > best_gain || (gain == best_gain && d < best_dist)) {\n                best_gain = gain;\n                best_dist = d;\n                best_idx = i;\n            }\n        }\n        if (best_idx == -1) break;\n        selected.push_back(best_idx);\n        in_sel[best_idx] = true;\n        for (int seg : seg_cover[best_idx]) {\n            if (seg != -1 && !cov_seg[seg]) {\n                cov_seg[seg] = true;\n                --uncovered;\n            }\n        }\n    }\n\n    // prune redundant waypoints (local coverage)\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        for (size_t i = 0; i < selected.size(); ++i) {\n            if (selected[i] == start_idx) continue;\n            vector<bool> cov(S, false);\n            for (size_t j = 0; j < selected.size(); ++j)\n                if (i != j)\n                    for (int seg : seg_cover[selected[j]])\n                        if (seg != -1) cov[seg] = true;\n            bool needed = false;\n            for (int seg : seg_cover[selected[i]])\n                if (seg != -1 && !cov[seg]) { needed = true; break; }\n            if (!needed) {\n                selected.erase(selected.begin() + i);\n                changed = true;\n                break;\n            }\n        }\n    }\n\n    vector<int> W;\n    for (int idx : selected) W.push_back(P[idx]);\n    int K = (int)W.size();\n\n    auto it_start = find(W.begin(), W.end(), start_cell);\n    if (it_start != W.end()) swap(W[0], *it_start);\n\n    if (K == 1) {\n        cout << \"\" << \"\\n\";\n        return 0;\n    }\n\n    // all-pairs distances between waypoints\n    vector<vector<int>> D(K, vector<int>(K, 0));\n    for (int i = 0; i < K; ++i) {\n        vector<int> dist, prv;\n        dial(adj, W[i], dist, prv);\n        for (int j = 0; j < K; ++j) D[i][j] = dist[W[j]];\n    }\n\n    // initial tour: cheapest insertion\n    vector<int> tour(K);\n    vector<bool> in_tour(K, false);\n    tour[0] = 0;\n    in_tour[0] = true;\n    for (int t = 1; t < K; ++t) {\n        int best_node = -1, best_pos = -1, best_inc = INF;\n        for (int v = 1; v < K; ++v) {\n            if (in_tour[v]) continue;\n            for (int i = 0; i < t; ++i) {\n                int u = tour[i];\n                int w = tour[(i + 1) % t];\n                int inc = D[u][v] + D[v][w] - D[u][w];\n                if (inc < best_inc) {\n                    best_inc = inc;\n                    best_node = v;\n                    best_pos = i + 1;\n                }\n            }\n        }\n        for (int i = t; i > best_pos; --i) tour[i] = tour[i - 1];\n        tour[best_pos] = best_node;\n        in_tour[best_node] = true;\n    }\n\n    // improve via Or-opt (relocation)\n    {\n        auto calc_cost = [&](const vector<int> &tr) {\n            int sum = 0;\n            for (int i = 0; i < K; ++i) sum += D[tr[i]][tr[(i + 1) % K]];\n            return sum;\n        };\n        int cur_cost = calc_cost(tour);\n        while (true) {\n            // check time\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            int best_delta = 0, best_i = -1, best_j = -1;\n            for (int i = 1; i < K; ++i) {\n                int prev = (i - 1 + K) % K;\n                int next = (i + 1) % K;\n                int node = tour[i];\n                for (int j = 0; j < K; ++j) {\n                    if (j == i || j == i - 1) continue;\n                    int nextj = (j + 1) % K;\n                    int delta =\n                        -D[tour[prev]][node] - D[node][tour[next]] - D[tour[j]][tour[nextj]]\n                        + D[tour[prev]][tour[next]] + D[tour[j]][node] + D[node][tour[nextj]];\n                    if (delta < best_delta) {\n                        best_delta = delta;\n                        best_i = i;\n                        best_j = j;\n                    }\n                }\n            }\n            if (best_delta >= 0) break;\n            int node = tour[best_i];\n            if (best_j > best_i) {\n                tour.erase(tour.begin() + best_i);\n                tour.insert(tour.begin() + best_j, node);\n            } else {\n                tour.erase(tour.begin() + best_i);\n                tour.insert(tour.begin() + best_j + 1, node);\n            }\n            cur_cost += best_delta;\n        }\n    }\n\n    // 2-opt edge exchange (segment reversal) \u2013 cheap and can improve further\n    {\n        auto calc_cost = [&](const vector<int> &tr) {\n            int sum = 0;\n            for (int i = 0; i < K; ++i) sum += D[tr[i]][tr[(i + 1) % K]];\n            return sum;\n        };\n        int cur_cost = calc_cost(tour);\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            for (int i = 0; i < K; ++i) {\n                for (int j = i + 2; j < K; ++j) {\n                    if (i == 0 && j == K - 1) continue;   // not full reversal\n                    int u1 = tour[i], u2 = tour[(i + 1) % K];\n                    int v1 = tour[j], v2 = tour[(j + 1) % K];\n                    int delta = -D[u1][u2] - D[v1][v2] + D[u1][v1] + D[u2][v2];\n                    if (delta < 0) {\n                        // reverse segment i+1 .. j\n                        reverse(tour.begin() + i + 1, tour.begin() + j + 1);\n                        cur_cost += delta;\n                        improved = true;\n                        // restart loops\n                        goto two_opt_restart;\n                    }\n                }\n            }\n            two_opt_restart:;\n        }\n    }\n\n    // produce final output string\n    string ans;\n    ans.reserve(1'000'000);\n    for (int step = 0; step < K; ++step) {\n        int u = W[tour[step]];\n        int v = W[tour[(step + 1) % K]];\n        vector<int> dist, prv;\n        dial(adj, u, dist, prv);\n        vector<int> path;\n        for (int cur = v; cur != u; cur = prv[cur]) path.push_back(cur);\n        path.push_back(u);\n        reverse(path.begin(), path.end());\n        for (size_t k = 0; k + 1 < path.size(); ++k) {\n            int ci = cells[path[k]].first, cj = cells[path[k]].second;\n            int ni = cells[path[k + 1]].first, nj = cells[path[k + 1]].second;\n            if (ni < ci) ans.push_back('U');\n            else if (ni > ci) ans.push_back('D');\n            else if (nj < cj) ans.push_back('L');\n            else ans.push_back('R');\n        }\n    }\n\n    cout << ans << \"\\n\";\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <set>\n#include <climits>\n#include <cmath>\nusing namespace std;\n\nstruct Obs {\n    int task;\n    int L;\n    int U;\n};\n\nint N, M, K, R;\nvector<vector<int>> d;           // task difficulties\nvector<vector<int>> out_edges;   // dependents of each task\nvector<int> indegree;            // original indegree\nvector<int> height;              // longest path to sink (including itself)\nint max_height;\n\nvector<int> task_status;         // 0: not started, 1: in progress, 2: completed\nvector<int> req_remaining;       // number of unfinished prerequisites\nvector<int> worker_task;         // which task worker is doing (-1 = free)\nvector<int> worker_start;        // day the worker started current task\nvector<vector<Obs>> obs;         // observations per worker\nvector<vector<int>> LB, UB;      // skill bounds per worker\n\n// update skill bounds for worker j using all observations\nvoid update_bounds(int j) {\n    vector<int> &lb = LB[j];\n    vector<int> &ub = UB[j];\n    fill(lb.begin(), lb.end(), 0);\n    fill(ub.begin(), ub.end(), 200);\n\n    bool changed = true;\n    int iter = 0;\n    while (changed && iter < 10) {\n        changed = false;\n        iter++;\n        for (const auto &ob : obs[j]) {\n            int ti = ob.task;\n            int L = ob.L;\n            int U = ob.U;\n            // Update lower bounds using upper bound U\n            for (int k = 0; k < K; k++) {\n                int new_lb = max(lb[k], d[ti][k] - U);\n                if (new_lb > ub[k]) new_lb = ub[k]; // keep consistent\n                if (new_lb > lb[k]) {\n                    lb[k] = new_lb;\n                    changed = true;\n                }\n            }\n            // Precompute S_others_max (max possible deficit from other skills)\n            vector<int> S_others_max(K, 0);\n            for (int k = 0; k < K; k++) {\n                int sum = 0;\n                for (int k2 = 0; k2 < K; k2++) {\n                    if (k2 == k) continue;\n                    sum += max(0, d[ti][k2] - lb[k2]);\n                }\n                S_others_max[k] = sum;\n            }\n            // Update upper bounds using lower bound L\n            for (int k = 0; k < K; k++) {\n                if (L > S_others_max[k]) {\n                    int new_ub = d[ti][k] - (L - S_others_max[k]);\n                    if (new_ub < lb[k]) new_ub = lb[k]; // keep consistent\n                    if (new_ub < ub[k]) {\n                        ub[k] = new_ub;\n                        changed = true;\n                    }\n                }\n            }\n        }\n    }\n}\n\n// estimate days needed for worker w to finish task idx\nint estimate_t(int worker, int task) {\n    double r = 0.0;\n    if (max_height > 1) {\n        r = (double)(height[task] - 1) / (max_height - 1);\n    }\n    int w_val = 0;\n    for (int k = 0; k < K; k++) {\n        double s_blend = LB[worker][k] + (UB[worker][k] - LB[worker][k]) * (1.0 - r);\n        int s_int = (int)round(s_blend);\n        int def = d[task][k] - s_int;\n        if (def > 0) w_val += def;\n    }\n    return (w_val == 0) ? 1 : w_val;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> M >> K >> R;\n    d.resize(N, vector<int>(K));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < K; j++) {\n            cin >> d[i][j];\n        }\n    }\n    out_edges.resize(N);\n    indegree.assign(N, 0);\n    for (int i = 0; i < R; i++) {\n        int u, v;\n        cin >> u >> v;\n        u--; v--;\n        out_edges[u].push_back(v);\n        indegree[v]++;\n    }\n    \n    // Compute height = length of longest path to a sink (inclusive)\n    height.resize(N);\n    max_height = 0;\n    for (int i = N - 1; i >= 0; i--) {\n        int best = 0;\n        for (int v : out_edges[i]) {\n            best = max(best, height[v]);\n        }\n        height[i] = best + 1;\n        max_height = max(max_height, height[i]);\n    }\n    \n    // Initialize state\n    task_status.assign(N, 0);\n    req_remaining = indegree;\n    worker_task.assign(M, -1);\n    worker_start.assign(M, -1);\n    obs.resize(M);\n    LB.assign(M, vector<int>(K, 0));\n    UB.assign(M, vector<int>(K, 200));\n    \n    int day = 1;\n    int completed = 0;\n    \n    while (true) {\n        vector<int> free_workers;\n        for (int j = 0; j < M; j++) {\n            if (worker_task[j] == -1) free_workers.push_back(j);\n        }\n        vector<int> ready_tasks;\n        for (int i = 0; i < N; i++) {\n            if (task_status[i] == 0 && req_remaining[i] == 0) {\n                ready_tasks.push_back(i);\n            }\n        }\n        \n        // Sort by height descending (critical first)\n        sort(ready_tasks.begin(), ready_tasks.end(), [&](int a, int b) {\n            return height[a] > height[b];\n        });\n        \n        // Only consider a limited number of highest priority tasks\n        int max_consider = max((int)free_workers.size() * 3, 40);\n        if ((int)ready_tasks.size() > max_consider) {\n            ready_tasks.resize(max_consider);\n        }\n        \n        vector<pair<int,int>> assignments;\n        set<int> used;\n        for (int task : ready_tasks) {\n            int best_w = -1;\n            int best_t = INT_MAX;\n            for (int w : free_workers) {\n                if (used.count(w)) continue;\n                int t_est = estimate_t(w, task);\n                if (t_est < best_t) {\n                    best_t = t_est;\n                    best_w = w;\n                }\n            }\n            if (best_w != -1) {\n                assignments.push_back({best_w, task});\n                used.insert(best_w);\n                if (used.size() == free_workers.size()) break;\n            }\n        }\n        \n        // Output assignments\n        cout << assignments.size();\n        for (auto &p : assignments) {\n            cout << \" \" << p.first + 1 << \" \" << p.second + 1;\n        }\n        cout << \"\\n\";\n        cout.flush();\n        \n        // Update state for newly started tasks\n        for (auto &p : assignments) {\n            int w = p.first;\n            int task = p.second;\n            worker_task[w] = task;\n            worker_start[w] = day;\n            task_status[task] = 1;\n        }\n        \n        // Read completions\n        int n;\n        cin >> n;\n        if (n == -1) {\n            break;\n        }\n        vector<int> finished_workers(n);\n        for (int i = 0; i < n; i++) {\n            cin >> finished_workers[i];\n            finished_workers[i]--;\n        }\n        \n        // Process each completion\n        for (int w : finished_workers) {\n            int task = worker_task[w];\n            int start = worker_start[w];\n            int t_actual = day - start + 1;\n            int L, U;\n            if (t_actual == 1) {\n                L = 0;\n                U = 4;\n            } else {\n                L = max(1, t_actual - 3);\n                U = t_actual + 3;\n            }\n            obs[w].push_back({task, L, U});\n            \n            task_status[task] = 2;\n            completed++;\n            for (int v : out_edges[task]) {\n                req_remaining[v]--;\n            }\n            worker_task[w] = -1;\n            worker_start[w] = -1;\n        }\n        \n        // Update skill bounds for workers who finished a task\n        for (int w : finished_workers) {\n            update_bounds(w);\n        }\n        \n        day++;\n        if (day > 2000) {\n            break;\n        }\n    }\n    \n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct InsertResult {\n    int cost, i, j;\n};\n\nint main() {\n    auto start_time = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration_cast<chrono::milliseconds>(\n                   chrono::steady_clock::now() - start_time)\n            .count();\n    };\n\n    // ---------- input ----------\n    constexpr int N = 1000;\n    vector<int> ax(N), ay(N), cx(N), cy(N);\n    for (int i = 0; i < N; ++i)\n        cin >> ax[i] >> ay[i] >> cx[i] >> cy[i];\n\n    // ---------- coordinates and distances ----------\n    constexpr int V = 2 * N + 1;           // 2001\n    vector<int> X(V), Y(V);\n    X[0] = 400; Y[0] = 400;\n    for (int i = 0; i < N; ++i) {\n        X[2 * i + 1] = ax[i]; Y[2 * i + 1] = ay[i];\n        X[2 * i + 2] = cx[i]; Y[2 * i + 2] = cy[i];\n    }\n    vector<int> D(V * V);\n    for (int i = 0; i < V; ++i)\n        for (int j = 0; j < V; ++j)\n            D[i * V + j] = abs(X[i] - X[j]) + abs(Y[i] - Y[j]);\n    auto dist = [&](int u, int v) { return D[u * V + v]; };\n\n    // ---------- route total length ----------\n    auto calc_total = [&](const vector<int>& s) {\n        if (s.empty()) return 0;\n        int tot = dist(0, s[0]);\n        for (size_t i = 0; i + 1 < s.size(); ++i)\n            tot += dist(s[i], s[i + 1]);\n        tot += dist(s.back(), 0);\n        return tot;\n    };\n\n    // ---------- evaluate insertion of order o into sequence s ----------\n    auto eval_ins = [&](const vector<int>& s, int o) -> InsertResult {\n        int L = (int)s.size();\n        int P = 2 * o + 1, D_ = 2 * o + 2;\n        int best_cost = INT_MAX, best_i = -1, best_j = -1;\n        for (int i = 0; i <= L; ++i) {\n            int prev_i = (i == 0 ? 0 : s[i - 1]);\n            int next_i = (i == L ? 0 : s[i]);\n            int base_i = dist(prev_i, next_i);\n            // P and D consecutive\n            int cost_pd = dist(prev_i, P) + dist(P, D_) + dist(D_, next_i) - base_i;\n            if (cost_pd < best_cost) {\n                best_cost = cost_pd;\n                best_i = best_j = i;\n            }\n            int inc_P = dist(prev_i, P) + dist(P, next_i) - base_i;\n            for (int j = i + 1; j <= L; ++j) {\n                int prev_j = s[j - 1];\n                int next_j = (j == L ? 0 : s[j]);\n                int inc_D = dist(prev_j, D_) + dist(D_, next_j) - dist(prev_j, next_j);\n                int cost = inc_P + inc_D;\n                if (cost < best_cost) {\n                    best_cost = cost;\n                    best_i = i;\n                    best_j = j;\n                }\n            }\n        }\n        return {best_cost, best_i, best_j};\n    };\n\n    // ---------- apply insertion ----------\n    auto apply_ins = [&](vector<int>& s, int o, int i, int j) {\n        int P = 2 * o + 1, D_ = 2 * o + 2;\n        vector<int> ns;\n        ns.reserve(s.size() + 2);\n        for (int pos = 0; pos <= (int)s.size(); ++pos) {\n            if (pos == i && pos == j) {\n                ns.push_back(P);\n                ns.push_back(D_);\n            } else {\n                if (pos == i) ns.push_back(P);\n                if (pos == j) ns.push_back(D_);\n            }\n            if (pos < (int)s.size()) ns.push_back(s[pos]);\n        }\n        s = move(ns);\n    };\n\n    auto remove_order_seq = [&](vector<int>& s, int o) {\n        int P = 2 * o + 1, D_ = 2 * o + 2;\n        s.erase(remove(s.begin(), s.end(), P), s.end());\n        s.erase(remove(s.begin(), s.end(), D_), s.end());\n    };\n\n    // ---------- local search on the route (fixed selection) ----------\n    auto improve_route = [&](vector<int>& seq, vector<int>& sel, int& T) {\n        bool improved = true;\n        int pass = 0;\n        while (improved && pass < 10 && elapsed() < 1950) {\n            improved = false;\n            // 1) re\u2011insert whole order\n            for (int o : sel) {\n                vector<int> temp_s = seq;\n                remove_order_seq(temp_s, o);\n                int T_wo = calc_total(temp_s);\n                auto res = eval_ins(temp_s, o);\n                int delta = T_wo + res.cost - T;\n                if (delta < 0) {\n                    seq = move(temp_s);\n                    apply_ins(seq, o, res.i, res.j);\n                    T = T_wo + res.cost;\n                    improved = true;\n                    break;\n                }\n            }\n            if (improved) continue;\n\n            // 2) relocate a single node (preserving precedence)\n            int L = (int)seq.size();\n            for (int idx = 0; idx < L; ++idx) {\n                int node = seq[idx];\n                bool pickup = (node % 2 == 1);\n                int other_node = pickup ? node + 1 : node - 1;\n                int other_idx = -1;\n                for (int k = 0; k < L; ++k)\n                    if (seq[k] == other_node) { other_idx = k; break; }\n                vector<int> temp_s = seq;\n                temp_s.erase(temp_s.begin() + idx);\n                int other_temp = (other_idx > idx) ? other_idx - 1 : other_idx;\n                int best_delta = 0, best_pos = -1;\n                for (int pos = 0; pos <= (int)temp_s.size(); ++pos) {\n                    if (pickup && pos > other_temp) continue;\n                    if (!pickup && pos <= other_temp) continue;\n                    int prv = (pos == 0 ? 0 : temp_s[pos - 1]);\n                    int nxt = (pos == (int)temp_s.size() ? 0 : temp_s[pos]);\n                    int delta = dist(prv, node) + dist(node, nxt) - dist(prv, nxt);\n                    if (delta < best_delta) {\n                        best_delta = delta;\n                        best_pos = pos;\n                    }\n                }\n                if (best_delta < 0) {\n                    temp_s.insert(temp_s.begin() + best_pos, node);\n                    seq = move(temp_s);\n                    T += best_delta;\n                    improved = true;\n                    break;\n                }\n            }\n            if (improved) continue;\n\n            // 3) 2\u2011opt (reverse segment) with precedence check\n            vector<int> pos(V, -1);\n            for (int k = 0; k < L; ++k) pos[seq[k]] = k;\n            int best_delta = 0, best_i = -1, best_j = -1;\n            for (int i = 0; i < L; ++i) {\n                for (int j = i + 1; j < L; ++j) {\n                    bool feasible = true;\n                    for (int o : sel) {\n                        int p = pos[2 * o + 1], d = pos[2 * o + 2];\n                        if (p >= i && p <= j && d >= i && d <= j) {\n                            feasible = false;\n                            break;\n                        }\n                    }\n                    if (!feasible) continue;\n                    int prev_i = (i == 0 ? 0 : seq[i - 1]);\n                    int next_j = (j == L - 1 ? 0 : seq[j + 1]);\n                    int delta = dist(prev_i, seq[j]) + dist(seq[i], next_j) -\n                                dist(prev_i, seq[i]) - dist(seq[j], next_j);\n                    if (delta < best_delta) {\n                        best_delta = delta;\n                        best_i = i;\n                        best_j = j;\n                    }\n                }\n            }\n            if (best_delta < 0) {\n                reverse(seq.begin() + best_i, seq.begin() + best_j + 1);\n                T += best_delta;\n                improved = true;\n            }\n            ++pass;\n        }\n    };\n\n    // ---------- initial solution: farthest insertion ----------\n    vector<int> seq;\n    vector<bool> flag(N, false);\n    vector<int> sel;\n    for (int step = 0; step < 50; ++step) {\n        int best_o = -1, best_cost = -1;\n        InsertResult best_res;\n        for (int o = 0; o < N; ++o) {\n            if (flag[o]) continue;\n            auto res = eval_ins(seq, o);\n            if (res.cost > best_cost) {\n                best_cost = res.cost;\n                best_o = o;\n                best_res = res;\n            }\n        }\n        apply_ins(seq, best_o, best_res.i, best_res.j);\n        flag[best_o] = true;\n        sel.push_back(best_o);\n    }\n    int T = calc_total(seq);\n    improve_route(seq, sel, T);\n\n    // ---------- store global best ----------\n    vector<int> best_seq = seq;\n    vector<bool> best_flag = flag;\n    vector<int> best_sel = sel;\n    int best_T = T;\n\n    // ---------- simulated annealing ----------\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> rnd_idx(0, 49);\n    uniform_int_distribution<int> rnd_order(0, N - 1);\n    uniform_real_distribution<double> rnd_prob(0.0, 1.0);\n    auto last_improve = chrono::steady_clock::now();\n\n    while (elapsed() < 1900) {\n        double temp = 300.0 * (1.0 - elapsed() / 2000.0) + 0.1;\n\n        int idx = rnd_idx(rng) % sel.size();\n        int o_sel = sel[idx];\n        int o_unsel;\n        do { o_unsel = rnd_order(rng); } while (flag[o_unsel]);\n\n        vector<int> temp_s = seq;\n        remove_order_seq(temp_s, o_sel);\n        int T_wo = calc_total(temp_s);\n        auto res = eval_ins(temp_s, o_unsel);\n        int delta = T_wo + res.cost - T;\n\n        if (delta < 0 || exp(-delta / temp) > rnd_prob(rng)) {\n            seq = move(temp_s);\n            apply_ins(seq, o_unsel, res.i, res.j);\n            T = T_wo + res.cost;\n            flag[o_sel] = false;\n            flag[o_unsel] = true;\n            sel[idx] = o_unsel;\n\n            if (T < best_T) {\n                best_T = T;\n                best_seq = seq;\n                best_flag = flag;\n                best_sel = sel;\n            }\n        }\n\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - last_improve).count() > 200) {\n            improve_route(seq, sel, T);\n            last_improve = chrono::steady_clock::now();\n            if (T < best_T) {\n                best_T = T;\n                best_seq = seq;\n                best_flag = flag;\n                best_sel = sel;\n            }\n        }\n    }\n\n    // ---------- final polish on the best solution ----------\n    seq = best_seq; flag = best_flag; sel = best_sel; T = best_T;\n    int last_T = T;\n    do {\n        last_T = T;\n        improve_route(seq, sel, T);\n    } while (T < last_T && elapsed() < 1950);\n    if (T < best_T) {\n        best_T = T;\n        best_seq = seq;\n        best_sel = sel;\n    }\n\n    // ---------- output ----------\n    sort(best_sel.begin(), best_sel.end());\n    cout << 50;\n    for (int o : best_sel) cout << \" \" << o + 1;\n    cout << \"\\n\";\n    cout << best_seq.size() + 2;\n    cout << \" 400 400\";\n    for (int node : best_seq)\n        cout << \" \" << X[node] << \" \" << Y[node];\n    cout << \" 400 400\" << endl;\n\n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n#include <tuple>\n#include <queue>\n#include <unordered_map>\n#include <cstdint>\n#include <climits>\n\nusing namespace std;\n\nstruct DSU {\n    vector<int> parent, sz;\n    int comps;\n    DSU(int n) : parent(n), sz(n, 1), comps(n) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    DSU(const DSU& other) : parent(other.parent), sz(other.sz), comps(other.comps) {}\n    int find(int x) {\n        while (parent[x] != x) {\n            parent[x] = parent[parent[x]];\n            x = parent[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        parent[b] = a;\n        sz[a] += sz[b];\n        --comps;\n        return true;\n    }\n    bool same(int a, int b) { return find(a) == find(b); }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    constexpr int N = 400;\n    constexpr int M = 1995;\n    \n    // -------- read coordinates --------\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; ++i) cin >> x[i] >> y[i];\n    \n    // -------- read edge endpoints --------\n    vector<int> U(M), V(M);\n    for (int i = 0; i < M; ++i) cin >> U[i] >> V[i];\n    \n    // -------- rounded Euclidean distances --------\n    vector<int> d(M);\n    for (int i = 0; i < M; ++i) {\n        double dx = x[U[i]] - x[V[i]];\n        double dy = y[U[i]] - y[V[i]];\n        d[i] = (int)round(sqrt(dx * dx + dy * dy));\n    }\n    \n    // -------- XorShift random generator --------\n    uint32_t xs[4] = {123456789, 362436069, 521288629, 88675123};\n    auto xorshift = [&]() -> uint32_t {\n        uint32_t t = xs[0] ^ (xs[0] << 11);\n        xs[0] = xs[1];\n        xs[1] = xs[2];\n        xs[2] = xs[3];\n        xs[3] = xs[3] ^ (xs[3] >> 19) ^ t ^ (t >> 8);\n        return xs[3];\n    };\n    \n    // -------- Monte Carlo probability of being in global MST --------\n    constexpr int NUM_SIM = 3000;\n    vector<int> mst_count(M, 0);\n    for (int sim = 0; sim < NUM_SIM; ++sim) {\n        vector<tuple<int, int, int, int>> sim_edges; // (l, u, v, idx)\n        sim_edges.reserve(M);\n        for (int i = 0; i < M; ++i) {\n            int range = 2 * d[i] + 1;\n            int l = d[i] + int(xorshift() % range);\n            sim_edges.emplace_back(l, U[i], V[i], i);\n        }\n        sort(sim_edges.begin(), sim_edges.end());\n        DSU dsu_sim(N);\n        for (auto [l, u, v, idx] : sim_edges) {\n            if (dsu_sim.unite(u, v)) {\n                mst_count[idx]++;\n            }\n        }\n    }\n    \n    vector<double> prob(M);\n    for (int i = 0; i < M; ++i) {\n        prob[i] = (double)mst_count[i] / NUM_SIM;\n    }\n    \n    // -------- pre\u2011sort edges by d --------\n    vector<int> sorted_idx(M);\n    iota(sorted_idx.begin(), sorted_idx.end(), 0);\n    sort(sorted_idx.begin(), sorted_idx.end(), [&](int a, int b) {\n        return d[a] < d[b];\n    });\n    \n    // -------- online decision --------\n    DSU dsu(N);\n    constexpr int MC_SAMPLES_PATH = 60;\n    \n    for (int i = 0; i < M; ++i) {\n        int l_i;\n        cin >> l_i;\n        int u = U[i], v = V[i];\n        \n        // already connected\n        if (dsu.same(u, v)) {\n            cout << 0 << endl;\n            continue;\n        }\n        \n        // very cheap edge -> accept immediately\n        if (l_i <= d[i] * 1.1) {\n            dsu.unite(u, v);\n            cout << 1 << endl;\n            continue;\n        }\n        \n        int ru = dsu.find(u);\n        int rv = dsu.find(v);\n        \n        // -------- build component MST using future edges (weight = d) --------\n        unordered_map<int, int> comp_id;\n        for (int k = 0; k < N; ++k) {\n            int r = dsu.find(k);\n            if (comp_id.find(r) == comp_id.end()) {\n                int id = (int)comp_id.size();\n                comp_id[r] = id;\n            }\n        }\n        int total_comps = (int)comp_id.size();\n        vector<vector<pair<int, int>>> comp_tree(total_comps); // (neighbor comp, edge_index)\n        DSU comp_dsu(total_comps);\n        \n        int id_ru = comp_id[ru];\n        int id_rv = comp_id[rv];\n        bool connected_via_future = false;\n        \n        for (int idx : sorted_idx) {\n            if (idx <= i) continue; // only future edges\n            int a = dsu.find(U[idx]);\n            int b = dsu.find(V[idx]);\n            if (a == b) continue;\n            int id_a = comp_id[a];\n            int id_b = comp_id[b];\n            if (comp_dsu.same(id_a, id_b)) continue;\n            comp_dsu.unite(id_a, id_b);\n            comp_tree[id_a].emplace_back(id_b, idx);\n            comp_tree[id_b].emplace_back(id_a, idx);\n            if (comp_dsu.same(id_ru, id_rv)) {\n                connected_via_future = true;\n                break;\n            }\n        }\n        \n        if (!connected_via_future) {\n            // forced acceptance: even all future edges cannot connect\n            dsu.unite(u, v);\n            cout << 1 << endl;\n            continue;\n        }\n        \n        // -------- extract path between ru and rv in component tree --------\n        vector<int> path_edges;\n        {\n            // BFS to find path\n            vector<int> parent(total_comps, -1);\n            vector<int> parent_edge(total_comps, -1);\n            queue<int> q;\n            q.push(id_ru);\n            parent[id_ru] = id_ru;\n            while (!q.empty()) {\n                int cur = q.front(); q.pop();\n                if (cur == id_rv) break;\n                for (auto [nxt, ei] : comp_tree[cur]) {\n                    if (parent[nxt] == -1) {\n                        parent[nxt] = cur;\n                        parent_edge[nxt] = ei;\n                        q.push(nxt);\n                    }\n                }\n            }\n            // climb from id_rv to id_ru\n            for (int cur = id_rv; cur != id_ru; cur = parent[cur]) {\n                path_edges.push_back(parent_edge[cur]);\n            }\n        }\n        \n        // -------- Monte Carlo simulation of the bottleneck --------\n        int count_better = 0;\n        for (int s = 0; s < MC_SAMPLES_PATH; ++s) {\n            int max_len = 0;\n            for (int ei : path_edges) {\n                int len = d[ei] + int(xorshift() % (2 * d[ei] + 1));\n                if (len > max_len) max_len = len;\n            }\n            if (max_len >= l_i) {\n                ++count_better;\n            }\n        }\n        double p_better = (double)count_better / MC_SAMPLES_PATH;\n        \n        // -------- dynamic threshold probability --------\n        double progress = (double)i / M;\n        int comps_now = dsu.comps;\n        int R = M - i - 1;\n        double urgency = (R > 0) ? (double)(comps_now - 1) / R : 1.0;\n        double threshold_prob = 0.7 - 0.2 * progress - 0.1 * urgency;\n        if (threshold_prob < 0.5) threshold_prob = 0.5;\n        if (threshold_prob > 0.7) threshold_prob = 0.7;\n        \n        // -------- decision --------\n        if (p_better >= threshold_prob) {\n            dsu.unite(u, v);\n            cout << 1 << endl;\n        } else {\n            cout << 0 << endl;\n        }\n    }\n    \n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\n\nconst ll INF = 1e12;\nconst ll BONUS = 10'000'000LL;\nconst int URGENT_WEIGHT = 10000;\n\n// ---------- Hungarian algorithm (min cost, square matrix) ----------\nll hungarian(const vector<vector<ll>> &a, vector<int> &ans) {\n    int n = (int)a.size();          // rows = workers (walls)\n    int m = (int)a[0].size();       // cols = jobs  (humans)\n    // We need n == m, the caller must pad.\n    vector<ll> u(n+1), v(m+1);\n    vector<int> p(m+1), way(m+1);\n    for (int i=1; i<=n; ++i) {\n        p[0] = i;\n        int j0 = 0;\n        vector<ll> minv(m+1, INF);\n        vector<char> used(m+1, false);\n        do {\n            used[j0] = true;\n            int i0 = p[j0], j1 = 0;\n            ll delta = INF;\n            for (int j=1; j<=m; ++j) if (!used[j]) {\n                ll cur = a[i0-1][j-1] - u[i0] - v[j];\n                if (cur < minv[j]) { minv[j] = cur; way[j] = j0; }\n                if (minv[j] < delta) { delta = minv[j]; j1 = j; }\n            }\n            for (int j=0; j<=m; ++j) {\n                if (used[j]) u[p[j]] += delta, v[j] -= delta;\n                else minv[j] -= delta;\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    ans.assign(n, -1);\n    for (int j=1; j<=m; ++j) if (p[j] != 0) ans[p[j]-1] = j-1;\n    return -v[0];\n}\n\n// ---------- Dinic for min-cut ----------\nstruct Dinic {\n    struct Edge { int to, rev; ll cap; };\n    vector<vector<Edge>> g;\n    vector<int> level, iter;\n    Dinic(int n) : g(n), level(n), iter(n) {}\n    void add_edge(int from, int to, ll cap) {\n        g[from].push_back({to, (int)g[to].size(), cap});\n        g[to].push_back({from, (int)g[from].size()-1, 0});\n    }\n    void bfs(int s) {\n        fill(level.begin(), level.end(), -1);\n        queue<int> q;\n        level[s]=0; q.push(s);\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (auto &e : g[v]) if (e.cap>0 && level[e.to]<0) {\n                level[e.to] = level[v]+1; q.push(e.to);\n            }\n        }\n    }\n    ll dfs(int v, int t, ll f) {\n        if (v==t) return f;\n        for (int &i=iter[v]; i<(int)g[v].size(); ++i) {\n            auto &e = g[v][i];\n            if (e.cap>0 && level[v]<level[e.to]) {\n                ll d = dfs(e.to, t, min(f, e.cap));\n                if (d>0) { e.cap-=d; g[e.to][e.rev].cap+=d; return d; }\n            }\n        }\n        return 0;\n    }\n    ll max_flow(int s, int t) {\n        ll flow=0;\n        while (true) {\n            bfs(s);\n            if (level[t]<0) return flow;\n            fill(iter.begin(), iter.end(), 0);\n            ll f;\n            while ((f=dfs(s,t,1LL<<60))>0) flow+=f;\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int dx[4] = {-1, 1, 0, 0};\n    const int dy[4] = {0, 0, -1, 1};\n    const char moveC[4] = {'U', 'D', 'L', 'R'};\n    const char buildC[4] = {'u', 'd', 'l', 'r'};\n\n    int N; cin >> N;\n    vector<int> px(N), py(N), pt(N);\n    for (int i=0; i<N; ++i) cin >> px[i] >> py[i] >> pt[i];\n    int M; cin >> M;\n    vector<int> hx(M), hy(M);\n    for (int i=0; i<M; ++i) cin >> hx[i] >> hy[i];\n\n    int grid[32][32];\n    memset(grid, 0, sizeof(grid));\n\n    auto buildable_now = [&](int x, int y) -> bool {\n        if (grid[x][y] != 0) return false;\n        for (int i=0; i<M; ++i) if (hx[i]==x && hy[i]==y) return false;\n        for (int i=0; i<N; ++i) if (px[i]==x && py[i]==y) return false;\n        for (int d=0; d<4; ++d) {\n            int nx = x+dx[d], ny = y+dy[d];\n            if (nx>=1 && nx<=30 && ny>=1 && ny<=30) {\n                for (int i=0; i<N; ++i)\n                    if (px[i]==nx && py[i]==ny) return false;\n            }\n        }\n        return true;\n    };\n\n    // BFS from a human\n    auto bfs_from = [&](int sx, int sy) -> pair<vector<vector<int>>, vector<vector<pair<int,int>>>> {\n        vector<vector<int>> dist(31, vector<int>(31, -1));\n        vector<vector<pair<int,int>>> parent(31, vector<pair<int,int>>(31, {-1,-1}));\n        queue<pair<int,int>> q;\n        dist[sx][sy] = 0;\n        q.push({sx, sy});\n        while (!q.empty()) {\n            auto [x,y] = q.front(); q.pop();\n            for (int d=0; d<4; ++d) {\n                int nx = x+dx[d], ny = y+dy[d];\n                if (nx>=1 && nx<=30 && ny>=1 && ny<=30 && grid[nx][ny]==0 && dist[nx][ny]==-1) {\n                    dist[nx][ny] = dist[x][y] + 1;\n                    parent[nx][ny] = {x, y};\n                    q.push({nx, ny});\n                }\n            }\n        }\n        return {dist, parent};\n    };\n\n    // BFS from pets\n    auto pet_bfs = [&]() {\n        vector<vector<int>> dist(31, vector<int>(31, -1));\n        queue<pair<int,int>> q;\n        for (int j=0; j<N; ++j) if (grid[px[j]][py[j]]==0) {\n            dist[px[j]][py[j]] = 0;\n            q.push({px[j], py[j]});\n        }\n        while (!q.empty()) {\n            auto [x,y] = q.front(); q.pop();\n            for (int d=0; d<4; ++d) {\n                int nx = x+dx[d], ny = y+dy[d];\n                if (nx>=1 && nx<=30 && ny>=1 && ny<=30 && grid[nx][ny]==0 && dist[nx][ny]==-1) {\n                    dist[nx][ny] = dist[x][y] + 1;\n                    q.push({nx, ny});\n                }\n            }\n        }\n        return dist;\n    };\n\n    // Min-cut\n    auto compute_min_cut = [&]() -> set<pair<int,int>> {\n        int id[32][32]; memset(id, -1, sizeof(id));\n        vector<pair<int,int>> cells;\n        for (int i=1; i<=30; ++i) for (int j=1; j<=30; ++j)\n            if (grid[i][j]==0) { id[i][j] = (int)cells.size(); cells.push_back({i,j}); }\n        int V = (int)cells.size();\n        int src = 2*V, sink = 2*V+1;\n        Dinic dinic(2*V+2);\n\n        for (auto [x,y] : cells) {\n            int u = id[x][y];\n            bool has_human = false, has_pet = false, adj_pet = false;\n            for (int i=0; i<M; ++i) if (hx[i]==x && hy[i]==y) has_human = true;\n            for (int i=0; i<N; ++i) if (px[i]==x && py[i]==y) has_pet = true;\n            if (!has_pet) {\n                for (int d=0; d<4; ++d) {\n                    int nx = x+dx[d], ny = y+dy[d];\n                    if (nx>=1 && nx<=30 && ny>=1 && ny<=30)\n                        for (int i=0; i<N; ++i)\n                            if (px[i]==nx && py[i]==ny) adj_pet = true;\n                }\n            }\n            bool buildable = !has_human && !has_pet && !adj_pet;\n            dinic.add_edge(2*u, 2*u+1, buildable ? 1 : INF);\n        }\n\n        for (int u=0; u<V; ++u) {\n            auto [x,y] = cells[u];\n            for (int d=0; d<4; ++d) {\n                int nx = x+dx[d], ny = y+dy[d];\n                if (nx>=1 && nx<=30 && ny>=1 && ny<=30 && id[nx][ny]!=-1)\n                    dinic.add_edge(2*u+1, 2*id[nx][ny], INF);\n            }\n        }\n\n        for (int i=0; i<M; ++i) {\n            int u = id[hx[i]][hy[i]];\n            if (u!=-1) dinic.add_edge(src, 2*u, INF);\n        }\n        for (int i=0; i<N; ++i) {\n            int u = id[px[i]][py[i]];\n            if (u!=-1) dinic.add_edge(2*u+1, sink, INF);\n        }\n\n        dinic.max_flow(src, sink);\n        vector<bool> visited(2*V+2, false);\n        queue<int> q;\n        visited[src]=true; q.push(src);\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (auto &e : dinic.g[v]) if (e.cap>0 && !visited[e.to]) {\n                visited[e.to]=true; q.push(e.to);\n            }\n        }\n        set<pair<int,int>> cut;\n        for (int u=0; u<V; ++u)\n            if (visited[2*u] && !visited[2*u+1])\n                cut.insert(cells[u]);\n        return cut;\n    };\n\n    for (int turn = 0; turn < 300; ++turn) {\n        // ---------- 1. Min-cut and urgency ----------\n        set<pair<int,int>> target_walls = compute_min_cut();\n        map<pair<int,int>, int> urgency;\n        {\n            auto pd = pet_bfs();\n            for (auto w : target_walls) {\n                int d = pd[w.first][w.second];\n                urgency[w] = (d == -1 ? 1000000 : d);\n            }\n        }\n\n        // ---------- 2. BFS from every human ----------\n        vector<vector<vector<int>>> dist_h(M);\n        vector<vector<vector<pair<int,int>>>> parent_h(M);\n        for (int i=0; i<M; ++i) {\n            auto [d, p] = bfs_from(hx[i], hy[i]);\n            dist_h[i] = move(d);\n            parent_h[i] = move(p);\n        }\n\n        // pet distance for fallback\n        auto pet_dist = pet_bfs();\n        auto safe = [&](int x, int y) -> int {\n            return pet_dist[x][y] == -1 ? 1000000 : pet_dist[x][y];\n        };\n\n        // ---------- 3. Hungarian assignment (walls -> humans) ----------\n        vector<pair<int,int>> walls_list(target_walls.begin(), target_walls.end());\n        int W = (int)walls_list.size();\n        int K = max(W, M);\n        vector<vector<ll>> cost(K, vector<ll>(K, 0LL)); // extra rows/cols padded with 0\n\n        for (int wi=0; wi<W; ++wi) {\n            auto w = walls_list[wi];\n            int urg = urgency[w];\n            for (int i=0; i<M; ++i) {\n                ll best_dist = INF;\n                for (int d=0; d<4; ++d) {\n                    int gx = w.first+dx[d], gy = w.second+dy[d];\n                    if (gx>=1 && gx<=30 && gy>=1 && gy<=30 && grid[gx][gy]==0) {\n                        int dis = dist_h[i][gx][gy];\n                        if (dis != -1 && dis < best_dist) best_dist = dis;\n                    }\n                }\n                if (best_dist < INF)\n                    cost[wi][i] = best_dist - BONUS + (ll)urg * URGENT_WEIGHT;\n                else\n                    cost[wi][i] = INF;\n            }\n        }\n\n        vector<int> assignment;\n        if (K > 0) {\n            hungarian(cost, assignment); // assignment[wall_index] = human_index\n        }\n\n        vector<int> assigned_wall(M, -1);\n        if (K > 0) {\n            for (int wi=0; wi<W; ++wi) {\n                int hum = assignment[wi];\n                if (hum < M) assigned_wall[hum] = wi;\n            }\n        }\n\n        // ---------- 4. Initial actions ----------\n        set<pair<int,int>> built_this_turn;\n        string actions(M, '.');\n\n        for (int i=0; i<M; ++i) {\n            if (assigned_wall[i] != -1) {\n                auto w = walls_list[assigned_wall[i]];\n                // Is there a gate adjacent to human? (i.e. wall cell is adjacent)\n                bool built = false;\n                for (int d=0; d<4; ++d) {\n                    int wx = hx[i]+dx[d], wy = hy[i]+dy[d];\n                    if (wx>=1 && wx<=30 && wy>=1 && wy<=30 && grid[wx][wy]==0\n                        && wx==w.first && wy==w.second) {\n                        if (buildable_now(wx, wy)) {\n                            actions[i] = buildC[d];\n                            built_this_turn.insert({wx, wy});\n                            target_walls.erase({wx, wy});\n                            built = true;\n                            break;\n                        }\n                    }\n                }\n                if (built) continue;\n\n                // otherwise move towards a gate of this wall\n                ll best_dist = INF;\n                int best_gx = -1, best_gy = -1;\n                for (int d=0; d<4; ++d) {\n                    int gx = w.first+dx[d], gy = w.second+dy[d];\n                    if (gx>=1 && gx<=30 && gy>=1 && gy<=30 && grid[gx][gy]==0) {\n                        int dd = dist_h[i][gx][gy];\n                        if (dd != -1 && dd < best_dist) {\n                            best_dist = dd; best_gx = gx; best_gy = gy;\n                        }\n                    }\n                }\n                if (best_gx != -1) {\n                    int cx = best_gx, cy = best_gy;\n                    while (parent_h[i][cx][cy] != make_pair(hx[i], hy[i])) {\n                        auto p = parent_h[i][cx][cy];\n                        if (p.first == -1) break;\n                        cx = p.first; cy = p.second;\n                    }\n                    if (cx < hx[i]) actions[i] = 'U';\n                    else if (cx > hx[i]) actions[i] = 'D';\n                    else if (cy < hy[i]) actions[i] = 'L';\n                    else actions[i] = 'R';\n                }\n            }\n        }\n\n        // ---------- 5. Opportunistic building ----------\n        for (int i=0; i<M; ++i) {\n            if (actions[i] != '.' && actions[i] != 'U' && actions[i] != 'D' && actions[i] != 'L' && actions[i] != 'R')\n                continue; // already building something\n            for (int d=0; d<4; ++d) {\n                int wx = hx[i]+dx[d], wy = hy[i]+dy[d];\n                if (wx>=1 && wx<=30 && wy>=1 && wy<=30 && grid[wx][wy]==0) {\n                    if (target_walls.count({wx, wy}) && !built_this_turn.count({wx, wy}) && buildable_now(wx, wy)) {\n                        actions[i] = buildC[d];\n                        built_this_turn.insert({wx, wy});\n                        target_walls.erase({wx, wy});\n                        break;\n                    }\n                }\n            }\n        }\n\n        // ---------- 6. Conflict resolution ----------\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 nx = hx[i], ny = hy[i];\n                if (c == 'U') nx--;\n                else if (c == 'D') nx++;\n                else if (c == 'L') ny--;\n                else if (c == 'R') ny++;\n                if (built_this_turn.count({nx, ny})) {\n                    actions[i] = '.';\n                }\n            }\n        }\n\n        // ---------- 7. Second pass (fallback) ----------\n        for (int i=0; i<M; ++i) {\n            if (actions[i] != '.') continue;\n            int cur = safe(hx[i], hy[i]);\n            int best = cur, bx = -1, by = -1;\n            for (int d=0; d<4; ++d) {\n                int nx = hx[i]+dx[d], ny = hy[i]+dy[d];\n                if (nx>=1 && nx<=30 && ny>=1 && ny<=30 && grid[nx][ny]==0\n                    && !built_this_turn.count({nx, ny})) {\n                    int sf = safe(nx, ny);\n                    if (sf > best) { best = sf; bx = nx; by = ny; }\n                }\n            }\n            if (bx != -1) {\n                if (bx < hx[i]) actions[i] = 'U';\n                else if (bx > hx[i]) actions[i] = 'D';\n                else if (by < hy[i]) actions[i] = 'L';\n                else actions[i] = 'R';\n            } else {\n                // try to build any adjacent wall\n                for (int d=0; d<4; ++d) {\n                    int nx = hx[i]+dx[d], ny = hy[i]+dy[d];\n                    if (nx>=1 && nx<=30 && ny>=1 && ny<=30 && grid[nx][ny]==0\n                        && !built_this_turn.count({nx, ny}) && buildable_now(nx, ny)) {\n                        actions[i] = buildC[d];\n                        built_this_turn.insert({nx, ny});\n                        break;\n                    }\n                }\n            }\n        }\n\n        // ---------- 8. Output and apply ----------\n        cout << actions << endl;\n\n        for (int i=0; i<M; ++i) {\n            char c = actions[i];\n            if (c == 'u') grid[hx[i]-1][hy[i]] = 1;\n            else if (c == 'd') grid[hx[i]+1][hy[i]] = 1;\n            else if (c == 'l') grid[hx[i]][hy[i]-1] = 1;\n            else if (c == 'r') grid[hx[i]][hy[i]+1] = 1;\n            else if (c == 'U') hx[i]--;\n            else if (c == 'D') hx[i]++;\n            else if (c == 'L') hy[i]--;\n            else if (c == 'R') hy[i]++;\n        }\n\n        for (int i=0; i<N; ++i) {\n            string s; cin >> s;\n            if (s == \".\") continue;\n            for (char c : s) {\n                if (c == 'U') px[i]--;\n                else if (c == 'D') px[i]++;\n                else if (c == 'L') py[i]--;\n                else if (c == 'R') py[i]++;\n            }\n        }\n    }\n    return 0;\n}","ahc009":"#include <iostream>\n#include <string>\n#include <vector>\n#include <array>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <numeric>\n#include <queue>\n#include <cmath>\n#include <set>\n\nusing namespace std;\n\nconst int L = 200;\nconst int H = 20, W = 20;\nconst int N = H * W;\n\nint start_id, target_id;\ndouble p;\nint next_cell[4][N];\ndouble p_stay[4][N], p_move[4][N];\nchar dir_chars[4] = {'U', 'D', 'L', 'R'};\ndouble reward[L];\n\n// Optimal adaptive DP for beam search heuristic\ndouble V_opt[L + 1][N];\n\n// forward/backward arrays for coordinate ascent\nvector<array<double, N>> F, V;\nvector<double> base_reward_prefix;\n\ndouble evaluate(const string &s) {\n    array<double, N> prob;\n    prob.fill(0.0);\n    prob[start_id] = 1.0;\n    vector<int> active = {start_id};\n    double er = 0.0;\n    for (int t = 0; t < L; ++t) {\n        if (active.empty()) break;\n        char c = s[t];\n        int d;\n        if (c == 'U') d = 0;\n        else if (c == 'D') d = 1;\n        else if (c == 'L') d = 2;\n        else d = 3;\n        array<double, N> next_prob;\n        next_prob.fill(0.0);\n        array<bool, N> next_mark;\n        next_mark.fill(false);\n        for (int i : active) {\n            double pr = prob[i];\n            double stay = p_stay[d][i];\n            double move = p_move[d][i];\n            next_prob[i] += pr * stay;\n            next_mark[i] = true;\n            if (move > 0.0) {\n                int nxt = next_cell[d][i];\n                if (nxt == target_id) {\n                    er += pr * move * reward[t];\n                } else {\n                    next_prob[nxt] += pr * move;\n                    next_mark[nxt] = true;\n                }\n            }\n        }\n        prob.fill(0.0);\n        active.clear();\n        for (int i = 0; i < N; ++i) {\n            if (next_mark[i]) {\n                prob[i] = next_prob[i];\n                active.push_back(i);\n            }\n        }\n    }\n    return er;\n}\n\nint main() {\n    auto start_time = chrono::steady_clock::now();\n    auto time_ms = [&]() {\n        return chrono::duration_cast<chrono::milliseconds>(\n            chrono::steady_clock::now() - start_time).count();\n    };\n\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj, ti, tj;\n    cin >> si >> sj >> ti >> tj >> p;\n    start_id = si * W + sj;\n    target_id = ti * W + tj;\n\n    vector<string> h(20), v(20);\n    for (int i = 0; i < 20; ++i) cin >> h[i];\n    for (int i = 0; i < 19; ++i) cin >> v[i]; // v has 19 rows of length 20\n\n    for (int t = 0; t < L; ++t) reward[t] = 401.0 - (t + 1);\n\n    // precompute walls and transition probabilities\n    int di[4] = {-1, 1, 0, 0};\n    int dj[4] = {0, 0, -1, 1};\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = i * W + j;\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + di[d];\n                int nj = j + dj[d];\n                bool wall = true;\n                if (ni >= 0 && ni < H && nj >= 0 && nj < W) {\n                    if (d == 0) {        // U\n                        if (v[i - 1][j] == '0') wall = false;\n                    } else if (d == 1) { // D\n                        if (v[i][j] == '0') wall = false;\n                    } else if (d == 2) { // L\n                        if (h[i][j - 1] == '0') wall = false;\n                    } else {             // R\n                        if (h[i][j] == '0') wall = false;\n                    }\n                }\n                if (!wall) {\n                    next_cell[d][id] = ni * W + nj;\n                } else {\n                    next_cell[d][id] = id;\n                }\n                p_stay[d][id] = wall ? 1.0 : p;\n                p_move[d][id] = wall ? 0.0 : (1.0 - p);\n            }\n        }\n    }\n\n    // Optimal adaptive DP (upper bound for beam search)\n    for (int i = 0; i < N; ++i) V_opt[0][i] = 0.0;\n    for (int r = 1; r <= L; ++r) {\n        double target_rew = 200.0 + r;\n        for (int i = 0; i < N; ++i) {\n            if (i == target_id) {\n                V_opt[r][i] = 0.0;\n                continue;\n            }\n            double best = 0.0;\n            for (int d = 0; d < 4; ++d) {\n                double stay = p_stay[d][i];\n                double move = p_move[d][i];\n                double val;\n                if (move == 0.0) {\n                    val = V_opt[r - 1][i];\n                } else {\n                    int nxt = next_cell[d][i];\n                    double move_val = (nxt == target_id) ? target_rew : V_opt[r - 1][nxt];\n                    val = stay * V_opt[r - 1][i] + move * move_val;\n                }\n                if (val > best) best = val;\n            }\n            V_opt[r][i] = best;\n        }\n    }\n\n    // ---------- Beam search ----------\n    const int K = 200;\n    vector<array<double, N>> beam_prob;\n    vector<string> beam_str;\n    vector<double> beam_er;\n\n    {\n        array<double, N> prob;\n        prob.fill(0.0);\n        prob[start_id] = 1.0;\n        beam_prob.push_back(prob);\n        beam_str.push_back(\"\");\n        beam_er.push_back(0.0);\n    }\n\n    for (int step = 0; step < L; ++step) {\n        vector<array<double, N>> next_prob_vec;\n        vector<string> next_str;\n        vector<double> next_er;\n        vector<double> next_score;\n\n        for (int idx = 0; idx < (int)beam_prob.size(); ++idx) {\n            const auto &prob = beam_prob[idx];\n            const string &s = beam_str[idx];\n            double er = beam_er[idx];\n\n            for (int d = 0; d < 4; ++d) {\n                array<double, N> ns_prob;\n                ns_prob.fill(0.0);\n                double ns_er = er;\n                for (int i = 0; i < N; ++i) {\n                    double pr = prob[i];\n                    if (pr == 0.0) continue;\n                    double stay = p_stay[d][i];\n                    double move = p_move[d][i];\n                    ns_prob[i] += pr * stay;\n                    if (move > 0.0) {\n                        int nxt = next_cell[d][i];\n                        if (nxt == target_id) {\n                            ns_er += pr * move * reward[step];\n                        } else {\n                            ns_prob[nxt] += pr * move;\n                        }\n                    }\n                }\n                int R = L - (step + 1);\n                double future = 0.0;\n                for (int i = 0; i < N; ++i) future += ns_prob[i] * V_opt[R][i];\n                double score = ns_er + future;\n\n                next_prob_vec.push_back(move(ns_prob));\n                next_str.push_back(s + dir_chars[d]);\n                next_er.push_back(ns_er);\n                next_score.push_back(score);\n            }\n        }\n\n        if (next_score.size() > K) {\n            vector<int> indices(next_score.size());\n            iota(indices.begin(), indices.end(), 0);\n            nth_element(indices.begin(), indices.begin() + K, indices.end(),\n                        [&](int a, int b) { return next_score[a] > next_score[b]; });\n            beam_prob.clear(); beam_str.clear(); beam_er.clear();\n            for (int i = 0; i < K; ++i) {\n                int id = indices[i];\n                beam_prob.push_back(move(next_prob_vec[id]));\n                beam_str.push_back(move(next_str[id]));\n                beam_er.push_back(next_er[id]);\n            }\n        } else {\n            beam_prob = move(next_prob_vec);\n            beam_str = move(next_str);\n            beam_er = move(next_er);\n        }\n    }\n\n    // collect distinct best strings from beam\n    vector<pair<double, string>> candidates;\n    {\n        vector<int> order(beam_er.size());\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) { return beam_er[a] > beam_er[b]; });\n        set<string> seen;\n        for (int idx : order) {\n            if (seen.insert(beam_str[idx]).second) {\n                candidates.emplace_back(beam_er[idx], beam_str[idx]);\n                if (candidates.size() >= 5) break;\n            }\n        }\n    }\n\n    // add deterministic shortest path repeated as fallback\n    {\n        vector<int> prev(N, -1);\n        vector<char> prev_move(N);\n        queue<int> q;\n        q.push(start_id);\n        prev[start_id] = start_id;\n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            if (u == target_id) break;\n            for (int d = 0; d < 4; ++d) {\n                if (p_stay[d][u] < 1.0) { // not wall\n                    int v = next_cell[d][u];\n                    if (prev[v] == -1) {\n                        prev[v] = u;\n                        prev_move[v] = dir_chars[d];\n                        q.push(v);\n                    }\n                }\n            }\n        }\n        string path;\n        for (int v = target_id; v != start_id; v = prev[v])\n            path += prev_move[v];\n        reverse(path.begin(), path.end());\n        string repeated;\n        while (repeated.size() < L) repeated += path;\n        repeated.resize(L);\n        double val = evaluate(repeated);\n        candidates.emplace_back(val, repeated);\n    }\n\n    // keep up to 5 distinct best\n    sort(candidates.begin(), candidates.end(),\n         [](const auto &a, const auto &b) { return a.first > b.first; });\n    set<string> unique_cands;\n    vector<string> start_strings;\n    for (auto &[val, s] : candidates) {\n        if (unique_cands.insert(s).second) {\n            start_strings.push_back(s);\n            if (start_strings.size() >= 5) break;\n        }\n    }\n\n    // ---------- Coordinate ascent ----------\n    F.resize(L + 1);\n    V.resize(L + 1);\n    base_reward_prefix.resize(L + 1);\n\n    auto char_to_dir = [](char c) -> int {\n        if (c == 'U') return 0;\n        if (c == 'D') return 1;\n        if (c == 'L') return 2;\n        return 3;\n    };\n\n    auto compute_forward = [&](const string &s) -> double {\n        F[0].fill(0.0);\n        F[0][start_id] = 1.0;\n        fill(base_reward_prefix.begin(), base_reward_prefix.end(), 0.0);\n        double total_er = 0.0;\n        for (int t = 0; t < L; ++t) {\n            int d = char_to_dir(s[t]);\n            double step_reward = 0.0;\n            auto &cur = F[t];\n            auto &nxt = F[t + 1];\n            nxt.fill(0.0);\n            for (int i = 0; i < N; ++i) {\n                double pr = cur[i];\n                if (pr == 0.0) continue;\n                double stay = p_stay[d][i];\n                double move = p_move[d][i];\n                nxt[i] += pr * stay;\n                if (move > 0.0) {\n                    int nc = next_cell[d][i];\n                    if (nc == target_id) {\n                        step_reward += pr * move * reward[t];\n                    } else {\n                        nxt[nc] += pr * move;\n                    }\n                }\n            }\n            base_reward_prefix[t + 1] = base_reward_prefix[t] + step_reward;\n            total_er += step_reward;\n        }\n        return total_er;\n    };\n\n    auto compute_backward = [&](const string &s) {\n        V[L].fill(0.0);\n        for (int t = L - 1; t >= 0; --t) {\n            int d = char_to_dir(s[t]);\n            auto &cur = V[t];\n            auto &nxt = V[t + 1];\n            for (int i = 0; i < N; ++i) {\n                double stay = p_stay[d][i];\n                double move = p_move[d][i];\n                double val = stay * nxt[i];\n                if (move > 0.0) {\n                    int nc = next_cell[d][i];\n                    if (nc == target_id) {\n                        val += move * reward[t];\n                    } else {\n                        val += move * nxt[nc];\n                    }\n                }\n                cur[i] = val;\n            }\n        }\n    };\n\n    double best_overall_er = -1e9;\n    string best_overall_str;\n\n    for (string &cur_str : start_strings) {\n        if (time_ms() > 1900) break;\n\n        // coordinate ascent\n        while (true) {\n            if (time_ms() > 1900) break;\n            double total_er = compute_forward(cur_str);\n            compute_backward(cur_str);\n\n            double best_improvement = -1e-12;\n            int best_pos = -1, best_dir = -1;\n            double best_new_total = total_er;\n\n            vector<int> cur_dirs(L);\n            for (int t = 0; t < L; ++t) cur_dirs[t] = char_to_dir(cur_str[t]);\n\n            for (int pos = 0; pos < L; ++pos) {\n                double base_val = base_reward_prefix[pos];\n                const auto &f = F[pos];\n                const auto &v_next = V[pos + 1];\n\n                for (int d = 0; d < 4; ++d) {\n                    if (d == cur_dirs[pos]) continue;\n                    double sum = base_val;\n                    for (int i = 0; i < N; ++i) {\n                        double pr = f[i];\n                        if (pr == 0.0) continue;\n                        double stay = p_stay[d][i];\n                        double move = p_move[d][i];\n                        double contrib = stay * v_next[i];\n                        if (move > 0.0) {\n                            int nxt = next_cell[d][i];\n                            if (nxt == target_id) {\n                                contrib += move * reward[pos];\n                            } else {\n                                contrib += move * v_next[nxt];\n                            }\n                        }\n                        sum += pr * contrib;\n                    }\n                    double improvement = sum - total_er;\n                    if (improvement > best_improvement) {\n                        best_improvement = improvement;\n                        best_pos = pos;\n                        best_dir = d;\n                        best_new_total = sum;\n                    }\n                }\n            }\n            if (best_improvement <= 1e-12) break;\n            cur_str[best_pos] = dir_chars[best_dir];\n        }\n        double final_er = evaluate(cur_str);\n        if (final_er > best_overall_er) {\n            best_overall_er = final_er;\n            best_overall_str = cur_str;\n        }\n    }\n\n    // ---------- Simulated Annealing (if time remains) ----------\n    if (time_ms() < 1850) {\n        mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n        uniform_real_distribution<double> real(0.0, 1.0);\n        uniform_int_distribution<int> pos_dis(0, L - 1);\n        uniform_int_distribution<int> dir_dis(0, 3);\n\n        string cur = best_overall_str;\n        double cur_val = best_overall_er;\n        string best_cur = cur;\n        double best_val = cur_val;\n        double T = 0.5;\n        double alpha = 0.999;\n\n        while (time_ms() < 1950) {\n            string nxt = cur;\n            int op = (int)(real(rng) * 100);\n            if (op < 60) {\n                int pos = pos_dis(rng);\n                char old = nxt[pos];\n                char nc = dir_chars[dir_dis(rng)];\n                while (nc == old) nc = dir_chars[dir_dis(rng)];\n                nxt[pos] = nc;\n            } else if (op < 80) {\n                int a = pos_dis(rng), b = pos_dis(rng);\n                swap(nxt[a], nxt[b]);\n            } else {\n                int a = pos_dis(rng), b = pos_dis(rng);\n                if (a > b) swap(a, b);\n                reverse(nxt.begin() + a, nxt.begin() + b + 1);\n            }\n            double nxt_val = evaluate(nxt);\n            double diff = nxt_val - cur_val;\n            if (diff > 0 || exp(diff / T) > real(rng)) {\n                cur = nxt;\n                cur_val = nxt_val;\n                if (cur_val > best_val) {\n                    best_val = cur_val;\n                    best_cur = cur;\n                }\n            }\n            T *= alpha;\n        }\n        best_overall_str = best_cur;\n    }\n\n    cout << best_overall_str << \"\\n\";\n    return 0;\n}","ahc010":"#include <iostream>\n#include <string>\n#include <cstring>\n#include <chrono>\n#include <cstdint>\n#include <cmath>\n\nusing namespace std;\n\n// fast xorshift random\nuint64_t xor64_state = 123456789ULL;\ninline uint64_t xor64() {\n    xor64_state ^= xor64_state << 13;\n    xor64_state ^= xor64_state >> 7;\n    xor64_state ^= xor64_state << 17;\n    return xor64_state;\n}\ninline int rand_int(int n) {\n    return xor64() % n;\n}\ninline double rand_double() {\n    return (xor64() >> 11) * (1.0 / (1ULL << 53));\n}\n\nchrono::steady_clock::time_point start_time;\ninline double elapsed_sec() {\n    return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n}\n\nconst int N = 30, TOTAL = 900;\nint init_tiles[TOTAL];\nint rot_table[8][4]; // rotation mapping\n\n// neighbor indices (flat, -1 for boundaries)\nint neig[3600];\n// transition table\nconst int to[8][4] = {\n    {1, 0, -1, -1},\n    {3, -1, -1, 0},\n    {-1, -1, 3, 2},\n    {-1, 2, 1, -1},\n    {1, 0, 3, 2},\n    {3, 2, 1, 0},\n    {2, -1, 0, -1},\n    {-1, 3, -1, 1}\n};\n\n// evaluation with static vis\nstatic uint16_t vis[3600] = {0};\nstatic uint16_t vis_id = 0;\n\ninline int evaluate(const int* cur) {\n    ++vis_id;\n    int max1 = 0, max2 = 0;\n    for (int i = 0; i < TOTAL; ++i) {\n        int t = cur[i];\n        int base = i * 4;\n        for (int d = 0; d < 4; ++d) {\n            int idx = base + d;\n            if (vis[idx] == vis_id) continue;\n            int d0 = to[t][d];\n            if (d0 < 0) continue;\n            int si = i, sd = d;\n            int ci = i, cd = d;\n            int len = 0;\n            while (true) {\n                vis[ci * 4 + cd] = vis_id;\n                int d2 = to[cur[ci]][cd];\n                if (d2 < 0) { len = -1; break; }\n                int ni = neig[ci * 4 + d2];\n                if (ni < 0) { len = -1; break; }\n                ++len;\n                ci = ni;\n                cd = (d2 + 2) & 3;\n                if (ci == si && cd == sd) break;\n                if (len > 4000) { len = -1; break; }\n            }\n            if (len > 0) {\n                if (len > max1) {\n                    max2 = max1;\n                    max1 = len;\n                } else if (len > max2) {\n                    max2 = len;\n                }\n            }\n        }\n    }\n    if (max2 == 0) return 0;\n    return max1 * max2;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    start_time = chrono::steady_clock::now();\n    xor64_state = chrono::steady_clock::now().time_since_epoch().count();\n\n    // read initial tiles\n    for (int i = 0; i < N; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; ++j) {\n            init_tiles[i * N + j] = s[j] - '0';\n        }\n    }\n\n    // precompute rotation table\n    const int rot1[8] = {1, 2, 3, 0, 5, 4, 7, 6};\n    for (int t = 0; t < 8; ++t) {\n        rot_table[t][0] = t;\n        for (int r = 1; r < 4; ++r) {\n            rot_table[t][r] = rot1[rot_table[t][r-1]];\n        }\n    }\n\n    // neighbor table\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int idx = i * N + j;\n            int b = idx * 4;\n            neig[b+0] = (j > 0) ? idx - 1 : -1;\n            neig[b+1] = (i > 0) ? idx - N : -1;\n            neig[b+2] = (j < N-1) ? idx + 1 : -1;\n            neig[b+3] = (i < N-1) ? idx + N : -1;\n        }\n    }\n\n    int best_rot[TOTAL];\n    int best_score = -1;\n    const double time_budget = 1.95;\n\n    // greedy initial solution (connect with already fixed neighbors)\n    {\n        int cur[TOTAL];\n        int rot[TOTAL];\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                int idx = i * N + j;\n                int best_r = 0;\n                int best_conn = -1;\n                for (int r = 0; r < 4; ++r) {\n                    int t = rot_table[init_tiles[idx]][r];\n                    int conn = 0;\n                    if (j > 0) {\n                        int lt = cur[idx - 1];\n                        if (to[t][0] != -1 && to[lt][2] != -1) ++conn;\n                    }\n                    if (i > 0) {\n                        int ut = cur[idx - N];\n                        if (to[t][1] != -1 && to[ut][3] != -1) ++conn;\n                    }\n                    if (conn > best_conn) {\n                        best_conn = conn;\n                        best_r = r;\n                    }\n                }\n                rot[idx] = best_r;\n                cur[idx] = rot_table[init_tiles[idx]][best_r];\n            }\n        }\n        int score = evaluate(cur);\n        // hill climb to improve greedy start\n        bool improved = true;\n        while (improved && elapsed_sec() < time_budget) {\n            improved = false;\n            for (int i = 0; i < TOTAL && elapsed_sec() < time_budget; ++i) {\n                int orig_rot = rot[i];\n                int best_local_sc = score;\n                int best_r = orig_rot;\n                for (int r = 0; r < 4; ++r) {\n                    if (r == orig_rot) continue;\n                    cur[i] = rot_table[init_tiles[i]][r];\n                    int ns = evaluate(cur);\n                    if (ns > best_local_sc) {\n                        best_local_sc = ns;\n                        best_r = r;\n                    }\n                }\n                if (best_r != orig_rot) {\n                    cur[i] = rot_table[init_tiles[i]][best_r];\n                    rot[i] = best_r;\n                    score = best_local_sc;\n                    improved = true;\n                } else {\n                    cur[i] = rot_table[init_tiles[i]][orig_rot];\n                }\n            }\n        }\n        if (score > best_score) {\n            best_score = score;\n            memcpy(best_rot, rot, sizeof(rot));\n        }\n    }\n\n    // restarts with simulated annealing + hill climbing\n    while (elapsed_sec() < 1.85) {\n        int cur[TOTAL];\n        int rot[TOTAL];\n        // random start\n        for (int i = 0; i < TOTAL; ++i) {\n            rot[i] = rand_int(4);\n            cur[i] = rot_table[init_tiles[i]][rot[i]];\n        }\n        int cur_score = evaluate(cur);\n        int restart_best_score = cur_score;\n        int restart_best_rot[TOTAL];\n        memcpy(restart_best_rot, rot, sizeof(rot));\n\n        // simulated annealing\n        double T = 250.0;\n        double alpha = 0.998;\n        const int inner_steps = 30;\n        while (T > 0.15) {\n            if (elapsed_sec() >= 1.85) break;\n            for (int sub = 0; sub < inner_steps; ++sub) {\n                int idx = rand_int(TOTAL);\n                int delta = (rand_int(3) + 1) & 3;\n                if (delta == 0) continue;\n                int old_rot = rot[idx];\n                int new_rot = (old_rot + delta) & 3;\n                int old_type = cur[idx];\n                int new_type = rot_table[init_tiles[idx]][new_rot];\n                if (new_type == old_type) continue;\n\n                cur[idx] = new_type;\n                rot[idx] = new_rot;\n                int new_score = evaluate(cur);\n                int diff = new_score - cur_score;\n                if (diff >= 0 || rand_double() < exp(diff / T)) {\n                    cur_score = new_score;\n                    if (new_score > restart_best_score) {\n                        restart_best_score = new_score;\n                        memcpy(restart_best_rot, rot, sizeof(rot));\n                    }\n                } else {\n                    cur[idx] = old_type;\n                    rot[idx] = old_rot;\n                }\n            }\n            T *= alpha;\n        }\n\n        // hill climb on the best found during this restart\n        if (elapsed_sec() < time_budget) {\n            memcpy(rot, restart_best_rot, sizeof(rot));\n            for (int i = 0; i < TOTAL; ++i) cur[i] = rot_table[init_tiles[i]][rot[i]];\n            bool improved = true;\n            int passes = 0;\n            while (improved && passes < 10 && elapsed_sec() < time_budget) {\n                improved = false;\n                for (int i = 0; i < TOTAL && elapsed_sec() < time_budget; ++i) {\n                    int orig_rot = rot[i];\n                    int best_local_sc = restart_best_score;\n                    int best_r = orig_rot;\n                    for (int r = 0; r < 4; ++r) {\n                        if (r == orig_rot) continue;\n                        cur[i] = rot_table[init_tiles[i]][r];\n                        int ns = evaluate(cur);\n                        if (ns > best_local_sc) {\n                            best_local_sc = ns;\n                            best_r = r;\n                        }\n                    }\n                    if (best_r != orig_rot) {\n                        cur[i] = rot_table[init_tiles[i]][best_r];\n                        rot[i] = best_r;\n                        restart_best_score = best_local_sc;\n                        improved = true;\n                    } else {\n                        cur[i] = rot_table[init_tiles[i]][orig_rot];\n                    }\n                }\n                ++passes;\n            }\n            if (restart_best_score > best_score) {\n                best_score = restart_best_score;\n                memcpy(best_rot, rot, sizeof(rot));\n            }\n        }\n    }\n\n    // final polish on globally best solution\n    if (elapsed_sec() < time_budget - 0.05) {\n        int cur[TOTAL];\n        for (int i = 0; i < TOTAL; ++i) cur[i] = rot_table[init_tiles[i]][best_rot[i]];\n        int cur_score = evaluate(cur);\n        bool improved = true;\n        while (improved && elapsed_sec() < time_budget) {\n            improved = false;\n            for (int i = 0; i < TOTAL && elapsed_sec() < time_budget; ++i) {\n                int orig_rot = best_rot[i];\n                int best_local_sc = cur_score;\n                int best_r = orig_rot;\n                for (int r = 0; r < 4; ++r) {\n                    if (r == orig_rot) continue;\n                    cur[i] = rot_table[init_tiles[i]][r];\n                    int ns = evaluate(cur);\n                    if (ns > best_local_sc) {\n                        best_local_sc = ns;\n                        best_r = r;\n                    }\n                }\n                if (best_r != orig_rot) {\n                    cur[i] = rot_table[init_tiles[i]][best_r];\n                    best_rot[i] = best_r;\n                    cur_score = best_local_sc;\n                    improved = true;\n                } else {\n                    cur[i] = rot_table[init_tiles[i]][orig_rot];\n                }\n            }\n        }\n        if (cur_score > best_score) best_score = cur_score;\n    }\n\n    // output 900 rotation digits\n    for (int i = 0; i < TOTAL; ++i) cout << best_rot[i];\n    cout << endl;\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\nusing uint64 = unsigned long long;\nusing uint16 = unsigned short;\n\nconst int MAXN = 10;\nconst int MAXV = MAXN * MAXN; // 100\n\nint N, T, V;\nint EMPTY_ID;\n\n// Directions: 0:left, 1:up, 2:right, 3:down\nint dir_bit[4] = {1, 2, 4, 8};\nint opp_dir[4] = {2, 3, 0, 1};\nint drow[4] = {0, -1, 0, 1};\nint dcol[4] = {-1, 0, 1, 0};\nchar move_chars[4] = {'L', 'U', 'R', 'D'};\nunordered_map<char, char> opp_char_map = {{'L','R'},{'R','L'},{'U','D'},{'D','U'}};\n\nint tile_has[16][4];\nuint16 mask_has[4], mask_no[4];\n\nvoid precompute_tile_masks() {\n    for (int t=0; t<16; ++t) {\n        for (int d=0; d<4; ++d) {\n            tile_has[t][d] = (t & dir_bit[d]) ? 1 : 0;\n        }\n    }\n    for (int d=0; d<4; ++d) {\n        uint16 m_has = 0;\n        for (int t=0; t<16; ++t) if (tile_has[t][d]) m_has |= (1<<t);\n        mask_has[d] = m_has;\n        mask_no[d] = (~m_has) & 0xFFFF;\n    }\n}\n\n// ---------- CSP (target board reconstruction) ----------\nuint16 dom[MAXN][MAXN];\nint csp_board[MAXN][MAXN];\nbool assigned[MAXN][MAXN];\nint csp_tile_counts[16];\n\nbool dfs_csp(int assigned_cnt) {\n    if (assigned_cnt == V) return true;\n    int best_i=-1, best_j=-1, best_pop=999;\n    for (int i=0; i<N; ++i) {\n        for (int j=0; j<N; ++j) {\n            if (!assigned[i][j]) {\n                int pop = __builtin_popcount(dom[i][j]);\n                if (pop < best_pop) {\n                    best_pop = pop;\n                    best_i = i; best_j = j;\n                }\n            }\n        }\n    }\n    if (best_pop == 0) return false;\n    int i=best_i, j=best_j;\n    uint16 cur_dom = dom[i][j];\n    for (int t=0; t<16; ++t) {\n        if (!(cur_dom & (1<<t))) continue;\n        if (csp_tile_counts[t] == 0) continue;\n        bool ok = true;\n        for (int d=0; d<4; ++d) {\n            int ni = i + drow[d], nj = j + dcol[d];\n            if (ni<0 || ni>=N || nj<0 || nj>=N) continue;\n            if (assigned[ni][nj]) {\n                int nt = csp_board[ni][nj];\n                if (tile_has[t][d] != tile_has[nt][opp_dir[d]]) {\n                    ok = false; break;\n                }\n            }\n        }\n        if (!ok) continue;\n        csp_tile_counts[t]--;\n        assigned[i][j] = true;\n        csp_board[i][j] = t;\n        vector<tuple<int,int,uint16>> saved;\n        for (int d=0; d<4; ++d) {\n            int ni = i + drow[d], nj = j + dcol[d];\n            if (ni<0 || ni>=N || nj<0 || nj>=N) continue;\n            if (!assigned[ni][nj]) {\n                uint16 old = dom[ni][nj];\n                uint16 new_dom;\n                if (tile_has[t][d]) {\n                    new_dom = old & mask_has[opp_dir[d]];\n                } else {\n                    new_dom = old & mask_no[opp_dir[d]];\n                }\n                if (new_dom == 0) { ok = false; break; }\n                if (new_dom != old) {\n                    dom[ni][nj] = new_dom;\n                    saved.push_back({ni,nj,old});\n                }\n            }\n        }\n        if (ok) {\n            if (dfs_csp(assigned_cnt+1)) return true;\n        }\n        for (auto& s : saved) {\n            dom[get<0>(s)][get<1>(s)] = get<2>(s);\n        }\n        assigned[i][j] = false;\n        csp_board[i][j] = -1;\n        csp_tile_counts[t]++;\n    }\n    return false;\n}\n\n// ---------- Hungarian algorithm ----------\nvector<int> hungarian(const vector<vector<int>>& cost) {\n    int n = cost.size();\n    if (n == 0) return {};\n    vector<int> u(n+1, 0), v(n+1, 0), p(n+1, 0), way(n+1, 0);\n    const int INF = 1e9;\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) {\n                if (!used[j]) {\n                    int cur = cost[i0-1][j-1] - u[i0] - v[j];\n                    if (cur < minv[j]) { minv[j] = cur; way[j] = j0; }\n                    if (minv[j] < delta) { delta = minv[j]; 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    vector<int> assignment(n, -1);\n    for (int j=1; j<=n; ++j) {\n        if (p[j] > 0) {\n            assignment[p[j]-1] = j-1;\n        }\n    }\n    return assignment;\n}\n\n// ---------- Node for beam search ----------\nstruct Node {\n    uint8_t board[MAXV];\n    int empty;\n    int h;\n    uint64 hash;\n    int parent;\n    char move;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> T;\n    V = N * N;\n    EMPTY_ID = V - 1; // empty tile gets this ID\n\n    precompute_tile_masks();\n\n    vector<string> grid(N);\n    for (int i=0; i<N; ++i) cin >> grid[i];\n\n    int init_type[MAXN][MAXN];\n    int tile_counts[16] = {0};\n    for (int i=0; i<N; ++i) {\n        for (int j=0; j<N; ++j) {\n            char c = grid[i][j];\n            int t = (c >= '0' && c <= '9') ? (c - '0') : (c - 'a' + 10);\n            init_type[i][j] = t;\n            tile_counts[t]++;\n        }\n    }\n\n    // ---------- target board CSP ----------\n    for (int i=0; i<N; ++i) for (int j=0; j<N; ++j) {\n        uint16 mask = 0xFFFF;\n        if (i == 0) mask &= mask_no[1];      // no up\n        if (i == N-1) mask &= mask_no[3];    // no down\n        if (j == 0) mask &= mask_no[0];      // no left\n        if (j == N-1) mask &= mask_no[2];    // no right\n        if (i == N-2 && j == N-1) mask &= mask_no[3]; // no down to empty\n        if (i == N-1 && j == N-2) mask &= mask_no[2]; // no right to empty\n        if (i == N-1 && j == N-1) mask = (1 << 0);    // only empty tile\n        else mask &= ~(1 << 0);              // empty tile already used\n        dom[i][j] = mask;\n    }\n    memset(assigned, 0, sizeof(assigned));\n    memset(csp_board, -1, sizeof(csp_board));\n    memcpy(csp_tile_counts, tile_counts, sizeof(tile_counts));\n    assigned[N-1][N-1] = true;\n    csp_board[N-1][N-1] = 0;\n    csp_tile_counts[0]--;\n    dom[N-1][N-1] = 0;\n\n    bool csp_ok = dfs_csp(1);\n    assert(csp_ok); // problem guarantees solvable\n\n    // ---------- ID assignment and matching ----------\n    int init_id[MAXN][MAXN];\n    int id_to_type[MAXV];\n    int id_count = 0;\n    for (int i=0; i<N; ++i) for (int j=0; j<N; ++j) {\n        if (init_type[i][j] == 0) {\n            init_id[i][j] = EMPTY_ID;\n            id_to_type[EMPTY_ID] = 0;\n        } else {\n            init_id[i][j] = id_count;\n            id_to_type[id_count] = init_type[i][j];\n            id_count++;\n        }\n    }\n\n    int targetPos[MAXV];\n    targetPos[EMPTY_ID] = (N-1)*N + (N-1);\n\n    vector<int> ids_of_type[16];\n    vector<int> cells_of_type[16];\n    for (int i=0; i<N; ++i) for (int j=0; j<N; ++j) {\n        int t = csp_board[i][j];\n        if (t != 0) {\n            cells_of_type[t].push_back(i*N + j);\n        }\n    }\n    for (int id=0; id<EMPTY_ID; ++id) {\n        int t = id_to_type[id];\n        ids_of_type[t].push_back(id);\n    }\n\n    // initial positions of IDs\n    int initPos[MAXV];\n    for (int i=0; i<N; ++i) for (int j=0; j<N; ++j) {\n        initPos[init_id[i][j]] = i*N + j;\n    }\n\n    for (int t=1; t<16; ++t) {\n        int n = ids_of_type[t].size();\n        if (n == 0) continue;\n        vector<vector<int>> cost(n, vector<int>(n));\n        for (int i=0; i<n; ++i) {\n            int id = ids_of_type[t][i];\n            int r1 = initPos[id] / N, c1 = initPos[id] % N;\n            for (int j=0; j<n; ++j) {\n                int cell = cells_of_type[t][j];\n                int r2 = cell / N, c2 = cell % N;\n                cost[i][j] = abs(r1-r2) + abs(c1-c2);\n            }\n        }\n        vector<int> assignment = hungarian(cost);\n        for (int i=0; i<n; ++i) {\n            int id = ids_of_type[t][i];\n            int j = assignment[i];\n            targetPos[id] = cells_of_type[t][j];\n        }\n    }\n\n    // ---------- Manhattan distance table ----------\n    int manDist[MAXV][MAXV];\n    for (int id=0; id<V; ++id) {\n        int tr = targetPos[id] / N, tc = targetPos[id] % N;\n        for (int cell=0; cell<V; ++cell) {\n            int r = cell / N, c = cell % N;\n            manDist[id][cell] = abs(tr-r) + abs(tc-c);\n        }\n    }\n\n    // ---------- Zobrist hashing ----------\n    mt19937_64 rng(12345);\n    uint64 zob[MAXV][MAXV];\n    for (int id=0; id<V; ++id)\n        for (int cell=0; cell<V; ++cell)\n            zob[id][cell] = rng();\n\n    // ---------- Initial state ----------\n    Node root;\n    for (int i=0; i<N; ++i)\n        for (int j=0; j<N; ++j)\n            root.board[i*N+j] = init_id[i][j];\n\n    int init_h = 0;\n    uint64 init_hash = 0;\n    for (int cell=0; cell<V; ++cell) {\n        int id = root.board[cell];\n        if (id == EMPTY_ID) root.empty = cell;\n        init_h += manDist[id][cell];\n        init_hash ^= zob[id][cell];\n    }\n    root.h = init_h;\n    root.hash = init_hash;\n    root.parent = -1;\n    root.move = 0;\n\n    if (init_h == 0) {\n        cout << \"\" << endl;\n        return 0;\n    }\n\n    // ---------- Beam search ----------\n    vector<Node> nodes;\n    nodes.reserve(400000);\n    unordered_set<uint64_t> global_hash;\n    global_hash.reserve(400000);\n\n    nodes.push_back(root);\n    global_hash.insert(root.hash);\n\n    vector<int> current_beam = {0};\n    int goal_node = -1;\n    int best_h_node = 0;\n    int best_h = init_h;\n    const int beam_width = 150;\n\n    clock_t start_time = clock();\n    const double TIME_LIMIT = 2.8 * CLOCKS_PER_SEC;\n\n    for (int depth = 0; depth < T; ++depth) {\n        if (clock() - start_time > TIME_LIMIT) break;\n        vector<int> next_nodes;\n        for (int idx : current_beam) {\n            Node& cur = nodes[idx];\n            int e = cur.empty;\n            int r = e / N, c = e % N;\n            for (int d=0; d<4; ++d) {\n                int nr = r + drow[d], nc = c + dcol[d];\n                if (nr<0 || nr>=N || nc<0 || nc>=N) continue;\n                if (cur.move != 0) {\n                    if (move_chars[d] == opp_char_map[cur.move]) continue;\n                }\n                int neighbor = nr*N + nc;\n                int tileID = cur.board[neighbor];\n\n                Node next;\n                memcpy(next.board, cur.board, V * sizeof(uint8_t));\n                next.board[e] = tileID;\n                next.board[neighbor] = EMPTY_ID;\n                next.empty = neighbor;\n\n                uint64 new_hash = cur.hash;\n                new_hash ^= zob[tileID][e] ^ zob[tileID][neighbor] ^ zob[EMPTY_ID][neighbor] ^ zob[EMPTY_ID][e];\n                next.hash = new_hash;\n                if (global_hash.count(new_hash)) continue;\n\n                int new_h = cur.h;\n                new_h += manDist[tileID][e] - manDist[tileID][neighbor];\n                new_h += manDist[EMPTY_ID][neighbor] - manDist[EMPTY_ID][e];\n                next.h = new_h;\n                next.parent = idx;\n                next.move = move_chars[d];\n\n                if (new_h == 0) goal_node = nodes.size();\n\n                nodes.push_back(next);\n                global_hash.insert(new_hash);\n                next_nodes.push_back(nodes.size()-1);\n\n                if (new_h < best_h) {\n                    best_h = new_h;\n                    best_h_node = nodes.size()-1;\n                }\n                if (goal_node != -1) break;\n            }\n            if (goal_node != -1) break;\n        }\n        if (goal_node != -1) break;\n        if (next_nodes.empty()) break;\n\n        sort(next_nodes.begin(), next_nodes.end(), [&](int a, int b) {\n            return nodes[a].h < nodes[b].h;\n        });\n        if (next_nodes.size() > beam_width) next_nodes.resize(beam_width);\n        current_beam = move(next_nodes);\n    }\n\n    // ---------- Output ----------\n    int out_node = (goal_node != -1) ? goal_node : best_h_node;\n    string seq;\n    while (nodes[out_node].parent != -1) {\n        seq.push_back(nodes[out_node].move);\n        out_node = nodes[out_node].parent;\n    }\n    reverse(seq.begin(), seq.end());\n    if ((int)seq.length() > T) seq = seq.substr(0, T);\n    cout << seq << endl;\n\n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <numeric>\n#include <cmath>\n#include <climits>\n#include <tuple>\n\nusing namespace std;\n\nstruct Point { int x, y; };\nstruct Line { int p1x, p1y, p2x, p2y; };\n\nvector<int> a(11);\nint total_attendees;\nvector<Point> pts;\nint N, K;\n\n// ----- geometry helpers -----\nlong long cross(const Line& L, const Point& p) {\n    return (long long)(L.p2x - L.p1x) * (p.y - L.p1y) -\n           (long long)(L.p2y - L.p1y) * (p.x - L.p1x);\n}\n\nbool line_intersects_circle(const Line& L) {\n    long long dx = L.p2x - L.p1x;\n    long long dy = L.p2y - L.p1y;\n    long long cross_val = llabs((long long)L.p1x * L.p2y - (long long)L.p1y * L.p2x);\n    long long lhs = cross_val * cross_val;\n    long long rhs = 100000000LL * (dx * dx + dy * dy);\n    return lhs <= rhs;\n}\n\n// ----- state representation -----\nstruct State {\n    vector<int> cell_of_point;\n    vector<int> cell_count;\n    vector<vector<int>> cell_points;\n    int real_score;            // sum_{d=1..10} min(a[d], b[d])\n};\n\nint compute_real_score(const vector<int>& cell_count) {\n    int b[11] = {0};\n    for (int cnt : cell_count)\n        if (cnt >= 1 && cnt <= 10) b[cnt]++;\n    int res = 0;\n    for (int d = 1; d <= 10; ++d) res += min(a[d], b[d]);\n    return res;\n}\n\nState build_initial_state() {\n    State st;\n    st.cell_of_point.assign(N, 0);\n    st.cell_count = {N};\n    st.cell_points = { vector<int>(N) };\n    iota(st.cell_points[0].begin(), st.cell_points[0].end(), 0);\n    st.real_score = compute_real_score(st.cell_count);\n    return st;\n}\n\n// returns (new_count, bits, score) ; score is real_score, -1 if hits a strawberry\ntuple<vector<int>, vector<int>, int> simulate(const State& st, const Line& L) {\n    int C = st.cell_count.size();\n    vector<int> new_count(2 * C, 0);\n    vector<int> bits(N);\n    long long dx = L.p2x - L.p1x;\n    long long dy = L.p2y - L.p1y;\n    for (int i = 0; i < N; ++i) {\n        int old_c = st.cell_of_point[i];\n        long long px = pts[i].x - L.p1x;\n        long long py = pts[i].y - L.p1y;\n        long long c = dx * py - dy * px;\n        if (c == 0) return { {}, {}, -1 };\n        int bit = (c > 0) ? 1 : 0;\n        bits[i] = bit;\n        new_count[old_c * 2 + bit]++;\n    }\n    int score = compute_real_score(new_count);\n    return {new_count, bits, score};\n}\n\nvoid apply_line(State& st, const vector<int>& new_count, const vector<int>& bits) {\n    int C = st.cell_count.size();\n    vector<int> new_cell_id(2 * C, -1);\n    int new_C = 0;\n    for (int c = 0; c < 2 * C; ++c)\n        if (new_count[c] > 0) new_cell_id[c] = new_C++;\n    st.cell_count.resize(new_C);\n    st.cell_points.assign(new_C, vector<int>());\n    for (int c = 0; c < 2 * C; ++c) {\n        if (new_count[c] > 0) {\n            int nid = new_cell_id[c];\n            st.cell_count[nid] = new_count[c];\n            st.cell_points[nid].reserve(new_count[c]);\n        }\n    }\n    for (int i = 0; i < N; ++i) {\n        int old_c = st.cell_of_point[i];\n        int nid = new_cell_id[old_c * 2 + bits[i]];\n        st.cell_of_point[i] = nid;\n        st.cell_points[nid].push_back(i);\n    }\n    st.real_score = compute_real_score(st.cell_count);\n}\n\n// ----- candidate generators (tuned) -----\nLine random_line_through_cake(mt19937& rng) {\n    uniform_int_distribution<int> dist_coord(-10000, 10000);\n    uniform_int_distribution<int> dist_d(-1000, 1000);\n    while (true) {\n        int x = dist_coord(rng);\n        int y = dist_coord(rng);\n        if ((long long)x * x + (long long)y * y < 100000000LL) {\n            int dx = dist_d(rng);\n            int dy = dist_d(rng);\n            if (dx == 0 && dy == 0) dx = 1;\n            return {x, y, x + dx, y + dy};\n        }\n    }\n}\n\nLine random_boundary_line(mt19937& rng) {\n    const double PI = acos(-1.0);\n    uniform_real_distribution<double> angle_dist(0, 2 * PI);\n    double a1 = angle_dist(rng);\n    double a2 = angle_dist(rng);\n    int p1x = (int)round(10000 * cos(a1));\n    int p1y = (int)round(10000 * sin(a1));\n    int p2x = (int)round(10000 * cos(a2));\n    int p2y = (int)round(10000 * sin(a2));\n    if (p1x == p2x && p1y == p2y) p1x++;\n    return {p1x, p1y, p2x, p2y};\n}\n\nLine random_cell_split_line(const State& st, mt19937& rng) {\n    const auto& cell_points = st.cell_points;\n    vector<int> valid_cells;\n    for (int c = 0; c < (int)cell_points.size(); ++c)\n        if (cell_points[c].size() >= 2) valid_cells.push_back(c);\n    if (valid_cells.empty()) return random_line_through_cake(rng);\n    uniform_int_distribution<int> dist_cell(0, valid_cells.size() - 1);\n    int c = valid_cells[dist_cell(rng)];\n    const auto& pvec = cell_points[c];\n    uniform_int_distribution<int> dist_pt(0, pvec.size() - 1);\n    int i1 = pvec[dist_pt(rng)];\n    int i2 = pvec[dist_pt(rng)];\n    while (i2 == i1) i2 = pvec[dist_pt(rng)];\n    Point p1 = pts[i1], p2 = pts[i2];\n    int mx = (p1.x + p2.x) / 2;\n    int my = (p1.y + p2.y) / 2;\n    uniform_int_distribution<int> dist_d(-200, 200);\n    int dx = dist_d(rng);\n    int dy = dist_d(rng);\n    if (dx == 0 && dy == 0) dx = 1;\n    Line L = {mx, my, mx + dx, my + dy};\n    long long c1 = cross(L, p1), c2 = cross(L, p2);\n    if (c1 == 0 || c2 == 0 || (c1 > 0) == (c2 > 0)) {\n        int ndx = -dy, ndy = dx;\n        L = {mx, my, mx + ndx, my + ndy};\n        c1 = cross(L, p1); c2 = cross(L, p2);\n        if (c1 == 0 || c2 == 0 || (c1 > 0) == (c2 > 0))\n            return random_line_through_cake(rng);\n    }\n    return L;\n}\n\nLine random_separating_line(mt19937& rng) {\n    uniform_int_distribution<int> dist_pt(0, N - 1);\n    int i1 = dist_pt(rng);\n    int i2 = dist_pt(rng);\n    while (i2 == i1) i2 = dist_pt(rng);\n    Point p1 = pts[i1], p2 = pts[i2];\n    int mx = (p1.x + p2.x) / 2;\n    int my = (p1.y + p2.y) / 2;\n    uniform_int_distribution<int> dist_d(-1000, 1000);\n    int dx = dist_d(rng);\n    int dy = dist_d(rng);\n    if (dx == 0 && dy == 0) dx = 1;\n    Line L = {mx, my, mx + dx, my + dy};\n    long long c1 = cross(L, p1), c2 = cross(L, p2);\n    if (c1 == 0 || c2 == 0 || (c1 > 0) == (c2 > 0)) {\n        swap(dx, dy); dx = -dx;\n        L = {mx, my, mx + dx, my + dy};\n        c1 = cross(L, p1); c2 = cross(L, p2);\n        if (c1 == 0 || c2 == 0 || (c1 > 0) == (c2 > 0))\n            return random_line_through_cake(rng);\n    }\n    return L;\n}\n\nLine perturb_existing_line(const vector<Line>& lines, mt19937& rng) {\n    if (lines.empty()) return random_line_through_cake(rng);\n    uniform_int_distribution<int> dist_idx(0, lines.size() - 1);\n    uniform_int_distribution<int> dist_delta(-300, 300);\n    uniform_int_distribution<int> dist_coord(0, 3);\n    Line L = lines[dist_idx(rng)];\n    int delta = dist_delta(rng);\n    int coord = dist_coord(rng);\n    if (coord == 0) L.p1x += delta;\n    else if (coord == 1) L.p1y += delta;\n    else if (coord == 2) L.p2x += delta;\n    else L.p2y += delta;\n    if (L.p1x == L.p2x && L.p1y == L.p2y) L.p1x++;\n    return L;\n}\n\nLine targeted_candidate(const State& st, mt19937& rng) {\n    vector<int> need(11, 0);\n    for (int d = 1; d <= 10; ++d) {\n        int bd = 0;\n        for (int cnt : st.cell_count) if (cnt == d) bd++;\n        if (bd < a[d]) need[d] = a[d] - bd;\n    }\n    bool any_need = false;\n    for (int d = 1; d <= 10; ++d) if (need[d] > 0) any_need = true;\n    if (!any_need) return random_line_through_cake(rng);\n\n    vector<int> unmet;\n    for (int d = 1; d <= 10; ++d) if (need[d] > 0) unmet.push_back(d);\n    uniform_int_distribution<int> dist_d(0, unmet.size() - 1);\n    int d = unmet[dist_d(rng)];\n\n    vector<int> cells;\n    for (int c = 0; c < (int)st.cell_count.size(); ++c)\n        if (st.cell_count[c] >= d + 1) cells.push_back(c);\n    if (cells.empty()) return random_line_through_cake(rng);\n\n    uniform_int_distribution<int> dist_cell(0, cells.size() - 1);\n    int c = cells[dist_cell(rng)];\n    const auto& pvec = st.cell_points[c];\n    int sz = pvec.size();\n    if (sz < d + 1) return random_line_through_cake(rng);\n\n    // attempt to separate d random points from the rest\n    vector<int> perm(sz);\n    iota(perm.begin(), perm.end(), 0);\n    shuffle(perm.begin(), perm.end(), rng);\n    vector<Point> A(d), B(sz - d);\n    for (int i = 0; i < d; ++i) A[i] = pts[pvec[perm[i]]];\n    for (int i = d; i < sz; ++i) B[i - d] = pts[pvec[perm[i]]];\n\n    // try 30 random angles\n    const double PI = acos(-1.0);\n    uniform_real_distribution<double> angle_dist(0, 2 * PI);\n    for (int attempt = 0; attempt < 30; ++attempt) {\n        double angle = angle_dist(rng);\n        long long dx = (long long)(cos(angle) * 10000);\n        long long dy = (long long)(sin(angle) * 10000);\n        if (dx == 0 && dy == 0) continue;\n        long long minA = LLONG_MAX, maxA = LLONG_MIN;\n        for (const auto& p : A) {\n            long long proj = dx * p.x + dy * p.y;\n            minA = min(minA, proj); maxA = max(maxA, proj);\n        }\n        long long minB = LLONG_MAX, maxB = LLONG_MIN;\n        for (const auto& p : B) {\n            long long proj = dx * p.x + dy * p.y;\n            minB = min(minB, proj); maxB = max(maxB, proj);\n        }\n        if (maxA < minB) {\n            long long mid = (maxA + minB) / 2;\n            if (dx == 0) {\n                int py = (int)(mid / dy);\n                return {0, py, 10000, (int)((mid - dx * 10000) / dy)};\n            } else if (dy != 0) {\n                return {0, (int)(mid / dy), 10000, (int)((mid - dx * 10000) / dy)};\n            } else {\n                int px = (int)(mid / dx);\n                return {px, 0, px, 10000};\n            }\n        } else if (maxB < minA) {\n            long long mid = (maxB + minA) / 2;\n            if (dx == 0) {\n                int py = (int)(mid / dy);\n                return {0, py, 10000, (int)((mid - dx * 10000) / dy)};\n            } else if (dy != 0) {\n                return {0, (int)(mid / dy), 10000, (int)((mid - dx * 10000) / dy)};\n            } else {\n                int px = (int)(mid / dx);\n                return {px, 0, px, 10000};\n            }\n        }\n    }\n    return random_line_through_cake(rng);\n}\n\n// ----- trial runner -----\nvector<Line> run_trial(mt19937& rng, chrono::steady_clock::time_point start, double limit) {\n    auto remain = [&]() { return chrono::duration<double>(chrono::steady_clock::now() - start).count() < limit; };\n\n    State st = build_initial_state();\n    vector<Line> lines;\n\n    // Greedy addition up to K lines\n    while ((int)lines.size() < K && remain()) {\n        int best_score = -1;\n        Line best_line;\n        vector<int> best_new_count, best_bits;\n        for (int t = 0; t < 120; ++t) {\n            if (!remain()) break;\n            Line cand;\n            int type = uniform_int_distribution<int>(0, 12)(rng);\n            if (type < 2) cand = random_boundary_line(rng);\n            else if (type < 4) cand = random_line_through_cake(rng);\n            else if (type < 6) cand = random_cell_split_line(st, rng);\n            else if (type < 8) cand = random_separating_line(rng);\n            else if (type < 10) cand = perturb_existing_line(lines, rng);\n            else cand = targeted_candidate(st, rng);\n            if (!line_intersects_circle(cand)) continue;\n            auto [new_count, bits, score] = simulate(st, cand);\n            if (score < 0) continue;\n            if (score > best_score) {\n                best_score = score;\n                best_line = cand;\n                best_new_count = std::move(new_count);\n                best_bits = std::move(bits);\n            }\n        }\n        if (best_score < 0) {   // fallback\n            while (remain()) {\n                Line cand = random_line_through_cake(rng);\n                if (!line_intersects_circle(cand)) continue;\n                auto [new_count, bits, score] = simulate(st, cand);\n                if (score >= 0) {\n                    best_line = cand;\n                    best_new_count = std::move(new_count);\n                    best_bits = std::move(bits);\n                    break;\n                }\n            }\n        }\n        if (!remain()) break;\n        apply_line(st, best_new_count, best_bits);\n        lines.push_back(best_line);\n    }\n\n    // Local search: while time permits, replace lines\n    while (remain()) {\n        bool improved = false;\n        vector<int> order(lines.size());\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n        for (int idx : order) {\n            if (!remain()) break;\n            Line old_line = lines[idx];\n            State curr = build_initial_state();\n            for (int j = 0; j < (int)lines.size(); ++j) {\n                if (j == idx) continue;\n                auto [new_count, bits, score] = simulate(curr, lines[j]);\n                apply_line(curr, new_count, bits);\n            }\n            int best_score = curr.real_score;\n            Line best_line;\n            vector<int> best_new_count, best_bits;\n            for (int t = 0; t < 100; ++t) {\n                if (!remain()) break;\n                Line cand;\n                int type = uniform_int_distribution<int>(0, 12)(rng);\n                if (type < 2) cand = random_boundary_line(rng);\n                else if (type < 4) cand = random_line_through_cake(rng);\n                else if (type < 6) cand = random_cell_split_line(curr, rng);\n                else if (type < 8) cand = random_separating_line(rng);\n                else if (type < 10) cand = perturb_existing_line(lines, rng);\n                else cand = targeted_candidate(curr, rng);\n                if (!line_intersects_circle(cand)) continue;\n                auto [new_count, bits, score] = simulate(curr, cand);\n                if (score < 0) continue;\n                if (score > best_score) {\n                    best_score = score;\n                    best_line = cand;\n                    best_new_count = std::move(new_count);\n                    best_bits = std::move(bits);\n                }\n            }\n            if (best_score > curr.real_score) {\n                lines[idx] = best_line;\n                improved = true;\n            } else {\n                lines[idx] = old_line;\n            }\n        }\n        if (!improved) break;\n        // rebuild state\n        st = build_initial_state();\n        for (const Line& L : lines) {\n            auto [new_count, bits, score] = simulate(st, L);\n            apply_line(st, new_count, bits);\n        }\n    }\n\n    return lines;\n}\n\n// ----- main -----\nint main() {\n    ios::sync_with_stdio(false); cin.tie(0);\n    auto start_time = chrono::steady_clock::now();\n\n    cin >> N >> K;\n    total_attendees = 0;\n    for (int d = 1; d <= 10; ++d) { cin >> a[d]; total_attendees += a[d]; }\n    pts.resize(N);\n    for (int i = 0; i < N; ++i) cin >> pts[i].x >> pts[i].y;\n\n    const double TOTAL_TIME = 2.95;\n    vector<Line> best_lines;\n    int best_real = -1;\n\n    mt19937 base_rng(chrono::steady_clock::now().time_since_epoch().count());\n    int trial = 0;\n    // Run several independent trials with different seeds.\n    while (chrono::duration<double>(chrono::steady_clock::now() - start_time).count() < TOTAL_TIME) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n        double remaining = TOTAL_TIME - elapsed;\n        // allocate at most 0.5s per trial, but at least 0.1s\n        double limit = min(remaining, 0.5);\n        if (limit < 0.1) break;\n        auto end_time = start_time + chrono::microseconds((long long)(limit * 1e6));\n        mt19937 rng(base_rng() + trial * 12345);\n        vector<Line> lines = run_trial(rng, start_time, chrono::duration<double>(end_time - start_time).count());\n        int real = -1;\n        if (!lines.empty()) {\n            // verify score\n            State st = build_initial_state();\n            bool valid = true;\n            for (const Line& L : lines) {\n                auto [new_count, bits, score] = simulate(st, L);\n                if (score < 0) { valid = false; break; }\n                apply_line(st, new_count, bits);\n            }\n            if (valid) real = st.real_score;\n        }\n        if (real > best_real) {\n            best_real = real;\n            best_lines = lines;\n        }\n        trial++;\n    }\n\n    // Output the best found solution\n    cout << best_lines.size() << \"\\n\";\n    for (const Line& L : best_lines) {\n        cout << L.p1x << \" \" << L.p1y << \" \" << L.p2x << \" \" << L.p2y << \"\\n\";\n    }\n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <array>\n#include <algorithm>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nstruct Pt { int x, y; };\n\nint main() {\n    auto global_start = chrono::steady_clock::now();\n    auto elapsed = [&]() { return chrono::duration<double>(chrono::steady_clock::now() - global_start).count(); };\n\n    int N, M;\n    cin >> N >> M;\n    vector<Pt> initial_dots(M);\n    for (int i = 0; i < M; ++i) cin >> initial_dots[i].x >> initial_dots[i].y;\n\n    int c = (N - 1) / 2;\n    vector<vector<int>> weight(N, vector<int>(N));\n    long long S = 0, initial_sum = 0;\n    for (int x = 0; x < N; ++x) for (int y = 0; y < N; ++y) {\n        weight[x][y] = (x - c) * (x - c) + (y - c) * (y - c) + 1;\n        S += weight[x][y];\n    }\n    for (auto& p : initial_dots) initial_sum += weight[p.x][p.y];\n\n    auto run_sim = [&](uint64_t seed) {\n        mt19937 rng(static_cast<unsigned int>(seed));\n\n        vector<vector<bool>> dot(N, vector<bool>(N, false));\n        vector<vector<bool>> used_h(N - 1, vector<bool>(N, false));\n        vector<vector<bool>> used_v(N, vector<bool>(N - 1, false));\n        vector<vector<bool>> used_d1(N - 1, vector<bool>(N - 1, false));\n        vector<vector<bool>> used_d2(N - 1, vector<bool>(N, false));\n        vector<vector<int>> row_dots(N), col_dots(N);\n        int diag_offs = N - 1;\n        vector<vector<int>> diag1(2 * N - 1), diag2(2 * N - 1);\n\n        for (auto& p : initial_dots) {\n            int x = p.x, y = p.y;\n            dot[x][y] = true;\n            row_dots[y].push_back(x);\n            col_dots[x].push_back(y);\n            int enc = y * N + x;\n            diag1[x - y + diag_offs].push_back(enc);\n            diag2[x + y].push_back(enc);\n        }\n        long long cur_sum = initial_sum;\n        vector<array<Pt, 4>> history;\n\n        auto segment_check = [&](Pt a, Pt b, bool check_only) -> bool {\n            int dx = b.x - a.x, dy = b.y - a.y;\n            int steps = max(abs(dx), abs(dy));\n            int sx = (dx == 0 ? 0 : (dx > 0 ? 1 : -1));\n            int sy = (dy == 0 ? 0 : (dy > 0 ? 1 : -1));\n            int cx = a.x, cy = a.y;\n            for (int s = 1; s <= steps; ++s) {\n                int nx = cx + sx, ny = cy + sy;\n                if (s < steps && dot[nx][ny]) return false;\n                if (sx != 0 && sy == 0) {\n                    int x = min(cx, nx), y = cy;\n                    if (check_only) { if (used_h[x][y]) return false; }\n                    else used_h[x][y] = true;\n                } else if (sx == 0 && sy != 0) {\n                    int x = cx, y = min(cy, ny);\n                    if (check_only) { if (used_v[x][y]) return false; }\n                    else used_v[x][y] = true;\n                } else if (sx == 1 && sy == 1) {\n                    if (check_only) { if (used_d1[cx][cy]) return false; }\n                    else used_d1[cx][cy] = true;\n                } else if (sx == -1 && sy == -1) {\n                    if (check_only) { if (used_d1[nx][ny]) return false; }\n                    else used_d1[nx][ny] = true;\n                } else if (sx == 1 && sy == -1) {\n                    if (check_only) { if (used_d2[cx][cy]) return false; }\n                    else used_d2[cx][cy] = true;\n                } else if (sx == -1 && sy == 1) {\n                    if (check_only) { if (used_d2[nx][ny]) return false; }\n                    else used_d2[nx][ny] = true;\n                } else return false;\n                cx = nx; cy = ny;\n            }\n            return true;\n        };\n\n        auto is_valid = [&](const array<Pt, 4>& p) {\n            if (dot[p[0].x][p[0].y]) return false;\n            if (!dot[p[1].x][p[1].y] || !dot[p[2].x][p[2].y] || !dot[p[3].x][p[3].y]) return false;\n            for (int i = 0; i < 4; ++i)\n                if (!segment_check(p[i], p[(i + 1) % 4], true)) return false;\n            return true;\n        };\n\n        auto apply_move = [&](const array<Pt, 4>& p) {\n            int x0 = p[0].x, y0 = p[0].y;\n            dot[x0][y0] = true;\n            row_dots[y0].push_back(x0);\n            col_dots[x0].push_back(y0);\n            int enc = y0 * N + x0;\n            diag1[x0 - y0 + diag_offs].push_back(enc);\n            diag2[x0 + y0].push_back(enc);\n            cur_sum += weight[x0][y0];\n            for (int i = 0; i < 4; ++i)\n                segment_check(p[i], p[(i + 1) % 4], false);\n        };\n\n        auto add_axis_small = [&](int x, int y, vector<array<Pt, 4>>& cands) {\n            if (x + 1 < N && y + 1 < N) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x + 1, y}, Pt{x + 1, y + 1}, Pt{x, y + 1}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n            if (x > 0 && y + 1 < N) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x, y + 1}, Pt{x - 1, y + 1}, Pt{x - 1, y}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n            if (x > 0 && y > 0) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x - 1, y}, Pt{x - 1, y - 1}, Pt{x, y - 1}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n            if (x + 1 < N && y > 0) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x, y - 1}, Pt{x + 1, y - 1}, Pt{x + 1, y}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n        };\n\n        auto add_diamond_small = [&](int x, int y, vector<array<Pt, 4>>& cands) {\n            if (x + 2 < N && y >= 1 && y + 1 < N) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x + 1, y + 1}, Pt{x + 2, y}, Pt{x + 1, y - 1}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n            if (x >= 1 && x + 1 < N && y >= 2) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x + 1, y - 1}, Pt{x, y - 2}, Pt{x - 1, y - 1}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n            if (x >= 2 && y >= 1 && y + 1 < N) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x - 1, y - 1}, Pt{x - 2, y}, Pt{x - 1, y + 1}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n            if (x >= 1 && x + 1 < N && y + 2 < N) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x - 1, y + 1}, Pt{x, y + 2}, Pt{x + 1, y + 1}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n        };\n\n        auto add_axis_large = [&](int x1, int y1, vector<array<Pt, 4>>& cands) {\n            for (int x2 : row_dots[y1]) {\n                if (x2 == x1) continue;\n                for (int y2 : col_dots[x1]) {\n                    if (y2 == y1) continue;\n                    if (!dot[x2][y2]) continue;\n                    array<Pt, 4> p = {Pt{x1, y1}, Pt{x2, y1}, Pt{x2, y2}, Pt{x1, y2}};\n                    if (is_valid(p)) cands.push_back(p);\n                }\n            }\n        };\n\n        auto add_general_diamond = [&](int x1, int y1, vector<array<Pt, 4>>& cands) {\n            int d1 = x1 - y1 + diag_offs;\n            int d2 = x1 + y1;\n            const auto& list1 = diag1[d1];\n            const auto& list2 = diag2[d2];\n            for (int enc2 : list1) {\n                int x2 = enc2 % N, y2 = enc2 / N;\n                if (x2 == x1 && y2 == y1) continue;\n                for (int enc4 : list2) {\n                    int x4 = enc4 % N, y4 = enc4 / N;\n                    if (x4 == x1 && y4 == y1) continue;\n                    int x3 = x2 + x4 - x1;\n                    int y3 = y2 + y4 - y1;\n                    if (x3 < 0 || x3 >= N || y3 < 0 || y3 >= N) continue;\n                    if (!dot[x3][y3]) continue;\n                    array<Pt, 4> p = {Pt{x1, y1}, Pt{x2, y2}, Pt{x3, y3}, Pt{x4, y4}};\n                    if (is_valid(p)) cands.push_back(p);\n                }\n            }\n        };\n\n        while (true) {\n            // Time check: stop this simulation if total time is nearly exhausted\n            if (elapsed() > 4.85) break;\n\n            vector<array<Pt, 4>> cands;\n            // collect all small moves (axis\u2011aligned and diamond unit squares)\n            for (int x = 0; x < N; ++x)\n                for (int y = 0; y < N; ++y) {\n                    if (dot[x][y]) continue;\n                    add_axis_small(x, y, cands);\n                    add_diamond_small(x, y, cands);\n                }\n\n            // if no small move exists, generate larger moves from the highest\u2011weight empty cells\n            if (cands.empty()) {\n                vector<int> empty_idx;\n                for (int x = 0; x < N; ++x)\n                    for (int y = 0; y < N; ++y)\n                        if (!dot[x][y])\n                            empty_idx.push_back(y * N + x);\n\n                sort(empty_idx.begin(), empty_idx.end(), [&](int a, int b) {\n                    return weight[a % N][a / N] > weight[b % N][b / N];\n                });\n\n                const int MAX_LARGE_CANDS = 50;   // collect at most this many large candidates\n                for (int enc : empty_idx) {\n                    if ((int)cands.size() >= MAX_LARGE_CANDS) break;\n                    int x = enc % N, y = enc / N;\n                    add_axis_large(x, y, cands);\n                    if ((int)cands.size() >= MAX_LARGE_CANDS) break;\n                    add_general_diamond(x, y, cands);\n                }\n                if (cands.empty()) break;   // no moves left at all\n            }\n\n            // evaluate candidates\n            vector<int> w(cands.size());\n            for (size_t i = 0; i < cands.size(); ++i)\n                w[i] = weight[cands[i][0].x][cands[i][0].y];\n\n            int max_w = *max_element(w.begin(), w.end());\n            vector<int> best_idx;\n            for (size_t i = 0; i < cands.size(); ++i)\n                if (w[i] == max_w) best_idx.push_back(static_cast<int>(i));\n\n            int pick;\n            // 80% chance to pick among the best, 20% random\n            if (best_idx.size() == cands.size() || (rng() % 100) < 80) {\n                pick = best_idx[rng() % best_idx.size()];\n            } else {\n                pick = rng() % cands.size();\n            }\n\n            apply_move(cands[pick]);\n            history.push_back(cands[pick]);\n        }\n        return make_pair(cur_sum, history);\n    };\n\n    long long best_sum = -1;\n    vector<array<Pt, 4>> best_hist;\n    int sim = 0;\n    while (true) {\n        if (elapsed() > 4.85) break;\n        uint64_t seed = chrono::steady_clock::now().time_since_epoch().count() + sim * 12345;\n        auto [sum, hist] = run_sim(seed);\n        if (sum > best_sum) {\n            best_sum = sum;\n            best_hist = move(hist);\n        }\n        ++sim;\n    }\n\n    cout << best_hist.size() << \"\\n\";\n    for (auto& p : best_hist) {\n        cout << p[0].x << \" \" << p[0].y << \" \"\n             << p[1].x << \" \" << p[1].y << \" \"\n             << p[2].x << \" \" << p[2].y << \" \"\n             << p[3].x << \" \" << p[3].y << \"\\n\";\n    }\n    return 0;\n}","ahc015":"#include <iostream>\n#include <cstring>\n#include <algorithm>\n#include <vector>\nusing namespace std;\n\nconst char DIR[4] = {'F', 'B', 'L', 'R'};\n\n// ---------- fast RNG ----------\nstatic unsigned rng_state = 123456789u;\ninline int xrand() {\n    rng_state ^= rng_state << 13;\n    rng_state ^= rng_state >> 17;\n    rng_state ^= rng_state << 5;\n    return rng_state & 0x7fffffff;\n}\n\n// ---------- BFS for connected components ----------\nint q[100];\nint vis[100];\nint vis_ver = 0;\n\nint comp_id_buf[100];\nint comp_size_buf[100];\nint comp_count_buf;\n\nint bfs_with_components(const int* b) {\n    ++vis_ver;\n    comp_count_buf = 0;\n    int tot = 0;\n    for (int i = 0; i < 100; ++i) {\n        if (b[i] && vis[i] != vis_ver) {\n            int f = b[i];\n            int head = 0, tail = 0;\n            q[tail++] = i;\n            vis[i] = vis_ver;\n            int sz = 0;\n            while (head < tail) {\n                int idx = q[head++];\n                ++sz;\n                comp_id_buf[idx] = comp_count_buf;\n                int r = idx / 10, c = idx % 10;\n                if (r > 0) {\n                    int ni = idx - 10;\n                    if (b[ni] == f && vis[ni] != vis_ver)\n                        vis[ni] = vis_ver, q[tail++] = ni;\n                }\n                if (r < 9) {\n                    int ni = idx + 10;\n                    if (b[ni] == f && vis[ni] != vis_ver)\n                        vis[ni] = vis_ver, q[tail++] = ni;\n                }\n                if (c > 0) {\n                    int ni = idx - 1;\n                    if (b[ni] == f && vis[ni] != vis_ver)\n                        vis[ni] = vis_ver, q[tail++] = ni;\n                }\n                if (c < 9) {\n                    int ni = idx + 1;\n                    if (b[ni] == f && vis[ni] != vis_ver)\n                        vis[ni] = vis_ver, q[tail++] = ni;\n                }\n            }\n            comp_size_buf[comp_count_buf] = sz;\n            ++comp_count_buf;\n            tot += sz * sz;\n        }\n    }\n    return tot;\n}\n\n// ---------- tilt operation ----------\nvoid tilt(const int* src, int dir, int* dst) {\n    if (dir == 0) {  // Forward\n        for (int c = 0; c < 10; ++c) {\n            int d = 0;\n            for (int r = 0; r < 10; ++r) {\n                int v = src[r * 10 + c];\n                if (v) dst[d++ * 10 + c] = v;\n            }\n            for (; d < 10; ++d) dst[d * 10 + c] = 0;\n        }\n    } else if (dir == 1) {  // Backward\n        for (int c = 0; c < 10; ++c) {\n            int d = 9;\n            for (int r = 9; r >= 0; --r) {\n                int v = src[r * 10 + c];\n                if (v) dst[d-- * 10 + c] = v;\n            }\n            for (; d >= 0; --d) dst[d * 10 + c] = 0;\n        }\n    } else if (dir == 2) {  // Left\n        for (int r = 0; r < 10; ++r) {\n            int base = r * 10, d = 0;\n            for (int c = 0; c < 10; ++c) {\n                int v = src[base + c];\n                if (v) dst[base + d++] = v;\n            }\n            for (; d < 10; ++d) dst[base + d] = 0;\n        }\n    } else {  // Right\n        for (int r = 0; r < 10; ++r) {\n            int base = r * 10, d = 9;\n            for (int c = 9; c >= 0; --c) {\n                int v = src[base + c];\n                if (v) dst[base + d--] = v;\n            }\n            for (; d >= 0; --d) dst[base + d] = 0;\n        }\n    }\n}\n\n// ---------- global flavors and suffix counts ----------\nint flavors[100];\nint suff_counts[101][3]; // suff_counts[i][f] = number of flavor f+1 in positions [i, 99]\n\n// ---------- future potential estimation (no further tilts after current state) ----------\nint cluster_seen[100];\nint cluster_token = 0;\n\n// board: current board, comp_id, comp_size, comp_count from BFS on this board\n// start_idx: index of first remaining candy (global flavors array)\ndouble static_future(const int* board, int start_idx,\n                     const int* comp_id, const int* comp_size, int comp_count) {\n    int rem = 100 - start_idx;\n    if (rem == 0) return 0.0;\n    const int* remain_f = suff_counts[start_idx];\n\n    int pot = 0;\n    ++cluster_token;\n    for (int i = 0; i < 100; ++i) {\n        if (board[i] == 0) {\n            int adj_sum[3] = {0}, adj_sq[3] = {0};\n            int r = i / 10, c = i % 10;\n            // up\n            if (r > 0) {\n                int nb = i - 10;\n                if (board[nb]) {\n                    int cid = comp_id[nb];\n                    int f = board[nb] - 1;\n                    if (cluster_seen[cid] != cluster_token) {\n                        cluster_seen[cid] = cluster_token;\n                        int sz = comp_size[cid];\n                        adj_sum[f] += sz;\n                        adj_sq[f] += sz * sz;\n                    }\n                }\n            }\n            // down\n            if (r < 9) {\n                int nb = i + 10;\n                if (board[nb]) {\n                    int cid = comp_id[nb];\n                    int f = board[nb] - 1;\n                    if (cluster_seen[cid] != cluster_token) {\n                        cluster_seen[cid] = cluster_token;\n                        int sz = comp_size[cid];\n                        adj_sum[f] += sz;\n                        adj_sq[f] += sz * sz;\n                    }\n                }\n            }\n            // left\n            if (c > 0) {\n                int nb = i - 1;\n                if (board[nb]) {\n                    int cid = comp_id[nb];\n                    int f = board[nb] - 1;\n                    if (cluster_seen[cid] != cluster_token) {\n                        cluster_seen[cid] = cluster_token;\n                        int sz = comp_size[cid];\n                        adj_sum[f] += sz;\n                        adj_sq[f] += sz * sz;\n                    }\n                }\n            }\n            // right\n            if (c < 9) {\n                int nb = i + 1;\n                if (board[nb]) {\n                    int cid = comp_id[nb];\n                    int f = board[nb] - 1;\n                    if (cluster_seen[cid] != cluster_token) {\n                        cluster_seen[cid] = cluster_token;\n                        int sz = comp_size[cid];\n                        adj_sum[f] += sz;\n                        adj_sq[f] += sz * sz;\n                    }\n                }\n            }\n            for (int f = 0; f < 3; ++f) {\n                if (remain_f[f] > 0) {\n                    int inc = (adj_sum[f] > 0) ? (adj_sum[f] + 1) * (adj_sum[f] + 1) - adj_sq[f] : 1;\n                    pot += inc * remain_f[f];\n                }\n            }\n        }\n    }\n    return (double)pot / rem;\n}\n\n// ---------- evaluate state b2 after placing next candy and tilting d1 ----------\n// t is the index of the candy just placed (0..99), so the next candy to place is t+2\ndouble evaluate_b2(int* b2, int t) {\n    int start_next = t + 2; // index of the first candy to place on b2\n    int rem = 100 - start_next;\n    if (rem == 0) {\n        return (double) bfs_with_components(b2);\n    }\n    if (rem == 1) {\n        // exactly one candy left, place it, try all tilts, return max sum_sq\n        int b2_mod[100];\n        memcpy(b2_mod, b2, sizeof(b2_mod));\n        // find the single empty cell\n        int e2 = -1;\n        for (int i = 0; i < 100; ++i) if (b2_mod[i] == 0) { e2 = i; break; }\n        b2_mod[e2] = flavors[start_next];\n        double best = -1e18;\n        for (int d2 = 0; d2 < 4; ++d2) {\n            int b3[100];\n            tilt(b2_mod, d2, b3);\n            double v = bfs_with_components(b3);\n            if (v > best) best = v;\n        }\n        return best;\n    }\n\n    // rem >= 2: sample K = 2 empty cells\n    int empty2[100];\n    int n_empty2 = 0;\n    for (int i = 0; i < 100; ++i)\n        if (b2[i] == 0) empty2[n_empty2++] = i;\n\n    int K = min(2, n_empty2);\n    double avg_max = 0.0;\n    int sampled[2] = {-1, -1};\n    for (int s = 0; s < K; ++s) {\n        int idx;\n        do {\n            idx = xrand() % n_empty2;\n        } while ((s > 0 && idx == sampled[0]) || (s > 1 && idx == sampled[1]));\n        sampled[s] = idx;\n        int e2 = empty2[idx];\n\n        int b2_mod[100];\n        memcpy(b2_mod, b2, sizeof(b2_mod));\n        b2_mod[e2] = flavors[start_next];\n\n        double best_d2 = -1e18;\n        for (int d2 = 0; d2 < 4; ++d2) {\n            int b3[100];\n            tilt(b2_mod, d2, b3);\n            int b3_comp_id[100], b3_comp_size[100], b3_comp_count;\n            int base_sq3 = bfs_with_components(b3); // this fills global comp buffers; we must copy them\n            // quickly copy to local arrays (bfs_with_components uses global buffers)\n            memcpy(b3_comp_id, comp_id_buf, sizeof(b3_comp_id));\n            memcpy(b3_comp_size, comp_size_buf, sizeof(b3_comp_size));\n            b3_comp_count = comp_count_buf;\n\n            double future3 = static_future(b3, start_next + 1,\n                                           b3_comp_id, b3_comp_size, b3_comp_count);\n            double val = (double)base_sq3 + future3;\n            if (val > best_d2) best_d2 = val;\n        }\n        avg_max += best_d2;\n    }\n    return avg_max / K;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    // Read flavors\n    for (int i = 0; i < 100; ++i) cin >> flavors[i];\n\n    // Precompute suffix counts\n    for (int f = 0; f < 3; ++f) suff_counts[100][f] = 0;\n    for (int i = 99; i >= 0; --i) {\n        for (int f = 0; f < 3; ++f) suff_counts[i][f] = suff_counts[i + 1][f];\n        suff_counts[i][flavors[i] - 1]++;\n    }\n\n    int board[100] = {0};\n\n    for (int t = 0; t < 100; ++t) {\n        int p;\n        cin >> p;\n\n        // Place the candy in the p-th empty cell\n        int pos = -1, empty_cnt = 0;\n        for (int i = 0; i < 100; ++i) {\n            if (board[i] == 0) {\n                ++empty_cnt;\n                if (empty_cnt == p) { pos = i; break; }\n            }\n        }\n        board[pos] = flavors[t];\n\n        // Last move: output anything and finish\n        if (t == 99) {\n            cout << \"F\\n\" << flush;\n            break;\n        }\n\n        int next_f = flavors[t + 1];\n        int best_dir = 0;\n        double best_val = -1e18;\n\n        for (int d0 = 0; d0 < 4; ++d0) {\n            int b1[100];\n            tilt(board, d0, b1);\n\n            int empty1[100];\n            int n_empty1 = 0;\n            for (int i = 0; i < 100; ++i)\n                if (b1[i] == 0) empty1[n_empty1++] = i;\n\n            double val = 0.0;\n            if (n_empty1 == 0) {\n                val = (double) bfs_with_components(b1);\n            } else {\n                for (int ei = 0; ei < n_empty1; ++ei) {\n                    int e1 = empty1[ei];\n                    b1[e1] = next_f;   // temporarily place next candy\n\n                    double best_d1_val = -1e18;\n                    for (int d1 = 0; d1 < 4; ++d1) {\n                        int b2[100];\n                        tilt(b1, d1, b2);\n                        double v = evaluate_b2(b2, t);\n                        if (v > best_d1_val) best_d1_val = v;\n                    }\n\n                    val += best_d1_val;\n                    b1[e1] = 0;   // restore empty cell\n                }\n                val /= n_empty1;\n            }\n\n            if (val > best_val) {\n                best_val = val;\n                best_dir = d0;\n            }\n        }\n\n        cout << DIR[best_dir] << '\\n' << flush;\n\n        // Apply the chosen tilt for the real board\n        int nb[100];\n        tilt(board, best_dir, nb);\n        memcpy(board, nb, sizeof(board));\n    }\n\n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <numeric>\n\nusing namespace std;\n\nstruct GraphInfo {\n    vector<vector<bool>> mat;\n    vector<int> sorted_deg;\n    string adj_str;\n};\n\n// Build M threshold graphs with minimum L1 distance between degree sequences\n// based on target D_min derived from epsilon and N.\nvector<GraphInfo> build_threshold_graphs(int N, int M, double eps, mt19937& rng) {\n    int L = N * (N - 1) / 2;\n    double sigma = 2.0 * sqrt(L * eps * (1.0 - eps));\n    // try different multipliers for minimum distance\n    vector<int> d_targets;\n    for (int mult = 6; mult >= 1; mult--) {\n        int d = max(1, (int)ceil(mult * sigma));\n        d_targets.push_back(d);\n    }\n    \n    int pool_size = max(M * 50, 30000);\n    bernoulli_distribution bit_dist(0.5);\n    \n    // generate a large pool of random threshold graphs\n    struct Candidate {\n        vector<int> deg;\n        string adj;\n    };\n    vector<Candidate> pool;\n    pool.reserve(pool_size);\n    \n    for (int idx = 0; idx < pool_size; idx++) {\n        // binary signature c[0] = 0, c[1..N-1] random bits\n        vector<int> c(N, 0);\n        for (int j = 1; j < N; j++) c[j] = bit_dist(rng) ? 1 : 0;\n        \n        // compute suffix sums of c\n        vector<int> suff(N+1, 0);\n        for (int j = N-1; j >= 0; j--) {\n            suff[j] = suff[j+1] + c[j];\n        }\n        \n        // compute degrees\n        vector<int> deg(N);\n        for (int i = 0; i < N; i++) {\n            deg[i] = suff[i+1] + (c[i] ? i : 0);\n        }\n        sort(deg.begin(), deg.end(), greater<int>());\n        \n        // build adjacency string in lexicographic order\n        string adj(L, '0');\n        int pos = 0;\n        for (int i = 0; i < N; i++) {\n            for (int j = i+1; j < N; j++) {\n                if (c[j] == 1) adj[pos] = '1';\n                pos++;\n            }\n        }\n        pool.push_back({move(deg), move(adj)});\n    }\n    \n    // Greedy selection trying each target distance\n    for (int D_min : d_targets) {\n        vector<Candidate> selected;\n        selected.reserve(M);\n        // randomise order\n        shuffle(pool.begin(), pool.end(), rng);\n        for (auto& cand : pool) {\n            bool ok = true;\n            for (auto& sel : selected) {\n                int dist = 0;\n                for (int i = 0; i < N; i++) {\n                    dist += abs(cand.deg[i] - sel.deg[i]);\n                }\n                if (dist < D_min) {\n                    ok = false;\n                    break;\n                }\n            }\n            if (ok) {\n                selected.push_back(cand);\n                if ((int)selected.size() == M) break;\n            }\n        }\n        if ((int)selected.size() == M) {\n            // convert to GraphInfo (with matrix for simulation)\n            vector<GraphInfo> graphs;\n            graphs.reserve(M);\n            for (auto& sel : selected) {\n                // build matrix from adj_str\n                vector<vector<bool>> mat(N, vector<bool>(N, false));\n                int pos = 0;\n                for (int i = 0; i < N; i++) {\n                    for (int j = i+1; j < N; j++) {\n                        if (sel.adj[pos] == '1') {\n                            mat[i][j] = mat[j][i] = true;\n                        }\n                        pos++;\n                    }\n                }\n                graphs.push_back({move(mat), move(sel.deg), move(sel.adj)});\n            }\n            return graphs;\n        }\n    }\n    return {}; // failed\n}\n\n// Simulate 100 queries and return number of wrong predictions\nint simulate_errors(int N, const vector<GraphInfo>& graphs, double eps, mt19937& rng) {\n    int M = (int)graphs.size();\n    uniform_int_distribution<int> s_dist(0, M-1);\n    uniform_real_distribution<double> flip_dist(0.0, 1.0);\n    int errors = 0;\n    \n    for (int q = 0; q < 100; q++) {\n        int s = s_dist(rng);\n        auto noisy_mat = graphs[s].mat;\n        \n        // apply noise\n        for (int i = 0; i < N; i++) {\n            for (int j = i+1; j < N; j++) {\n                if (flip_dist(rng) < eps) {\n                    noisy_mat[i][j] = !noisy_mat[i][j];\n                    noisy_mat[j][i] = noisy_mat[i][j];\n                }\n            }\n        }\n        \n        // random shuffle\n        vector<int> perm(N);\n        iota(perm.begin(), perm.end(), 0);\n        shuffle(perm.begin(), perm.end(), rng);\n        \n        // build H_mat using the permuted indices\n        vector<vector<bool>> H_mat(N, vector<bool>(N, false));\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (noisy_mat[i][j]) {\n                    int ui = perm[i], uj = perm[j];\n                    H_mat[ui][uj] = true;\n                }\n            }\n        }\n        \n        // compute degrees of H (undirected, no self-loops)\n        vector<int> H_deg(N, 0);\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (H_mat[i][j]) H_deg[i]++;\n            }\n        }\n        sort(H_deg.begin(), H_deg.end(), greater<int>());\n        \n        // nearest neighbour\n        int best_t = 0;\n        int best_dist = 1e9;\n        for (int t = 0; t < M; t++) {\n            int dist = 0;\n            for (int i = 0; i < N; i++) {\n                dist += abs(H_deg[i] - graphs[t].sorted_deg[i]);\n            }\n            if (dist < best_dist) {\n                best_dist = dist;\n                best_t = t;\n            }\n        }\n        if (best_t != s) errors++;\n    }\n    return errors;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int M;\n    double eps;\n    cin >> M >> eps;\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    double best_score = -1.0;\n    int best_N = 20;\n    vector<GraphInfo> best_graphs;\n    \n    auto start_time = chrono::steady_clock::now();\n    auto time_limit = chrono::milliseconds(4700);\n    \n    // Search over possible number of vertices\n    for (int N = 4; N <= 100; N++) {\n        auto now = chrono::steady_clock::now();\n        if (now - start_time > time_limit) break;\n        \n        auto graphs = build_threshold_graphs(N, M, eps, rng);\n        if (graphs.empty()) continue;\n        \n        // evaluate by simulation\n        int total_err = 0;\n        int sims = 3;\n        for (int s = 0; s < sims; s++) {\n            total_err += simulate_errors(N, graphs, eps, rng);\n        }\n        double avg_err = (double)total_err / sims;\n        double score = round(1e9 * pow(0.9, avg_err) / N);\n        \n        if (score > best_score) {\n            best_score = score;\n            best_N = N;\n            best_graphs = move(graphs);\n        }\n    }\n    \n    // Fallback: if nothing succeeded, create a simple set\n    if (best_graphs.empty()) {\n        int N = 20;\n        best_N = N;\n        best_graphs = build_threshold_graphs(N, M, eps, rng);\n    }\n    \n    // Output the chosen graphs\n    cout << best_N << \"\\n\";\n    for (auto& g : best_graphs) {\n        cout << g.adj_str << \"\\n\";\n    }\n    cout.flush();\n    \n    // Answer 100 queries\n    int N = best_N;\n    for (int q = 0; q < 100; q++) {\n        string H_str;\n        cin >> H_str;\n        \n        // compute sorted degree sequence\n        vector<int> H_deg(N, 0);\n        int pos = 0;\n        for (int i = 0; i < N; i++) {\n            for (int j = i+1; j < N; j++) {\n                if (H_str[pos] == '1') {\n                    H_deg[i]++;\n                    H_deg[j]++;\n                }\n                pos++;\n            }\n        }\n        sort(H_deg.begin(), H_deg.end(), greater<int>());\n        \n        // nearest neighbour among the stored candidates\n        int best_t = 0;\n        int best_dist = 1e9;\n        for (int t = 0; t < M; t++) {\n            int dist = 0;\n            for (int i = 0; i < N; i++) {\n                dist += abs(H_deg[i] - best_graphs[t].sorted_deg[i]);\n            }\n            if (dist < best_dist) {\n                best_dist = dist;\n                best_t = t;\n            }\n        }\n        cout << best_t << \"\\n\";\n        cout.flush();\n    }\n    \n    return 0;\n}","ahc017":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <chrono>\n#include <limits>\n#include <tuple>\nusing namespace std;\nusing ll = long long;\n\nconst int INF = 1'000'000'000;\n\nint main() {\n    auto start_time = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count();\n    };\n    \n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n    vector<int> U(M), V(M), W(M);\n    vector<vector<tuple<int,int,int>>> orig_adj(N); // to, weight, edge_id\n    vector<int> edge_idx(N*N, -1);\n    for (int i = 0; i < M; ++i) {\n        cin >> U[i] >> V[i] >> W[i];\n        --U[i]; --V[i];\n        orig_adj[U[i]].emplace_back(V[i], W[i], i);\n        orig_adj[V[i]].emplace_back(U[i], W[i], i);\n        edge_idx[U[i]*N + V[i]] = i;\n        edge_idx[V[i]*N + U[i]] = i;\n    }\n    // read and ignore coordinates\n    int dummy;\n    for (int i = 0; i < N; ++i) cin >> dummy >> dummy;\n    \n    // Compute original all-pairs shortest paths and edge centralities\n    vector<int> orig(N*N, INF);\n    vector<ll> cnt(M, 0);\n    vector<int> dist(N);\n    priority_queue<pair<int,int>, vector<pair<int,int>>, greater<>> pq;\n    \n    for (int s = 0; s < N; ++s) {\n        fill(dist.begin(), dist.end(), INF);\n        vector<int> parent_node(N, -1);\n        vector<int> parent_edge(N, -1);\n        dist[s] = 0;\n        pq.push({0, s});\n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop();\n            if (d != dist[u]) continue;\n            for (auto &edge : orig_adj[u]) {\n                int v = get<0>(edge), w = get<1>(edge), eid = get<2>(edge);\n                if (dist[v] > d + w) {\n                    dist[v] = d + w;\n                    parent_node[v] = u;\n                    parent_edge[v] = eid;\n                    pq.push({dist[v], v});\n                }\n            }\n        }\n        for (int t = 0; t < N; ++t) {\n            orig[s*N + t] = dist[t];\n        }\n        // compute subtree sizes for centrality\n        vector<int> sub(N, 1);\n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) { return dist[a] > dist[b]; });\n        for (int v : order) {\n            if (v == s) continue;\n            int p = parent_node[v];\n            if (p != -1) {\n                sub[p] += sub[v];\n                if (parent_edge[v] != -1) {\n                    cnt[parent_edge[v]] += sub[v];\n                }\n            }\n        }\n    }\n    \n    // Greedy assignment based on cnt\n    vector<int> assign(M, -1);\n    vector<int> day_cnt(D, 0);\n    vector<ll> day_sum_cnt(D, 0);\n    vector<int> sorted_edges(M);\n    iota(sorted_edges.begin(), sorted_edges.end(), 0);\n    sort(sorted_edges.begin(), sorted_edges.end(), [&](int a, int b) { return cnt[a] > cnt[b]; });\n    for (int e : sorted_edges) {\n        int best_d = -1;\n        ll best_sum = numeric_limits<ll>::max();\n        for (int d = 0; d < D; ++d) {\n            if (day_cnt[d] < K && day_sum_cnt[d] < best_sum) {\n                best_sum = day_sum_cnt[d];\n                best_d = d;\n            }\n        }\n        assign[e] = best_d;\n        day_cnt[best_d]++;\n        day_sum_cnt[best_d] += cnt[e];\n    }\n    \n    // Store day edges\n    vector<vector<int>> day_edges(D);\n    for (int e = 0; e < M; ++e) {\n        day_edges[assign[e]].push_back(e);\n    }\n    \n    // Exact evaluation helper\n    vector<bool> removed(M);\n    auto compute_day_dist = [&](const vector<int>& removed_edges, vector<int>& out_dist, ll& out_diff) {\n        fill(removed.begin(), removed.end(), false);\n        for (int e : removed_edges) removed[e] = true;\n        out_dist.assign(N*N, INF);\n        out_diff = 0;\n        for (int s = 0; s < N; ++s) {\n            fill(dist.begin(), dist.end(), INF);\n            dist[s] = 0;\n            pq.push({0, s});\n            while (!pq.empty()) {\n                auto [d, u] = pq.top(); pq.pop();\n                if (d != dist[u]) continue;\n                for (auto &edge : orig_adj[u]) {\n                    int v = get<0>(edge), w = get<1>(edge), eid = get<2>(edge);\n                    if (removed[eid]) continue;\n                    if (dist[v] > d + w) {\n                        dist[v] = d + w;\n                        pq.push({dist[v], v});\n                    }\n                }\n            }\n            int base = s * N;\n            for (int t = 0; t < N; ++t) {\n                out_dist[base + t] = dist[t];\n            }\n            for (int t = s+1; t < N; ++t) {\n                out_diff += dist[t] - orig[base + t];\n            }\n        }\n    };\n    \n    // Initial exact evaluation\n    vector<vector<int>> day_dist(D);\n    vector<ll> day_diff(D, 0);\n    ll total_diff = 0;\n    for (int d = 0; d < D; ++d) {\n        compute_day_dist(day_edges[d], day_dist[d], day_diff[d]);\n        total_diff += day_diff[d];\n    }\n    ll best_total_diff = total_diff;\n    vector<int> best_assign = assign;\n    \n    // Local search\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> real_dist(0.0, 1.0);\n    \n    const int TIME_LIMIT_MS = 5800;\n    while (elapsed() < TIME_LIMIT_MS) {\n        // Pick a day A weighted by day_diff\n        ll sum_weights = accumulate(day_diff.begin(), day_diff.end(), 0LL);\n        int A;\n        if (sum_weights > 0) {\n            discrete_distribution<int> day_sel(day_diff.begin(), day_diff.end());\n            A = day_sel(rng);\n        } else {\n            uniform_int_distribution<int> unif(0, D-1);\n            A = unif(rng);\n        }\n        if (day_edges[A].empty()) continue;\n        \n        // Pick a random edge in A\n        uniform_int_distribution<int> edge_sel_A(0, (int)day_edges[A].size() - 1);\n        int e = day_edges[A][edge_sel_A(rng)];\n        \n        // Pick a random B != A with capacity\n        vector<int> candidates;\n        for (int d = 0; d < D; ++d) {\n            if (d != A && day_cnt[d] < K) candidates.push_back(d);\n        }\n        if (candidates.empty()) continue;\n        uniform_int_distribution<int> cand_sel(0, (int)candidates.size() - 1);\n        int B = candidates[cand_sel(rng)];\n        \n        // Evaluate move: remove e from A, add e to B\n        vector<int> new_A_edges = day_edges[A];\n        new_A_edges.erase(remove(new_A_edges.begin(), new_A_edges.end(), e), new_A_edges.end());\n        vector<int> new_dA;\n        ll new_diffA;\n        compute_day_dist(new_A_edges, new_dA, new_diffA);\n        \n        // New B: S_B U {e} (incremental update)\n        vector<int> oldB = day_dist[B];\n        vector<int> new_dB = oldB;\n        int u = U[e], v = V[e], w = W[e];\n        for (int i = 0; i < N; ++i) {\n            int iu = oldB[i*N + u];\n            int iv = oldB[i*N + v];\n            int base_i = i * N;\n            for (int j = 0; j < N; ++j) {\n                int idx = base_i + j;\n                int via_u = iu + w + oldB[v*N + j];\n                int via_v = iv + w + oldB[u*N + j];\n                if (via_u < new_dB[idx]) new_dB[idx] = via_u;\n                if (via_v < new_dB[idx]) new_dB[idx] = via_v;\n            }\n        }\n        ll new_diffB = 0;\n        for (int i = 0; i < N; ++i) {\n            int base = i * N;\n            for (int j = i+1; j < N; ++j) {\n                new_diffB += new_dB[base + j] - orig[base + j];\n            }\n        }\n        \n        ll new_total_diff = total_diff - day_diff[A] - day_diff[B] + new_diffA + new_diffB;\n        if (new_total_diff < total_diff) {\n            // Accept move\n            assign[e] = B;\n            day_cnt[A]--;\n            day_cnt[B]++;\n            auto &vecA = day_edges[A];\n            vecA.erase(remove(vecA.begin(), vecA.end(), e), vecA.end());\n            day_edges[B].push_back(e);\n            day_dist[A] = move(new_dA);\n            day_dist[B] = move(new_dB);\n            day_diff[A] = new_diffA;\n            day_diff[B] = new_diffB;\n            total_diff = new_total_diff;\n            if (total_diff < best_total_diff) {\n                best_total_diff = total_diff;\n                best_assign = assign;\n            }\n        }\n    }\n    \n    // Output best assignment\n    for (int i = 0; i < M; ++i) {\n        if (i) cout << \" \";\n        cout << best_assign[i] + 1;\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc019":"#include <iostream>\n#include <vector>\n#include <string>\n#include <tuple>\n#include <algorithm>\n\nusing namespace std;\n\nconst int perms[6][3] = {{0,1,2},{0,2,1},{1,0,2},{1,2,0},{2,0,1},{2,1,0}};\n\nint main() {\n    int D;\n    cin >> D;\n    vector<string> f[2], r[2];\n    for (int i = 0; i < 2; i++) {\n        f[i].resize(D);\n        for (int k = 0; k < D; k++) cin >> f[i][k];\n        r[i].resize(D);\n        for (int k = 0; k < D; k++) cin >> r[i][k];\n    }\n\n    int total = D * D * D;\n    vector<bool> allowed[2], used[2];\n    vector<vector<bool>> uncov_f[2], uncov_r[2];\n    vector<int> bid[2];\n\n    for (int i = 0; i < 2; i++) {\n        allowed[i].assign(total, false);\n        used[i].assign(total, false);\n        uncov_f[i].assign(D, vector<bool>(D, false));\n        uncov_r[i].assign(D, vector<bool>(D, false));\n        bid[i].assign(total, 0);\n    }\n\n    auto idx = [&](int x, int y, int z) {\n        return x * D * D + y * D + z;\n    };\n\n    // Initialize allowed and uncovered\n    for (int i = 0; i < 2; i++) {\n        for (int z = 0; z < D; z++) {\n            for (int x = 0; x < D; x++) {\n                if (f[i][z][x] == '1') uncov_f[i][z][x] = true;\n            }\n            for (int y = 0; y < D; y++) {\n                if (r[i][z][y] == '1') uncov_r[i][z][y] = true;\n            }\n        }\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    if (f[i][z][x] == '1' && r[i][z][y] == '1') {\n                        allowed[i][idx(x, y, z)] = true;\n                    }\n                }\n            }\n        }\n    }\n\n    auto can_place = [&](int i, int x0, int y0, int z0, int dx, int dy, int dz) {\n        for (int x = x0; x < x0 + dx; x++)\n            for (int y = y0; y < y0 + dy; y++)\n                for (int z = z0; z < z0 + dz; z++)\n                    if (!allowed[i][idx(x, y, z)] || used[i][idx(x, y, z)])\n                        return false;\n        return true;\n    };\n\n    auto count_covered = [&](int i, int x0, int y0, int z0, int dx, int dy, int dz) {\n        bool fc[14][14] = {false}, rc[14][14] = {false};\n        for (int x = x0; x < x0 + dx; x++)\n            for (int y = y0; y < y0 + dy; y++)\n                for (int z = z0; z < z0 + dz; z++) {\n                    if (uncov_f[i][z][x]) fc[z][x] = true;\n                    if (uncov_r[i][z][y]) rc[z][y] = true;\n                }\n        int cnt = 0;\n        for (int z = 0; z < D; z++) for (int x = 0; x < D; x++) if (fc[z][x]) cnt++;\n        for (int z = 0; z < D; z++) for (int y = 0; y < D; y++) if (rc[z][y]) cnt++;\n        return cnt;\n    };\n\n    auto apply_placement = [&](int i, int x0, int y0, int z0, int dx, int dy, int dz, int b_id) {\n        for (int x = x0; x < x0 + dx; x++)\n            for (int y = y0; y < y0 + dy; y++)\n                for (int z = z0; z < z0 + dz; z++) {\n                    int id = idx(x, y, z);\n                    used[i][id] = true;\n                    bid[i][id] = b_id;\n                    uncov_f[i][z][x] = false;\n                    uncov_r[i][z][y] = false;\n                }\n    };\n\n    // Compute box that contains seed and expands only into slabs that contain\n    // at least one cell belonging to an uncovered line in silhouette i.\n    auto compute_useful_box = [&](int i, int sx, int sy, int sz,\n                                  int &x0, int &y0, int &z0, int &dx, int &dy, int &dz) {\n        x0 = sx; y0 = sy; z0 = sz;\n        int x1 = sx, y1 = sy, z1 = sz;\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            // x-\n            while (x0 > 0) {\n                bool ok = true;\n                bool any_useful = false;\n                for (int y = y0; y <= y1 && ok; y++) {\n                    for (int z = z0; z <= z1; z++) {\n                        if (!allowed[i][idx(x0-1, y, z)] || used[i][idx(x0-1, y, z)]) {\n                            ok = false; break;\n                        }\n                        if (uncov_f[i][z][x0-1] || uncov_r[i][z][y]) any_useful = true;\n                    }\n                }\n                if (ok && any_useful) { x0--; changed = true; } else break;\n            }\n            // x+\n            while (x1 < D-1) {\n                bool ok = true;\n                bool any_useful = false;\n                for (int y = y0; y <= y1 && ok; y++) {\n                    for (int z = z0; z <= z1; z++) {\n                        if (!allowed[i][idx(x1+1, y, z)] || used[i][idx(x1+1, y, z)]) {\n                            ok = false; break;\n                        }\n                        if (uncov_f[i][z][x1+1] || uncov_r[i][z][y]) any_useful = true;\n                    }\n                }\n                if (ok && any_useful) { x1++; changed = true; } else break;\n            }\n            // y-\n            while (y0 > 0) {\n                bool ok = true;\n                bool any_useful = false;\n                for (int x = x0; x <= x1 && ok; x++) {\n                    for (int z = z0; z <= z1; z++) {\n                        if (!allowed[i][idx(x, y0-1, z)] || used[i][idx(x, y0-1, z)]) {\n                            ok = false; break;\n                        }\n                        if (uncov_f[i][z][x] || uncov_r[i][z][y0-1]) any_useful = true;\n                    }\n                }\n                if (ok && any_useful) { y0--; changed = true; } else break;\n            }\n            // y+\n            while (y1 < D-1) {\n                bool ok = true;\n                bool any_useful = false;\n                for (int x = x0; x <= x1 && ok; x++) {\n                    for (int z = z0; z <= z1; z++) {\n                        if (!allowed[i][idx(x, y1+1, z)] || used[i][idx(x, y1+1, z)]) {\n                            ok = false; break;\n                        }\n                        if (uncov_f[i][z][x] || uncov_r[i][z][y1+1]) any_useful = true;\n                    }\n                }\n                if (ok && any_useful) { y1++; changed = true; } else break;\n            }\n            // z-\n            while (z0 > 0) {\n                bool ok = true;\n                bool any_useful = false;\n                for (int x = x0; x <= x1 && ok; x++) {\n                    for (int y = y0; y <= y1; y++) {\n                        if (!allowed[i][idx(x, y, z0-1)] || used[i][idx(x, y, z0-1)]) {\n                            ok = false; break;\n                        }\n                        if (uncov_f[i][z0-1][x] || uncov_r[i][z0-1][y]) any_useful = true;\n                    }\n                }\n                if (ok && any_useful) { z0--; changed = true; } else break;\n            }\n            // z+\n            while (z1 < D-1) {\n                bool ok = true;\n                bool any_useful = false;\n                for (int x = x0; x <= x1 && ok; x++) {\n                    for (int y = y0; y <= y1; y++) {\n                        if (!allowed[i][idx(x, y, z1+1)] || used[i][idx(x, y, z1+1)]) {\n                            ok = false; break;\n                        }\n                        if (uncov_f[i][z1+1][x] || uncov_r[i][z1+1][y]) any_useful = true;\n                    }\n                }\n                if (ok && any_useful) { z1++; changed = true; } else break;\n            }\n        }\n        dx = x1 - x0 + 1;\n        dy = y1 - y0 + 1;\n        dz = z1 - z0 + 1;\n    };\n\n    // Find any valid placement (used for post-processing)\n    auto find_placement_any = [&](int i, int dx0, int dy0, int dz0,\n                                  int &bx0, int &by0, int &bz0, int &bdx, int &bdy, int &bdz) {\n        int dims[3] = {dx0, dy0, dz0};\n        for (auto &p : perms) {\n            int gdx = dims[p[0]], gdy = dims[p[1]], gdz = dims[p[2]];\n            for (int x0 = 0; x0 <= D - gdx; x0++) {\n                for (int y0 = 0; y0 <= D - gdy; y0++) {\n                    for (int z0 = 0; z0 <= D - gdz; z0++) {\n                        if (can_place(i, x0, y0, z0, gdx, gdy, gdz)) {\n                            bx0 = x0; by0 = y0; bz0 = z0;\n                            bdx = gdx; bdy = gdy; bdz = gdz;\n                            return true;\n                        }\n                    }\n                }\n            }\n        }\n        return false;\n    };\n\n    // Find placement with maximum covered uncovered pixels, returns ccj\n    auto find_best_placement = [&](int i, int dx0, int dy0, int dz0,\n                                   int &bx0, int &by0, int &bz0, int &bdx, int &bdy, int &bdz,\n                                   int &best_cc) {\n        best_cc = -1;\n        bool found = false;\n        int dims[3] = {dx0, dy0, dz0};\n        for (auto &p : perms) {\n            int gdx = dims[p[0]], gdy = dims[p[1]], gdz = dims[p[2]];\n            for (int x0 = 0; x0 <= D - gdx; x0++) {\n                for (int y0 = 0; y0 <= D - gdy; y0++) {\n                    for (int z0 = 0; z0 <= D - gdz; z0++) {\n                        if (can_place(i, x0, y0, z0, gdx, gdy, gdz)) {\n                            int cc = count_covered(i, x0, y0, z0, gdx, gdy, gdz);\n                            if (cc > best_cc) {\n                                best_cc = cc;\n                                bx0 = x0; by0 = y0; bz0 = z0;\n                                bdx = gdx; bdy = gdy; bdz = gdz;\n                                found = true;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        return found;\n    };\n\n    struct Block { int dx, dy, dz; };\n    vector<Block> blocks;\n\n    // ----- Greedy phase: shared blocks -----\n    while (true) {\n        int uncov_cnt[2] = {0, 0};\n        for (int i = 0; i < 2; i++) {\n            for (int z = 0; z < D; z++) {\n                for (int x = 0; x < D; x++) if (uncov_f[i][z][x]) uncov_cnt[i]++;\n                for (int y = 0; y < D; y++) if (uncov_r[i][z][y]) uncov_cnt[i]++;\n            }\n        }\n        if (uncov_cnt[0] == 0 && uncov_cnt[1] == 0) break;\n\n        struct Candidate {\n            int i, j;\n            int x0, y0, z0, dx, dy, dz;\n            int cci;\n            int jx0, jy0, jz0, jdx, jdy, jdz, ccj;\n            int score;\n        };\n        vector<Candidate> cands;\n\n        for (int i = 0; i < 2; i++) {\n            if (uncov_cnt[i] == 0) continue;\n            int j = 1 - i;\n\n            // Gather seeds: one per uncovered line\n            vector<tuple<int,int,int>> seeds;\n            // front uncovered\n            for (int z = 0; z < D; z++) {\n                for (int x = 0; x < D; x++) {\n                    if (uncov_f[i][z][x]) {\n                        for (int y = 0; y < D; y++) {\n                            if (allowed[i][idx(x, y, z)] && !used[i][idx(x, y, z)]) {\n                                seeds.emplace_back(x, y, z);\n                                break; // one per line\n                            }\n                        }\n                    }\n                }\n            }\n            // right uncovered\n            for (int z = 0; z < D; z++) {\n                for (int y = 0; y < D; y++) {\n                    if (uncov_r[i][z][y]) {\n                        for (int x = 0; x < D; x++) {\n                            if (allowed[i][idx(x, y, z)] && !used[i][idx(x, y, z)]) {\n                                seeds.emplace_back(x, y, z);\n                                break;\n                            }\n                        }\n                    }\n                }\n            }\n\n            for (auto [sx, sy, sz] : seeds) {\n                int x0, y0, z0, dx, dy, dz;\n                compute_useful_box(i, sx, sy, sz, x0, y0, z0, dx, dy, dz);\n                int cci = count_covered(i, x0, y0, z0, dx, dy, dz);\n                if (cci == 0) continue;\n                int jx0, jy0, jz0, jdx, jdy, jdz, ccj;\n                bool match = find_best_placement(j, dx, dy, dz, jx0, jy0, jz0, jdx, jdy, jdz, ccj);\n                if (match && ccj > 0) {\n                    int score = (cci + ccj) * 10000 - dx * dy * dz;\n                    cands.push_back({i, j, x0, y0, z0, dx, dy, dz, cci,\n                                     jx0, jy0, jz0, jdx, jdy, jdz, ccj, score});\n                }\n            }\n        }\n\n        if (!cands.empty()) {\n            // Pick candidate with highest score\n            int best = 0;\n            for (int k = 1; k < (int)cands.size(); k++)\n                if (cands[k].score > cands[best].score) best = k;\n            Candidate &c = cands[best];\n            int id = (int)blocks.size() + 1;\n            apply_placement(c.i, c.x0, c.y0, c.z0, c.dx, c.dy, c.dz, id);\n            apply_placement(c.j, c.jx0, c.jy0, c.jz0, c.jdx, c.jdy, c.jdz, id);\n            blocks.push_back({c.dx, c.dy, c.dz});\n        } else {\n            break; // no matchable placement found\n        }\n    }\n\n    // ----- Fill remaining uncovered cells with 1x1x1 blocks -----\n    for (int i = 0; i < 2; i++) {\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            // front\n            for (int z = 0; z < D && !changed; z++) {\n                for (int x = 0; x < D && !changed; x++) {\n                    if (uncov_f[i][z][x]) {\n                        for (int y = 0; y < D; y++) {\n                            if (allowed[i][idx(x, y, z)] && !used[i][idx(x, y, z)]) {\n                                int id = (int)blocks.size() + 1;\n                                apply_placement(i, x, y, z, 1, 1, 1, id);\n                                blocks.push_back({1, 1, 1});\n                                changed = true;\n                                break;\n                            }\n                        }\n                    }\n                }\n            }\n            // right\n            for (int z = 0; z < D && !changed; z++) {\n                for (int y = 0; y < D && !changed; y++) {\n                    if (uncov_r[i][z][y]) {\n                        for (int x = 0; x < D; x++) {\n                            if (allowed[i][idx(x, y, z)] && !used[i][idx(x, y, z)]) {\n                                int id = (int)blocks.size() + 1;\n                                apply_placement(i, x, y, z, 1, 1, 1, id);\n                                blocks.push_back({1, 1, 1});\n                                changed = true;\n                                break;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    // ----- Post-processing: try to use missing blocks in the other silhouette -----\n    int n = (int)blocks.size();\n    vector<bool> in0(n + 1, false), in1(n + 1, false);\n    for (int x = 0; x < D; x++)\n        for (int y = 0; y < D; y++)\n            for (int z = 0; z < D; z++) {\n                int id = bid[0][idx(x, y, z)];\n                if (id > 0) in0[id] = true;\n            }\n    for (int x = 0; x < D; x++)\n        for (int y = 0; y < D; y++)\n            for (int z = 0; z < D; z++) {\n                int id = bid[1][idx(x, y, z)];\n                if (id > 0) in1[id] = true;\n            }\n\n    vector<int> order(n);\n    for (int k = 0; k < n; k++) order[k] = k + 1;\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        int va = blocks[a - 1].dx * blocks[a - 1].dy * blocks[a - 1].dz;\n        int vb = blocks[b - 1].dx * blocks[b - 1].dy * blocks[b - 1].dz;\n        return va > vb;\n    });\n\n    for (int k : order) {\n        if (!in0[k]) {\n            int a = blocks[k - 1].dx, b = blocks[k - 1].dy, c = blocks[k - 1].dz;\n            int x0, y0, z0, dx, dy, dz;\n            if (find_placement_any(0, a, b, c, x0, y0, z0, dx, dy, dz)) {\n                apply_placement(0, x0, y0, z0, dx, dy, dz, k);\n                in0[k] = true;\n            }\n        }\n        if (!in1[k]) {\n            int a = blocks[k - 1].dx, b = blocks[k - 1].dy, c = blocks[k - 1].dz;\n            int x0, y0, z0, dx, dy, dz;\n            if (find_placement_any(1, a, b, c, x0, y0, z0, dx, dy, dz)) {\n                apply_placement(1, x0, y0, z0, dx, dy, dz, k);\n                in1[k] = true;\n            }\n        }\n    }\n\n    // ----- Output -----\n    cout << n << \"\\n\";\n    for (int i = 0; i < 2; i++) {\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 (x != 0 || y != 0 || z != 0) cout << \" \";\n                    cout << bid[i][idx(x, y, z)];\n                }\n            }\n        }\n        cout << \"\\n\";\n    }\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\nusing int64 = long long;\n\ninline int64 ceil_sqrt(int64 x) {\n    if (x <= 0) return 0;\n    int64 r = (int64)sqrt((long double)x);\n    while (r * r < x) ++r;\n    while (r * r > x) --r;\n    if (r * r < x) ++r;\n    return r;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start_time = chrono::steady_clock::now();\n    auto elapsed = [&]() { return chrono::duration<double>(chrono::steady_clock::now() - start_time).count(); };\n\n    int N, M, K;\n    cin >> N >> M >> K;\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; ++i) cin >> x[i] >> y[i];\n    vector<tuple<int, int, int>> edges(M);\n    vector<vector<pair<int, int>>> adj(N);\n    vector<vector<int>> edge_idx(N, vector<int>(N, -1));\n    for (int j = 0; j < M; ++j) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        --u; --v;\n        edges[j] = {u, v, w};\n        adj[u].push_back({v, w});\n        adj[v].push_back({u, w});\n        edge_idx[u][v] = edge_idx[v][u] = j;\n    }\n    vector<int> a(K), b(K);\n    for (int k = 0; k < K; ++k) cin >> a[k] >> b[k];\n\n    // ---------- all-pairs shortest paths ----------\n    vector<vector<int64>> dist(N, vector<int64>(N));\n    vector<vector<int>> nxt(N, vector<int>(N, -1));\n    for (int s = 0; s < N; ++s) {\n        priority_queue<pair<int64, int>, vector<pair<int64, int>>, greater<>> pq;\n        vector<int64> d(N, numeric_limits<int64>::max());\n        d[s] = 0;\n        nxt[s][s] = s;\n        pq.push({0, s});\n        while (!pq.empty()) {\n            auto [du, u] = pq.top(); pq.pop();\n            if (du != d[u]) continue;\n            for (auto &[v, w] : adj[u]) {\n                if (d[u] + w < d[v]) {\n                    d[v] = d[u] + w;\n                    nxt[s][v] = u;\n                    pq.push({d[v], v});\n                }\n            }\n        }\n        dist[s] = d;\n    }\n\n    // precompute path edges\n    vector<vector<vector<int>>> path_edges(N, vector<vector<int>>(N));\n    for (int s = 0; s < N; ++s) {\n        for (int t = 0; t < N; ++t) {\n            if (s == t) continue;\n            vector<int> eids;\n            int cur = t;\n            while (cur != s) {\n                int p = nxt[s][cur];\n                int eid = edge_idx[cur][p];\n                if (eid != -1) eids.push_back(eid);\n                cur = p;\n            }\n            path_edges[s][t] = eids;\n        }\n    }\n\n    const int64 R2 = 25000000LL; // 5000^2\n    vector<vector<int64>> dsq(N, vector<int64>(K));\n    vector<vector<int>> station_res(N);\n    for (int i = 0; i < N; ++i) {\n        for (int k = 0; k < K; ++k) {\n            int64 dx = x[i] - a[k];\n            int64 dy = y[i] - b[k];\n            int64 d2 = dx * dx + dy * dy;\n            dsq[i][k] = d2;\n            if (d2 <= R2) station_res[i].push_back(k);\n        }\n    }\n    // residents' nearby stations sorted by distance\n    vector<vector<int>> res_stations(K);\n    for (int k = 0; k < K; ++k) {\n        vector<pair<int64, int>> tmp;\n        for (int i = 0; i < N; ++i)\n            if (dsq[i][k] <= R2) tmp.push_back({dsq[i][k], i});\n        sort(tmp.begin(), tmp.end());\n        for (auto &p : tmp) res_stations[k].push_back(p.second);\n    }\n\n    // pre-sort all edges by weight\n    vector<pair<int, int>> sorted_edge_indices(M);\n    for (int j = 0; j < M; ++j) sorted_edge_indices[j] = {get<2>(edges[j]), j};\n    sort(sorted_edge_indices.begin(), sorted_edge_indices.end());\n\n    // ---------- evaluation ----------\n    auto evaluate = [&](const vector<bool> &active) -> int64 {\n        vector<int> T;\n        for (int i = 0; i < N; ++i) if (active[i]) T.push_back(i);\n        int t = T.size();\n\n        vector<bool> used_edge(M, false);\n        if (t > 1) {\n            // Prim metric MST\n            vector<bool> inmst(t, false);\n            vector<int64> minw(t, numeric_limits<int64>::max());\n            vector<int> parent(t, -1);\n            minw[0] = 0;\n            for (int i = 0; i < t; ++i) {\n                int u = -1;\n                for (int j = 0; j < t; ++j)\n                    if (!inmst[j] && (u == -1 || minw[j] < minw[u])) u = j;\n                inmst[u] = true;\n                if (parent[u] != -1) {\n                    int src = T[u], dst = T[parent[u]];\n                    for (int eid : path_edges[src][dst]) used_edge[eid] = true;\n                }\n                for (int v = 0; v < t; ++v) {\n                    if (!inmst[v] && dist[T[u]][T[v]] < minw[v]) {\n                        minw[v] = dist[T[u]][T[v]];\n                        parent[v] = u;\n                    }\n                }\n            }\n        }\n\n        // BFS on used edges\n        vector<vector<int>> radj(N);\n        for (int j = 0; j < M; ++j) if (used_edge[j]) {\n            auto [u, v, w] = edges[j];\n            radj[u].push_back(v);\n            radj[v].push_back(u);\n        }\n        vector<bool> reachable(N, false);\n        queue<int> q;\n        reachable[0] = true; q.push(0);\n        while (!q.empty()) {\n            int node = q.front(); q.pop();\n            for (int to : radj[node]) {\n                if (!reachable[to]) {\n                    reachable[to] = true;\n                    q.push(to);\n                }\n            }\n        }\n\n        // Kruskal on reachable subgraph\n        vector<int> uf(N);\n        iota(uf.begin(), uf.end(), 0);\n        function<int(int)> find = [&](int x) { return uf[x] == x ? x : uf[x] = find(uf[x]); };\n        int comps = count(reachable.begin(), reachable.end(), true);\n        int used_cnt = 0;\n        int64 cable_cost = 0;\n        for (auto &[w, j] : sorted_edge_indices) {\n            auto [u, v, _] = edges[j];\n            if (!reachable[u] || !reachable[v]) continue;\n            int ru = find(u), rv = find(v);\n            if (ru != rv) {\n                uf[ru] = rv;\n                cable_cost += w;\n                if (++used_cnt == comps - 1) break;\n            }\n        }\n        if (used_cnt != comps - 1) return numeric_limits<int64>::max();\n\n        // power cost: nearest active for each resident\n        vector<int64> max_dsq(N, 0);\n        for (int k = 0; k < K; ++k) {\n            const auto &lst = res_stations[k];\n            int best = -1;\n            for (int i : lst) {\n                if (active[i]) { best = i; break; }\n            }\n            if (best == -1) return numeric_limits<int64>::max();\n            int64 d = dsq[best][k];\n            if (d > max_dsq[best]) max_dsq[best] = d;\n        }\n        int64 power_cost = 0;\n        for (int i = 0; i < N; ++i) {\n            if (max_dsq[i] > 0) {\n                int64 P = ceil_sqrt(max_dsq[i]);\n                if (P > 5000) return numeric_limits<int64>::max();\n                power_cost += P * P;\n            }\n        }\n        return cable_cost + power_cost;\n    };\n\n    // ---------- coverage helpers ----------\n    vector<int> cov_count(K, 0);\n    auto add_station = [&](int i, vector<bool> &active) {\n        if (active[i]) return;\n        active[i] = true;\n        for (int k : station_res[i]) ++cov_count[k];\n    };\n    auto del_station = [&](int i, vector<bool> &active) {\n        if (!active[i]) return;\n        active[i] = false;\n        for (int k : station_res[i]) --cov_count[k];\n    };\n\n    // ---------- greedy ratio initial set ----------\n    vector<bool> cur_active(N, false);\n    vector<int64> best_dist_sq(K, numeric_limits<int64>::max());\n    int uncovered = K;\n    cur_active[0] = true;\n    vector<int> active_list = {0};\n    for (int k : station_res[0]) {\n        best_dist_sq[k] = dsq[0][k];\n        --uncovered;\n    }\n    while (uncovered > 0) {\n        double best_ratio = 1e18;\n        int best_i = -1;\n        for (int i = 1; i < N; ++i) {\n            if (cur_active[i]) continue;\n            int64 connect_cost = numeric_limits<int64>::max();\n            for (int j : active_list) connect_cost = min(connect_cost, dist[j][i]);\n            int64 max_d2 = 0;\n            int new_cov = 0;\n            for (int k : station_res[i]) {\n                if (best_dist_sq[k] == numeric_limits<int64>::max()) {\n                    new_cov++;\n                    if (dsq[i][k] > max_d2) max_d2 = dsq[i][k];\n                }\n            }\n            if (new_cov == 0) continue;\n            int64 P = ceil_sqrt(max_d2);\n            int64 power_inc = P * P;\n            double ratio = (double)(connect_cost + power_inc) / new_cov;\n            if (ratio < best_ratio) {\n                best_ratio = ratio;\n                best_i = i;\n            }\n        }\n        if (best_i == -1) {\n            for (int i = 1; i < N && uncovered > 0; ++i) {\n                if (!cur_active[i]) {\n                    for (int k : station_res[i]) if (best_dist_sq[k] == numeric_limits<int64>::max()) {\n                        best_i = i;\n                        break;\n                    }\n                    if (best_i != -1) break;\n                }\n            }\n        }\n        if (best_i == -1) break;\n        cur_active[best_i] = true;\n        active_list.push_back(best_i);\n        for (int k : station_res[best_i]) {\n            if (dsq[best_i][k] < best_dist_sq[k]) {\n                if (best_dist_sq[k] == numeric_limits<int64>::max()) --uncovered;\n                best_dist_sq[k] = dsq[best_i][k];\n            }\n        }\n    }\n\n    // build cov_count from cur_active\n    fill(cov_count.begin(), cov_count.end(), 0);\n    for (int i = 0; i < N; ++i) if (cur_active[i])\n        for (int k : station_res[i]) ++cov_count[k];\n\n    // initial hill-climbing removal\n    int64 cur_cost = evaluate(cur_active);\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int i = 1; i < N; ++i) {\n            if (!cur_active[i]) continue;\n            del_station(i, cur_active);\n            bool ok = true;\n            for (int k : station_res[i]) if (cov_count[k] == 0) { ok = false; break; }\n            if (!ok) { add_station(i, cur_active); continue; }\n            int64 new_cost = evaluate(cur_active);\n            if (new_cost < cur_cost) {\n                cur_cost = new_cost;\n                improved = true;\n            } else {\n                add_station(i, cur_active);\n            }\n        }\n    }\n\n    vector<bool> best_active = cur_active;\n    int64 best_cost = cur_cost;\n\n    // update active_list\n    active_list.clear();\n    for (int i = 0; i < N; ++i) if (cur_active[i]) active_list.push_back(i);\n\n    // ---------- Simulated Annealing ----------\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> rand_vertex(1, N - 1);\n    uniform_real_distribution<double> rand_double(0.0, 1.0);\n\n    double T_start = max(1e6, (double)cur_cost * 0.1);\n    double T_end = T_start * 1e-6;\n    double sa_start = elapsed();\n\n    while (elapsed() < 1.85) {\n        double frac = (elapsed() - sa_start) / (1.85 - sa_start);\n        double T = T_start * pow(T_end / T_start, frac);\n        if (T < 1e-9) T = 1e-9;\n\n        if (rand_double(rng) < 0.3 && active_list.size() > 1) { // swap move\n            // pick a random active vertex j (not 0)\n            int idx_j = uniform_int_distribution<int>(1, (int)active_list.size() - 1)(rng);\n            int j = active_list[idx_j];\n            // remove j temporarily\n            del_station(j, cur_active);\n            bool ok = true;\n            for (int k : station_res[j]) if (cov_count[k] == 0) { ok = false; break; }\n            if (!ok) {\n                add_station(j, cur_active);\n                continue;\n            }\n            // pick a random inactive vertex i\n            int i;\n            do { i = rand_vertex(rng); } while (cur_active[i]);\n            add_station(i, cur_active);\n            // evaluate\n            int64 new_cost = evaluate(cur_active);\n            bool accept = (new_cost < cur_cost);\n            if (!accept && new_cost != numeric_limits<int64>::max()) {\n                double delta = (double)(int64)(new_cost - cur_cost);\n                double prob = exp(-delta / T);\n                if (rand_double(rng) < prob) accept = true;\n            }\n            if (accept) {\n                cur_cost = new_cost;\n                // update active_list: replace j with i\n                active_list[idx_j] = i;\n                if (new_cost < best_cost) {\n                    best_cost = new_cost;\n                    best_active = cur_active;\n                }\n            } else {\n                // revert\n                del_station(i, cur_active);\n                add_station(j, cur_active);\n            }\n        } else { // simple toggle\n            int i = rand_vertex(rng);\n            bool old = cur_active[i];\n            if (old) {\n                del_station(i, cur_active);\n                bool ok = true;\n                for (int k : station_res[i]) if (cov_count[k] == 0) { ok = false; break; }\n                if (!ok) { add_station(i, cur_active); continue; }\n            } else {\n                add_station(i, cur_active);\n            }\n            int64 new_cost = evaluate(cur_active);\n            bool accept = (new_cost < cur_cost);\n            if (!accept && new_cost != numeric_limits<int64>::max()) {\n                double delta = (double)(int64)(new_cost - cur_cost);\n                double prob = exp(-delta / T);\n                if (rand_double(rng) < prob) accept = true;\n            }\n            if (accept) {\n                cur_cost = new_cost;\n                // update active_list\n                if (!old) active_list.push_back(i);\n                else active_list.erase(find(active_list.begin(), active_list.end(), i));\n                if (new_cost < best_cost) {\n                    best_cost = new_cost;\n                    best_active = cur_active;\n                }\n            } else {\n                if (old) add_station(i, cur_active);\n                else del_station(i, cur_active);\n            }\n        }\n    }\n\n    // final hill-climbing on best\n    cur_active = best_active;\n    cur_cost = best_cost;\n    fill(cov_count.begin(), cov_count.end(), 0);\n    for (int i = 0; i < N; ++i) if (cur_active[i])\n        for (int k : station_res[i]) ++cov_count[k];\n    active_list.clear();\n    for (int i = 0; i < N; ++i) if (cur_active[i]) active_list.push_back(i);\n\n    improved = true;\n    while (improved && elapsed() < 1.95) {\n        improved = false;\n        for (int i = 1; i < N; ++i) {\n            bool old = cur_active[i];\n            if (old) {\n                del_station(i, cur_active);\n                bool ok = true;\n                for (int k : station_res[i]) if (cov_count[k] == 0) { ok = false; break; }\n                if (!ok) { add_station(i, cur_active); continue; }\n            } else {\n                add_station(i, cur_active);\n            }\n            int64 new_cost = evaluate(cur_active);\n            if (new_cost < cur_cost) {\n                cur_cost = new_cost;\n                // update active_list\n                if (!old) active_list.push_back(i);\n                else active_list.erase(find(active_list.begin(), active_list.end(), i));\n                if (new_cost < best_cost) {\n                    best_cost = new_cost;\n                    best_active = cur_active;\n                }\n                improved = true;\n            } else {\n                if (old) add_station(i, cur_active);\n                else del_station(i, cur_active);\n            }\n        }\n    }\n\n    // ---------- power assignment optimization ----------\n    vector<int> act_list;\n    for (int i = 0; i < N; ++i) if (best_active[i]) act_list.push_back(i);\n    vector<vector<int>> active_for_res(K);\n    for (int k = 0; k < K; ++k) {\n        for (int i : res_stations[k])\n            if (best_active[i]) active_for_res[k].push_back(i);\n    }\n    vector<int> assign(K);\n    vector<vector<int>> station_assign(N);\n    for (int k = 0; k < K; ++k) {\n        assign[k] = active_for_res[k][0];\n        station_assign[assign[k]].push_back(k);\n    }\n    vector<int64> max_dsq(N, 0);\n    for (int i = 0; i < N; ++i) {\n        for (int k : station_assign[i]) {\n            if (dsq[i][k] > max_dsq[i]) max_dsq[i] = dsq[i][k];\n        }\n    }\n    bool changed = true;\n    while (changed && elapsed() < 1.98) {\n        changed = false;\n        for (int k = 0; k < K; ++k) {\n            int cur = assign[k];\n            int64 cur_d2 = dsq[cur][k];\n            for (int j : active_for_res[k]) {\n                if (j == cur) continue;\n                int64 new_max_cur;\n                if (cur_d2 == max_dsq[cur]) {\n                    new_max_cur = 0;\n                    for (int kk : station_assign[cur])\n                        if (kk != k && dsq[cur][kk] > new_max_cur) new_max_cur = dsq[cur][kk];\n                } else {\n                    new_max_cur = max_dsq[cur];\n                }\n                int64 new_max_j = max(max_dsq[j], dsq[j][k]);\n                int64 old_val = (ceil_sqrt(max_dsq[cur]) * ceil_sqrt(max_dsq[cur])) +\n                                (ceil_sqrt(max_dsq[j]) * ceil_sqrt(max_dsq[j]));\n                int64 new_val = (ceil_sqrt(new_max_cur) * ceil_sqrt(new_max_cur)) +\n                                (ceil_sqrt(new_max_j) * ceil_sqrt(new_max_j));\n                if (new_val < old_val) {\n                    auto &vcur = station_assign[cur];\n                    vcur.erase(find(vcur.begin(), vcur.end(), k));\n                    station_assign[j].push_back(k);\n                    max_dsq[cur] = new_max_cur;\n                    max_dsq[j] = new_max_j;\n                    assign[k] = j;\n                    changed = true;\n                    break;\n                }\n            }\n        }\n    }\n\n    // ---------- build final edges ----------\n    vector<int> final_B(M, 0);\n    {\n        vector<int> T = act_list;\n        int t = T.size();\n        vector<bool> used_edge(M, false);\n        if (t > 1) {\n            vector<bool> inmst(t, false);\n            vector<int64> minw(t, numeric_limits<int64>::max());\n            vector<int> parent(t, -1);\n            minw[0] = 0;\n            for (int i = 0; i < t; ++i) {\n                int u = -1;\n                for (int j = 0; j < t; ++j)\n                    if (!inmst[j] && (u == -1 || minw[j] < minw[u])) u = j;\n                inmst[u] = true;\n                if (parent[u] != -1) {\n                    int src = T[u], dst = T[parent[u]];\n                    for (int eid : path_edges[src][dst]) used_edge[eid] = true;\n                }\n                for (int v = 0; v < t; ++v) {\n                    if (!inmst[v] && dist[T[u]][T[v]] < minw[v]) {\n                        minw[v] = dist[T[u]][T[v]];\n                        parent[v] = u;\n                    }\n                }\n            }\n        }\n        vector<vector<int>> radj(N);\n        for (int j = 0; j < M; ++j) if (used_edge[j]) {\n            auto [u, v, w] = edges[j];\n            radj[u].push_back(v);\n            radj[v].push_back(u);\n        }\n        vector<bool> reachable(N, false);\n        queue<int> q;\n        reachable[0] = true; q.push(0);\n        while (!q.empty()) {\n            int node = q.front(); q.pop();\n            for (int to : radj[node]) {\n                if (!reachable[to]) {\n                    reachable[to] = true;\n                    q.push(to);\n                }\n            }\n        }\n        vector<int> uf(N);\n        iota(uf.begin(), uf.end(), 0);\n        function<int(int)> find = [&](int x) { return uf[x] == x ? x : uf[x] = find(uf[x]); };\n        int comps = count(reachable.begin(), reachable.end(), true);\n        int used = 0;\n        for (auto &[w, j] : sorted_edge_indices) {\n            auto [u, v, _] = edges[j];\n            if (!reachable[u] || !reachable[v]) continue;\n            int ru = find(u), rv = find(v);\n            if (ru != rv) {\n                uf[ru] = rv;\n                final_B[j] = 1;\n                if (++used == comps - 1) break;\n            }\n        }\n    }\n\n    vector<int> final_P(N, 0);\n    for (int i = 0; i < N; ++i) {\n        if (max_dsq[i] > 0) {\n            int64 P = ceil_sqrt(max_dsq[i]);\n            if (P > 5000) P = 5000;\n            final_P[i] = (int)P;\n        }\n    }\n\n    // ---------- output ----------\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << final_P[i];\n    }\n    cout << '\\n';\n    for (int j = 0; j < M; ++j) {\n        if (j) cout << ' ';\n        cout << final_B[j];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <array>\nusing namespace std;\n\nconst int N = 30;\n\nstruct Move {\n    int x1, y1, x2, y2;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // read input\n    vector<vector<int>> orig(N);\n    for (int x = 0; x < N; ++x) {\n        orig[x].resize(x + 1);\n        for (int y = 0; y <= x; ++y)\n            cin >> orig[x][y];\n    }\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto start_time = chrono::steady_clock::now();\n    const double limit = 1.9; // seconds\n\n    size_t best_len = 10000000;\n    vector<Move> best_moves;\n\n    // pre\u2011allocate move buffer (reused per trial)\n    vector<Move> moves;\n    moves.reserve(10000);\n\n    // cancellation helper\n    auto cancel_pairs = [&](vector<Move>& mvec) {\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            for (size_t i = 0; i + 1 < mvec.size(); ++i) {\n                Move& a = mvec[i];\n                Move& b = mvec[i + 1];\n                if ((a.x1 == b.x2 && a.y1 == b.y2 && a.x2 == b.x1 && a.y2 == b.y1) ||\n                    (a.x1 == b.x1 && a.y1 == b.y1 && a.x2 == b.x2 && a.y2 == b.y2)) {\n                    mvec.erase(mvec.begin() + i, mvec.begin() + i + 2);\n                    changed = true;\n                    break;\n                }\n            }\n        }\n    };\n\n    while (true) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n        if (elapsed > limit) break;\n\n        // fresh copy of the grid\n        auto grid = orig;\n        moves.clear();\n\n        // random bottom\u2011up order: for each row, shuffle the columns\n        for (int x = N - 2; x >= 0; --x) {\n            vector<int> cols(x + 1);\n            for (int y = 0; y <= x; ++y) cols[y] = y;\n            shuffle(cols.begin(), cols.end(), rng);\n            for (int y : cols) {\n                int cx = x, cy = y;\n                while (cx < N - 1) {\n                    int left  = grid[cx + 1][cy];\n                    int right = grid[cx + 1][cy + 1];\n                    if (grid[cx][cy] <= min(left, right))\n                        break;\n                    if (left < right) {\n                        swap(grid[cx][cy], grid[cx + 1][cy]);\n                        moves.push_back({cx, cy, cx + 1, cy});\n                        cx = cx + 1;\n                        // cy unchanged\n                    } else {\n                        swap(grid[cx][cy], grid[cx + 1][cy + 1]);\n                        moves.push_back({cx, cy, cx + 1, cy + 1});\n                        cx = cx + 1;\n                        cy = cy + 1;\n                    }\n                }\n            }\n        }\n\n        // adjacent pair cancellation\n        cancel_pairs(moves);\n\n        if (moves.size() < best_len) {\n            best_len = moves.size();\n            best_moves = moves;\n        }\n    }\n\n    // output best sequence\n    cout << best_moves.size() << '\\n';\n    for (auto m : best_moves)\n        cout << m.x1 << ' ' << m.y1 << ' ' << m.x2 << ' ' << m.y2 << '\\n';\n\n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <functional>\n#include <utility>\n\nusing namespace std;\n\nint main() {\n    // Read initial information\n    int D, N;\n    cin >> D >> N;\n    int ent_r = 0, ent_c = (D - 1) / 2;\n    int start = ent_r * D + ent_c;\n\n    // Mark cells that cannot hold containers (entrance + obstacles)\n    vector<vector<bool>> blocked(D, vector<bool>(D, false));\n    blocked[ent_r][ent_c] = true;  // entrance\n    for (int i = 0; i < N; i++) {\n        int r, c;\n        cin >> r >> c;\n        blocked[r][c] = true;\n    }\n\n    int K = D * D - 1 - N;  // number of containers\n\n    // BFS distances from entrance over free cells\n    vector<int> dist(D * D, -1);\n    queue<int> q;\n    dist[start] = 0;\n    q.push(start);\n    const int dr[4] = {-1, 1, 0, 0};\n    const int dc[4] = {0, 0, -1, 1};\n\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        int r = u / D, c = u % D;\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n            if (blocked[nr][nc]) continue;\n            int v = nr * D + nc;\n            if (dist[v] == -1) {\n                dist[v] = dist[u] + 1;\n                q.push(v);\n            }\n        }\n    }\n\n    // Collect all free cells (non-blocked, non-entrance)\n    vector<int> free_cells;\n    for (int r = 0; r < D; r++) {\n        for (int c = 0; c < D; c++) {\n            if (!blocked[r][c]) {\n                free_cells.push_back(r * D + c);\n            }\n        }\n    }\n\n    // Sort free cells by distance, then by ID (row-major)\n    sort(free_cells.begin(), free_cells.end(), [&](int a, int b) {\n        if (dist[a] != dist[b]) return dist[a] < dist[b];\n        return a < b;\n    });\n\n    // Prepare mapping: order of each cell, and ideal cell for each rank\n    vector<int> ord(D * D, -1);\n    vector<int> ideal(K);\n    for (int i = 0; i < K; i++) {\n        int cell = free_cells[i];\n        ord[cell] = i;\n        ideal[i] = cell;\n    }\n\n    // State of the warehouse\n    vector<bool> occupied(D * D, false);\n    vector<int> rank_at(D * D, -1);\n\n    // Process arrivals\n    for (int d = 0; d < K; d++) {\n        int rank;\n        cin >> rank;\n\n        // Get all empty cells currently reachable from entrance\n        vector<int> reachable;\n        vector<bool> vis(D * D, false);\n        queue<int> bfs;\n        bfs.push(start);\n        vis[start] = true;\n        while (!bfs.empty()) {\n            int u = bfs.front(); bfs.pop();\n            reachable.push_back(u);\n            int r = u / D, c = u % D;\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (blocked[nr][nc]) continue;\n                int v = nr * D + nc;\n                if (occupied[v]) continue;\n                if (!vis[v]) {\n                    vis[v] = true;\n                    bfs.push(v);\n                }\n            }\n        }\n\n        // Build adjacency among reachable cells\n        vector<vector<int>> adj(D * D);\n        for (int u : reachable) {\n            int r = u / D, c = u % D;\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (blocked[nr][nc]) continue;\n                int v = nr * D + nc;\n                if (occupied[v]) continue;\n                if (vis[v]) {\n                    adj[u].push_back(v);\n                }\n            }\n        }\n\n        // Find articulation points (cells that would disconnect the empty area)\n        vector<int> disc(D * D, -1), low(D * D, -1);\n        vector<bool> is_art(D * D, false);\n        int timer = 0;\n        function<void(int, int)> dfs = [&](int u, int parent) {\n            disc[u] = low[u] = timer++;\n            int children = 0;\n            for (int v : adj[u]) {\n                if (v == parent) continue;\n                if (disc[v] == -1) {\n                    dfs(v, u);\n                    low[u] = min(low[u], low[v]);\n                    if (parent != -1 && low[v] >= disc[u]) {\n                        is_art[u] = true;\n                    }\n                    children++;\n                } else {\n                    low[u] = min(low[u], disc[v]);\n                }\n            }\n            if (parent == -1 && children > 1) {\n                is_art[u] = true;\n            }\n        };\n        dfs(start, -1);\n\n        // Safe cells = reachable empty cells except entrance and articulation points\n        vector<int> safe;\n        for (int u : reachable) {\n            if (u == start) continue;\n            if (!is_art[u]) {\n                safe.push_back(u);\n            }\n        }\n\n        // Choose placement cell\n        int target = ideal[rank];\n        int chosen = -1;\n        bool target_safe = false;\n        for (int u : safe) if (u == target) { target_safe = true; break; }\n\n        if (target_safe) {\n            chosen = target;\n        } else {\n            int best_diff = 1e9;\n            for (int u : safe) {\n                int diff = abs(ord[u] - rank);\n                if (diff < best_diff) {\n                    best_diff = diff;\n                    chosen = u;\n                } else if (diff == best_diff) {\n                    if (ord[u] < ord[chosen]) {\n                        chosen = u;\n                    }\n                }\n            }\n        }\n\n        // Place the container\n        occupied[chosen] = true;\n        rank_at[chosen] = rank;\n        cout << chosen / D << \" \" << chosen % D << endl;\n    }\n\n    // Removal phase\n    vector<bool> removed(D * D, false);\n    vector<pair<int, int>> removal_seq;\n\n    while (removal_seq.size() < K) {\n        queue<int> bfs;\n        vector<bool> vis(D * D, false);\n        bfs.push(start);\n        vis[start] = true;\n        vector<int> candidates;\n\n        while (!bfs.empty()) {\n            int u = bfs.front(); bfs.pop();\n            int r = u / D, c = u % D;\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (blocked[nr][nc]) continue;\n                int v = nr * D + nc;\n                if (vis[v]) continue;\n                if (removed[v] || v == start) {\n                    vis[v] = true;\n                    bfs.push(v);\n                } else if (occupied[v] && !removed[v]) {\n                    candidates.push_back(v);\n                }\n            }\n        }\n\n        sort(candidates.begin(), candidates.end());\n        candidates.erase(unique(candidates.begin(), candidates.end()), candidates.end());\n\n        int best = -1, best_rank = 1e9;\n        for (int v : candidates) {\n            if (rank_at[v] < best_rank) {\n                best_rank = rank_at[v];\n                best = v;\n            }\n        }\n\n        removed[best] = true;\n        removal_seq.emplace_back(best / D, best % D);\n    }\n\n    for (auto [r, c] : removal_seq) {\n        cout << r << \" \" << c << endl;\n    }\n\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int N = 50, N2 = N * N, MAXC = 101; // colors 0..100\n\nint N4[N2][4];\nvector<int> boundary;\nbool req_adj[MAXC][MAXC];\n\nint vis[N2], vis_token = 0, bfs_q[N2];\n\n// fast RNG (Xorshift64)\nuint64_t rng_state = 123456789;\nuint64_t rng_next() {\n    rng_state = rng_state * 6364136223846793005ULL + 1442695040888963407ULL;\n    return rng_state >> 33;\n}\nint rng_int(int n) { return rng_next() % n; }\ndouble rng_double() { return (rng_next() & 0xFFFFFFFF) / 4294967296.0; }\n\n// ---------------------------------------------------------------------\n// Full energy computation (used inside SA)\n// ---------------------------------------------------------------------\nvoid compute_energy(const int* g, int m, int& E, int& viol_conn, int& viol_adj) {\n    ++vis_token;\n    E = 0; viol_conn = 0; viol_adj = 0;\n    int comps[MAXC] = {0}, cell_cnt[MAXC] = {0};\n\n    // 1) connectivity for colors 1..m\n    for (int i = 0; i < N2; ++i) {\n        int c = g[i];\n        if (c == 0) { ++E; continue; }\n        cell_cnt[c]++;\n        if (vis[i] != vis_token) {\n            comps[c]++;\n            int head = 0, tail = 0;\n            bfs_q[tail++] = i; vis[i] = vis_token;\n            while (head < tail) {\n                int v = bfs_q[head++];\n                for (int k = 0; k < 4; ++k) {\n                    int u = N4[v][k];\n                    if (u != -1 && g[u] == c && vis[u] != vis_token) {\n                        vis[u] = vis_token;\n                        bfs_q[tail++] = u;\n                    }\n                }\n            }\n        }\n    }\n    for (int c = 1; c <= m; ++c) {\n        if (cell_cnt[c] == 0) viol_conn += 1;\n        else if (comps[c] != 1) viol_conn += comps[c] - 1;\n    }\n\n    // 2) connectivity for 0 (must be connected to the outside)\n    for (int idx : boundary) {\n        if (g[idx] == 0 && vis[idx] != vis_token) {\n            int head = 0, tail = 0;\n            bfs_q[tail++] = idx; vis[idx] = vis_token;\n            while (head < tail) {\n                int v = bfs_q[head++];\n                for (int k = 0; k < 4; ++k) {\n                    int u = N4[v][k];\n                    if (u != -1 && g[u] == 0 && vis[u] != vis_token) {\n                        vis[u] = vis_token;\n                        bfs_q[tail++] = u;\n                    }\n                }\n            }\n        }\n    }\n    int isolated_zeros = 0;\n    for (int i = 0; i < N2; ++i)\n        if (g[i] == 0 && vis[i] != vis_token)\n            ++isolated_zeros;\n    viol_conn += isolated_zeros;\n\n    // 3) adjacency\n    int adj[MAXC][MAXC] = {0};\n    for (int i = 0; i < N2; ++i) {\n        int c1 = g[i];\n        if (i % N < N - 1) {\n            int c2 = g[i + 1];\n            if (c1 != c2) { adj[c1][c2]++; adj[c2][c1]++; }\n        }\n        if (i / N < N - 1) {\n            int c2 = g[i + N];\n            if (c1 != c2) { adj[c1][c2]++; adj[c2][c1]++; }\n        }\n    }\n    for (int idx : boundary) {\n        int c = g[idx];\n        if (c != 0) { adj[c][0]++; adj[0][c]++; }\n    }\n    for (int a = 0; a <= m; ++a) {\n        for (int b = a + 1; b <= m; ++b) {\n            if (req_adj[a][b]) {\n                if (adj[a][b] == 0) viol_adj++;\n            } else {\n                viol_adj += adj[a][b];\n            }\n        }\n    }\n}\n\n// ---------------------------------------------------------------------\n// Greedy safe erosion (works on a valid grid and keeps it valid)\n// ---------------------------------------------------------------------\nint cnt[MAXC], curr_adj[MAXC][MAXC];\n\nint greedy_erode(int* g, int m) {\n    // Build count and adjacency\n    memset(cnt, 0, sizeof(cnt));\n    memset(curr_adj, 0, sizeof(curr_adj));\n    for (int i = 0; i < N2; ++i)\n        if (g[i] != 0) cnt[g[i]]++;\n    for (int i = 0; i < N2; ++i) {\n        int c1 = g[i];\n        if (i % N < N - 1) {\n            int c2 = g[i + 1];\n            if (c1 != c2) { curr_adj[c1][c2]++; curr_adj[c2][c1]++; }\n        }\n        if (i / N < N - 1) {\n            int c2 = g[i + N];\n            if (c1 != c2) { curr_adj[c1][c2]++; curr_adj[c2][c1]++; }\n        }\n    }\n    for (int idx : boundary) {\n        int c = g[idx];\n        if (c != 0) { curr_adj[c][0]++; curr_adj[0][c]++; }\n    }\n\n    vector<int> order(N2);\n    iota(order.begin(), order.end(), 0);\n    bool changed = true;\n    int removed = 0;\n    while (changed) {\n        changed = false;\n        for (int i = N2 - 1; i > 0; --i)\n            swap(order[i], order[rng_int(i + 1)]);\n\n        for (int idx : order) {\n            if (g[idx] == 0) continue;\n            // must have a zero neighbour (including outside)\n            bool has_zero = false;\n            for (int k = 0; k < 4; ++k) {\n                int u = N4[idx][k];\n                if (u == -1 || g[u] == 0) { has_zero = true; break; }\n            }\n            if (!has_zero) continue;\n\n            int c = g[idx];\n            if (cnt[c] <= 1) continue;\n\n            int lost[MAXC] = {0}, gain[MAXC] = {0};\n            for (int k = 0; k < 4; ++k) {\n                int u = N4[idx][k];\n                int d = (u == -1) ? 0 : g[u];\n                if (d == c) continue;\n                lost[d]++;\n                if (d != 0) gain[d]++;\n            }\n\n            // adjacency must stay correct\n            bool valid = true;\n            for (int d = 0; d <= m; ++d) {\n                if (req_adj[c][d] && curr_adj[c][d] - lost[d] < 1) { valid = false; break; }\n                if (d != 0 && !req_adj[0][d] && gain[d] > 0) { valid = false; break; }\n            }\n            if (!valid) continue;\n\n            // connectivity of colour c after removal\n            int start = -1;\n            for (int k = 0; k < 4; ++k) {\n                int u = N4[idx][k];\n                if (u != -1 && g[u] == c) { start = u; break; }\n            }\n            if (start == -1) continue;\n\n            ++vis_token;\n            int head = 0, tail = 0;\n            bfs_q[tail++] = start; vis[start] = vis_token;\n            while (head < tail) {\n                int v = bfs_q[head++];\n                for (int k = 0; k < 4; ++k) {\n                    int u = N4[v][k];\n                    if (u != -1 && u != idx && g[u] == c && vis[u] != vis_token) {\n                        vis[u] = vis_token;\n                        bfs_q[tail++] = u;\n                    }\n                }\n            }\n            if (tail != cnt[c] - 1) continue;\n\n            // --- apply removal ---\n            for (int k = 0; k < 4; ++k) {\n                int u = N4[idx][k];\n                int d = (u == -1) ? 0 : g[u];\n                if (d == c) continue;\n                curr_adj[c][d]--; curr_adj[d][c]--;\n                if (d != 0) { curr_adj[0][d]++; curr_adj[d][0]++; }\n            }\n            cnt[c]--;\n            g[idx] = 0;\n            removed++;\n            changed = true;\n        }\n    }\n\n    int E = 0;\n    for (int i = 0; i < N2; ++i) if (g[i] == 0) ++E;\n    return E;\n}\n\n// ---------------------------------------------------------------------\nint main() {\n    auto start_time = chrono::high_resolution_clock::now();\n    auto elapsed_ms = [&]() {\n        return chrono::duration_cast<chrono::milliseconds>(\n            chrono::high_resolution_clock::now() - start_time).count();\n    };\n\n    int n, m;\n    cin >> n >> m;\n    vector<vector<int>> orig(n, vector<int>(n));\n    for (int i = 0; i < n; ++i)\n        for (int j = 0; j < n; ++j)\n            cin >> orig[i][j];\n\n    // ---------- precompute neighbours and boundary ----------\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int idx = i * N + j;\n            N4[idx][0] = (i > 0) ? idx - N : -1;\n            N4[idx][1] = (i < n - 1) ? idx + N : -1;\n            N4[idx][2] = (j > 0) ? idx - 1 : -1;\n            N4[idx][3] = (j < n - 1) ? idx + 1 : -1;\n            if (i == 0 || i == n - 1 || j == 0 || j == n - 1)\n                boundary.push_back(idx);\n        }\n    }\n\n    // ---------- required adjacency from the original map ----------\n    memset(req_adj, 0, sizeof(req_adj));\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c1 = orig[i][j];\n            if (j + 1 < n) {\n                int c2 = orig[i][j + 1];\n                if (c1 != c2) req_adj[c1][c2] = req_adj[c2][c1] = true;\n            }\n            if (i + 1 < n) {\n                int c2 = orig[i + 1][j];\n                if (c1 != c2) req_adj[c1][c2] = req_adj[c2][c1] = true;\n            }\n            if (i == 0 || i == n - 1 || j == 0 || j == n - 1)\n                req_adj[c1][0] = req_adj[0][c1] = true;\n        }\n    }\n\n    // ---------- initial state (original map) ----------\n    int cur[N2];\n    for (int i = 0; i < n; ++i)\n        for (int j = 0; j < n; ++j)\n            cur[i * N + j] = orig[i][j];\n\n    // ---------- initial greedy erosion ----------\n    int E = greedy_erode(cur, m);\n\n    int best[N2];\n    memcpy(best, cur, sizeof(cur));\n    int best_E = E;\n\n    // current energy (state is valid \u2192 violations = 0)\n    double cur_energy = -E;\n\n    // ---------- Simulated Annealing ----------\n    const int W = 5000;\n    double T_start = 100000.0;\n    double T_end = 0.1;\n\n    while (elapsed_ms() < 1950) {\n        double progress = elapsed_ms() / 1950.0;\n        double T = T_start * pow(T_end / T_start, progress);\n        if (T < 0.01) T = 0.01;\n\n        int idx = rng_int(N2);\n        int old_c = cur[idx];\n\n        // sometimes swap two adjacent cells\n        if (rng_double() < 0.05) {\n            int k = rng_int(4);\n            int nidx = N4[idx][k];\n            if (nidx != -1 && cur[idx] != cur[nidx]) {\n                int old2 = cur[nidx];\n                cur[idx] = old2;\n                cur[nidx] = old_c;\n                int nE, nvc, nva;\n                compute_energy(cur, m, nE, nvc, nva);\n                double new_energy = -nE + W * nvc + W * nva;\n                double delta = new_energy - cur_energy;\n                if (delta <= 0 || rng_double() < exp(-delta / T)) {\n                    cur_energy = new_energy;\n                    if (nvc == 0 && nva == 0 && nE > best_E) {\n                        best_E = nE;\n                        memcpy(best, cur, sizeof(cur));\n                    }\n                } else {\n                    cur[idx] = old_c;\n                    cur[nidx] = old2;\n                }\n            }\n            continue;\n        }\n\n        // single cell change\n        int new_c;\n        double r = rng_double();\n        if (r < 0.5) {\n            new_c = 0;\n        } else if (r < 0.8) {\n            int neigh[4], ncnt = 0;\n            for (int k = 0; k < 4; ++k) {\n                int u = N4[idx][k];\n                int d = (u == -1) ? 0 : cur[u];\n                if (d != old_c) {\n                    bool dup = false;\n                    for (int t = 0; t < ncnt; ++t) if (neigh[t] == d) { dup = true; break; }\n                    if (!dup) neigh[ncnt++] = d;\n                }\n            }\n            if (ncnt > 0) new_c = neigh[rng_int(ncnt)];\n            else new_c = old_c;\n        } else {\n            new_c = rng_int(m) + 1;\n        }\n        if (new_c == old_c) continue;\n\n        cur[idx] = new_c;\n        int nE, nvc, nva;\n        compute_energy(cur, m, nE, nvc, nva);\n        double new_energy = -nE + W * nvc + W * nva;\n        double delta = new_energy - cur_energy;\n        if (delta <= 0 || rng_double() < exp(-delta / T)) {\n            cur_energy = new_energy;\n            if (nvc == 0 && nva == 0 && nE > best_E) {\n                best_E = nE;\n                memcpy(best, cur, sizeof(cur));\n            }\n        } else {\n            cur[idx] = old_c;\n        }\n\n        // periodically refine the best valid solution\n        if (rng_int(1000) == 0) {\n            int tmp[N2];\n            memcpy(tmp, best, sizeof(best));\n            int new_e = greedy_erode(tmp, m);\n            if (new_e > best_E) {\n                best_E = new_e;\n                memcpy(best, tmp, sizeof(tmp));\n            }\n        }\n    }\n\n    // ---------- final greedy erosion on the best valid grid ----------\n    memcpy(cur, best, sizeof(best));\n    int final_E = greedy_erode(cur, m);\n    if (final_E > best_E) {\n        best_E = final_E;\n        memcpy(best, cur, sizeof(cur));\n    }\n\n    // ---------- output ----------\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (j) cout << ' ';\n            cout << best[i * N + j];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <cmath>\n\nusing namespace std;\n\nint N, D, Q_total;\nint used_queries = 0;\n\nchar ask(const vector<int>& L, const vector<int>& R) {\n    cout << L.size() << \" \" << R.size();\n    for (int x : L) cout << \" \" << x;\n    for (int x : R) cout << \" \" << x;\n    cout << endl;\n    char res; cin >> res;\n    used_queries++;\n    return res;\n}\n\nchar compare_items(int a, int b) {\n    return ask({a}, {b});\n}\n\n// ---------- Tournament tree ----------\nstruct TournamentTree {\n    int N;\n    int size;\n    vector<int> tree;         // 2*size, leaves indices\n    vector<int> leaf_pos;     // mapping item -> leaf index\n    vector<int> sorted;       // extracted in descending order\n    int height;\n    int extracted = 0;\n\n    TournamentTree(int n) : N(n) {\n        size = 1;\n        height = 0;\n        while (size < N) size <<= 1, height++;\n        tree.assign(2 * size, -1);\n        leaf_pos.resize(N);\n        for (int i = 0; i < N; ++i) {\n            int leaf = size + i;\n            tree[leaf] = i;\n            leaf_pos[i] = leaf;\n        }\n        // bottom\u2011up build\n        for (int i = size - 1; i >= 1; --i) {\n            int l = tree[2*i], r = tree[2*i+1];\n            if (l == -1) tree[i] = r;\n            else if (r == -1) tree[i] = l;\n            else {\n                if (used_queries >= Q_total) break;\n                char res = compare_items(l, r);\n                if (res == '>') tree[i] = l;\n                else if (res == '<') tree[i] = r;\n                else tree[i] = l;\n            }\n        }\n    }\n\n    // extract as many items as possible, leave only small leftover queries\n    void extract_all_possible() {\n        while (extracted < N && used_queries < Q_total) {\n            // need at least <height> comparisons for one full extraction\n            if (used_queries + height > Q_total) break;\n            int winner = tree[1];\n            if (winner == -1) break;\n            int leaf = leaf_pos[winner];\n            tree[leaf] = -1;\n            int node = leaf / 2;\n            while (node >= 1) {\n                int l = tree[2*node], r = tree[2*node+1];\n                if (l == -1) tree[node] = r;\n                else if (r == -1) tree[node] = l;\n                else {\n                    char res = compare_items(l, r);\n                    if (res == '>') tree[node] = l;\n                    else if (res == '<') tree[node] = r;\n                    else tree[node] = l;\n                }\n                node /= 2;\n            }\n            sorted.push_back(winner);\n            extracted++;\n        }\n    }\n\n    // return remaining items in heap BFS order\n    vector<int> get_remaining_order() {\n        vector<int> ord;\n        vector<bool> seen(N, false);\n        for (int i = 1; i < 2*size; ++i) {\n            int it = tree[i];\n            if (it != -1 && !seen[it]) {\n                seen[it] = true;\n                ord.push_back(it);\n            }\n        }\n        return ord;\n    }\n};\n\n// ---------- enforce known order ----------\nvoid enforce_order(vector<double>& w,\n                   const vector<int>& sorted,\n                   const vector<int>& remaining_order,\n                   int K) {\n    // among sorted items\n    for (int i = 0; i + 1 < K; ++i) {\n        int a = sorted[i], b = sorted[i+1];\n        if (w[a] < w[b]) {\n            double avg = (w[a] + w[b]) / 2.0;\n            w[a] = avg + 0.5;\n            w[b] = avg - 0.5;\n        }\n    }\n    // remaining <= smallest sorted\n    if (K > 0) {\n        int last = sorted[K-1];\n        for (int r : remaining_order) {\n            if (w[last] < w[r]) {\n                double avg = (w[last] + w[r]) / 2.0;\n                w[last] = avg + 0.5;\n                w[r] = avg - 0.5;\n            }\n        }\n    }\n    // clip\n    for (int i = 0; i < N; ++i) if (w[i] < 1.0) w[i] = 1.0;\n}\n\n// ---------- greedy partition ----------\nvector<int> greedy_partition(const vector<double>& w) {\n    vector<pair<double,int>> items(N);\n    for (int i = 0; i < N; ++i) items[i] = {w[i], i};\n    sort(items.begin(), items.end(),\n         [](auto& a, auto& b) { return a.first > b.first; });\n    vector<int> P(N, 0);\n    vector<double> bin_sum(D, 0.0);\n    for (auto& p : items) {\n        int idx = p.second;\n        int best = 0;\n        for (int b = 1; b < D; ++b)\n            if (bin_sum[b] < bin_sum[best]) best = b;\n        P[idx] = best;\n        bin_sum[best] += p.first;\n    }\n    return P;\n}\n\n// ---------- main ----------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    cin >> N >> D >> Q_total;\n    used_queries = 0;\n\n    // expected order statistics (exponential \u03bb=1e\u20115)\n    vector<double> H(N + 1, 0.0);\n    for (int i = 1; i <= N; ++i) H[i] = H[i-1] + 1.0 / i;\n    vector<double> exp_w(N);\n    for (int r = 0; r < N; ++r) {\n        exp_w[r] = 100000.0 * (H[N] - H[r]);\n    }\n\n    // Phase 1 : tournament sorting\n    TournamentTree tt(N);\n    tt.extract_all_possible();\n    vector<int>& sorted = tt.sorted;\n    int K = sorted.size();\n    vector<int> remaining_order = tt.get_remaining_order();\n\n    // initial weights\n    vector<double> w(N, 1.0);\n    for (int i = 0; i < K; ++i) w[sorted[i]] = exp_w[i];\n    for (int j = 0; j < (int)remaining_order.size(); ++j)\n        w[remaining_order[j]] = exp_w[K + j];\n    enforce_order(w, sorted, remaining_order, K);\n\n    // Phase 2 : use leftover queries for whole\u2011bin comparisons\n    struct BinQuery { vector<int> L, R; char res; };\n    vector<BinQuery> bin_queries;\n\n    vector<int> P = greedy_partition(w);\n\n    while (used_queries < Q_total) {\n        // current bin sums\n        vector<double> bin_sum(D, 0.0);\n        for (int i = 0; i < N; ++i) bin_sum[P[i]] += w[i];\n\n        // pick two non\u2011empty bins with closest sums\n        int b1 = -1, b2 = -1;\n        double min_diff = 1e30;\n        for (int i = 0; i < D; ++i) {\n            if (bin_sum[i] == 0) continue;\n            for (int j = i + 1; j < D; ++j) {\n                if (bin_sum[j] == 0) continue;\n                double diff = fabs(bin_sum[i] - bin_sum[j]);\n                if (diff < min_diff) { min_diff = diff; b1 = i; b2 = j; }\n            }\n        }\n        if (b1 == -1) { b1 = 0; b2 = 1 % D; }\n\n        vector<int> L, R;\n        for (int i = 0; i < N; ++i) {\n            if (P[i] == b1) L.push_back(i);\n            else if (P[i] == b2) R.push_back(i);\n        }\n\n        char res = ask(L, R);\n        bin_queries.push_back({L, R, res});\n\n        // online weight update\n        double sL = 0.0, sR = 0.0;\n        for (int i : L) sL += w[i];\n        for (int i : R) sR += w[i];\n        double margin = 0.0;\n        if (res == '<' && sL >= sR - margin) {\n            double error = sL - sR + margin;\n            double adj = 0.5 * error / (L.size() + R.size());\n            for (int i : L) w[i] -= adj;\n            for (int i : R) w[i] += adj;\n        } else if (res == '>' && sL <= sR + margin) {\n            double error = sR - sL + margin;\n            double adj = 0.5 * error / (L.size() + R.size());\n            for (int i : L) w[i] += adj;\n            for (int i : R) w[i] -= adj;\n        } else if (res == '=' && fabs(sL - sR) > margin) {\n            double diff = sL - sR;\n            double adj = 0.5 * diff / (L.size() + R.size());\n            for (int i : L) w[i] -= adj;\n            for (int i : R) w[i] += adj;\n        }\n        for (int i : L) w[i] = max(w[i], 1.0);\n        for (int i : R) w[i] = max(w[i], 1.0);\n        enforce_order(w, sorted, remaining_order, K);\n\n        if (used_queries % 5 == 0)\n            P = greedy_partition(w);\n    }\n\n    // Phase 3 : post\u2011process weight refinement on all bin queries\n    if (!bin_queries.empty()) {\n        int iterations = min(2000, (int)bin_queries.size() * 5);\n        double step = 0.3;\n        for (int it = 0; it < iterations; ++it) {\n            for (auto& q : bin_queries) {\n                double sL = 0.0, sR = 0.0;\n                for (int i : q.L) sL += w[i];\n                for (int i : q.R) sR += w[i];\n                if (q.res == '<' && sL >= sR) {\n                    double error = sL - sR + 1.0;\n                    double adj = step * error / (q.L.size() + q.R.size());\n                    for (int i : q.L) w[i] -= adj;\n                    for (int i : q.R) w[i] += adj;\n                } else if (q.res == '>' && sL <= sR) {\n                    double error = sR - sL + 1.0;\n                    double adj = step * error / (q.L.size() + q.R.size());\n                    for (int i : q.L) w[i] += adj;\n                    for (int i : q.R) w[i] -= adj;\n                } else if (q.res == '=' && fabs(sL - sR) > 0.5) {\n                    double diff = sL - sR;\n                    double adj = step * diff / (q.L.size() + q.R.size());\n                    for (int i : q.L) w[i] -= adj;\n                    for (int i : q.R) w[i] += adj;\n                }\n                for (int i : q.L) w[i] = max(w[i], 1.0);\n                for (int i : q.R) w[i] = max(w[i], 1.0);\n            }\n            enforce_order(w, sorted, remaining_order, K);\n            step *= 0.999;\n            if (step < 0.01) step = 0.01;\n        }\n    }\n\n    // Phase 4 : final refinement via Simulated Annealing\n    vector<int> bestP = greedy_partition(w);\n    vector<double> bin_sum(D, 0.0);\n    for (int i = 0; i < N; ++i) bin_sum[bestP[i]] += w[i];\n    double mean = accumulate(bin_sum.begin(), bin_sum.end(), 0.0) / D;\n    double best_var = 0.0;\n    for (double s : bin_sum) best_var += (s - mean) * (s - mean);\n    best_var /= D;\n\n    mt19937 rng(12345);\n    uniform_int_distribution<int> dist_item(0, N - 1);\n    uniform_int_distribution<int> dist_bin(0, D - 2);\n    uniform_real_distribution<double> uni(0.0, 1.0);\n\n    const int SA_ITERS = 300000;\n    double T = 1.0;\n    vector<int> curP = bestP;\n    vector<double> cur_bin_sum = bin_sum;\n    double cur_var = best_var;\n\n    for (int it = 0; it < SA_ITERS; ++it) {\n        int i = dist_item(rng);\n        int old_b = curP[i];\n        int new_b = dist_bin(rng);\n        if (new_b >= old_b) new_b++;\n        if (new_b == old_b) continue;\n\n        double new_old = cur_bin_sum[old_b] - w[i];\n        double new_new = cur_bin_sum[new_b] + w[i];\n        double delta = ((new_old - mean) * (new_old - mean) +\n                        (new_new - mean) * (new_new - mean)\n                        - (cur_bin_sum[old_b] - mean) * (cur_bin_sum[old_b] - mean)\n                        - (cur_bin_sum[new_b] - mean) * (cur_bin_sum[new_b] - mean)) / D;\n        if (delta < 0 || uni(rng) < exp(-delta / T)) {\n            curP[i] = new_b;\n            cur_bin_sum[old_b] = new_old;\n            cur_bin_sum[new_b] = new_new;\n            cur_var += delta;\n            if (cur_var < best_var) {\n                best_var = cur_var;\n                bestP = curP;\n            }\n        }\n        T *= 0.9999;\n        if (T < 0.001) T = 0.001;\n    }\n\n    // output\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << \" \";\n        cout << bestP[i];\n    }\n    cout << endl;\n\n    return 0;\n}","ahc026":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <climits>\n#include <utility>\n\nusing namespace std;\n\nstruct State {\n    int n, m;\n    vector<vector<int>> stacks;\n    vector<pair<int,int>> pos;     // pos[box] = {stack, index}\n    vector<int> min_val;           // minimum value in each stack, INT_MAX if empty\n\n    State(const vector<vector<int>>& init, int n_, int m_) : n(n_), m(m_) {\n        stacks = init;\n        pos.assign(n + 1, {-1, -1});\n        min_val.assign(m, INT_MAX);\n        for (int i = 0; i < m; ++i) {\n            for (int j = 0; j < (int)stacks[i].size(); ++j) {\n                int box = stacks[i][j];\n                pos[box] = {i, j};\n            }\n            if (!stacks[i].empty())\n                min_val[i] = *min_element(stacks[i].begin(), stacks[i].end());\n        }\n    }\n\n    // Move boxes [idx .. end] from stack s to stack t.\n    void move_block(int s, int idx, int t) {\n        vector<int> block(stacks[s].begin() + idx, stacks[s].end());\n        stacks[s].erase(stacks[s].begin() + idx, stacks[s].end());\n        int min_moved = INT_MAX;\n        for (int val : block) {\n            stacks[t].push_back(val);\n            pos[val] = {t, (int)stacks[t].size() - 1};\n            if (val < min_moved) min_moved = val;\n        }\n        // update min_val for s\n        if (stacks[s].empty()) min_val[s] = INT_MAX;\n        else min_val[s] = *min_element(stacks[s].begin(), stacks[s].end());\n        // update min_val for t\n        if (stacks[t].empty()) min_val[t] = min_moved;\n        else min_val[t] = min(min_val[t], min_moved);\n    }\n\n    // Remove the top box of stack s (the current target box v).\n    void carry_out(int s) {\n        int v = stacks[s].back();\n        stacks[s].pop_back();\n        pos[v] = {-1, -1};\n        if (stacks[s].empty()) {\n            min_val[s] = INT_MAX;\n        } else if (v == min_val[s]) {\n            min_val[s] = *min_element(stacks[s].begin(), stacks[s].end());\n        }\n    }\n};\n\n// Deterministic greedy heuristic for choosing a destination stack.\nint choose_target(const State& st, int s, int p) {\n    int max_block = -1;\n    for (int i = p + 1; i < (int)st.stacks[s].size(); ++i)\n        max_block = max(max_block, st.stacks[s][i]);\n\n    int best_t = -1;\n    int best_priority = -1;   // 2 = ideal, 1 = empty, 0 = violation\n    int best_key = 0;\n\n    for (int t = 0; t < st.m; ++t) {\n        if (t == s) continue;\n        if (st.stacks[t].empty()) {\n            if (best_priority < 1) {\n                best_priority = 1;\n                best_t = t;\n            }\n        } else {\n            int min_t = st.min_val[t];\n            if (min_t > max_block) {                   // ideal\n                if (best_priority < 2) {\n                    best_priority = 2;\n                    best_key = min_t;\n                    best_t = t;\n                } else if (best_priority == 2 && min_t < best_key) {\n                    best_key = min_t;\n                    best_t = t;\n                }\n            } else {                                    // violation\n                if (best_priority < 0) {\n                    best_priority = 0;\n                    best_key = min_t;\n                    best_t = t;\n                } else if (best_priority == 0 && min_t > best_key) {\n                    best_key = min_t;\n                    best_t = t;\n                }\n            }\n        }\n    }\n    return best_t;\n}\n\n// Greedy simulation from box start_v to the end. Returns additional energy cost.\nint greedy_cost(State state, int start_v) {\n    int total = 0;\n    for (int v = start_v; v <= state.n; ++v) {\n        auto [s, p] = state.pos[v];\n        while (p != (int)state.stacks[s].size() - 1) {\n            int idx = p + 1;\n            int k = state.stacks[s].size() - idx;\n            int t = choose_target(state, s, p);\n            state.move_block(s, idx, t);\n            total += k + 1;\n        }\n        state.carry_out(s);\n    }\n    return total;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int n, m;\n    cin >> n >> m;\n    vector<vector<int>> init_stacks(m, vector<int>(n / m));\n    for (int i = 0; i < m; ++i)\n        for (int j = 0; j < n / m; ++j)\n            cin >> init_stacks[i][j];\n\n    State init_state(init_stacks, n, m);\n\n    struct HistoryNode {\n        State state;\n        int parent;\n        int cost_so_far;\n        bool is_move;\n        int v_op;            // box chosen for move (valid if is_move)\n        int dest_t;          // destination stack (1\u2011indexed)\n        int v_carry;         // box carried out (always the current v)\n    };\n\n    vector<HistoryNode> history;\n    history.push_back({init_state, -1, 0, false, 0, 0, 0});\n    vector<int> beam = {0};\n\n    const int BEAM_WIDTH = 50;\n\n    for (int v = 1; v <= n; ++v) {\n        vector<HistoryNode> candidates;\n        candidates.reserve(beam.size() * m);\n\n        for (int idx : beam) {\n            HistoryNode& cur = history[idx];\n            int s = cur.state.pos[v].first;\n            int p = cur.state.pos[v].second;\n\n            if (p == (int)cur.state.stacks[s].size() - 1) {\n                // v is already on top \u2013 carry it out directly\n                State new_st = cur.state;\n                new_st.carry_out(s);\n                candidates.push_back({move(new_st), idx, cur.cost_so_far, false, 0, 0, v});\n            } else {\n                int idx_block = p + 1;\n                int k = cur.state.stacks[s].size() - idx_block;\n                for (int t = 0; t < m; ++t) {\n                    if (t == s) continue;\n                    State new_st = cur.state;\n                    new_st.move_block(s, idx_block, t);\n                    new_st.carry_out(s);\n                    int u = cur.state.stacks[s][idx_block]; // box moved together with block\n                    candidates.push_back({move(new_st), idx, cur.cost_so_far + (k + 1), true, u, t + 1, v});\n                }\n            }\n        }\n\n        // Prune to beam width using greedy evaluation\n        if ((int)candidates.size() > BEAM_WIDTH) {\n            vector<pair<int,int>> scored;\n            scored.reserve(candidates.size());\n            for (int i = 0; i < (int)candidates.size(); ++i) {\n                int est = candidates[i].cost_so_far + greedy_cost(candidates[i].state, v + 1);\n                scored.push_back({est, i});\n            }\n            sort(scored.begin(), scored.end());\n            vector<HistoryNode> kept;\n            kept.reserve(BEAM_WIDTH);\n            for (int i = 0; i < BEAM_WIDTH; ++i) {\n                kept.push_back(move(candidates[scored[i].second]));\n            }\n            candidates.swap(kept);\n        }\n\n        beam.clear();\n        for (auto& cand : candidates) {\n            beam.push_back((int)history.size());\n            history.push_back(move(cand));\n        }\n    }\n\n    // Pick the best final state\n    int best_idx = beam[0];\n    int best_cost = history[best_idx].cost_so_far;\n    for (int idx : beam) {\n        if (history[idx].cost_so_far < best_cost) {\n            best_cost = history[idx].cost_so_far;\n            best_idx = idx;\n        }\n    }\n\n    // Reconstruct operations\n    vector<pair<int,int>> ops;\n    int cur_idx = best_idx;\n    while (history[cur_idx].parent != -1) {\n        const HistoryNode& node = history[cur_idx];\n        if (node.is_move) {\n            // chronological order: move then carry. Walking backward: carry then move.\n            ops.push_back({node.v_carry, 0});\n            ops.push_back({node.v_op, node.dest_t});\n        } else {\n            ops.push_back({node.v_carry, 0});\n        }\n        cur_idx = node.parent;\n    }\n    reverse(ops.begin(), ops.end());\n\n    for (auto &op : ops)\n        cout << op.first << \" \" << op.second << \"\\n\";\n\n    return 0;\n}","ahc027":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <functional>\n#include <stack>\n#include <numeric>\n#include <cassert>\n\nusing namespace std;\n\n// ---------- Dinic max flow ----------\nstruct Dinic {\n    struct Edge {\n        int to, rev, cap, init;\n        Edge() {}\n        Edge(int to, int rev, int cap, int init) : to(to), rev(rev), cap(cap), init(init) {}\n    };\n    vector<vector<Edge>> g;\n    vector<int> level, iter;\n    Dinic(int n) : g(n) {}\n    void add_edge(int from, int to, int cap) {\n        g[from].push_back(Edge(to, (int)g[to].size(), cap, cap));\n        g[to].push_back(Edge(from, (int)g[from].size() - 1, 0, 0));\n    }\n    void bfs(int s) {\n        fill(level.begin(), level.end(), -1);\n        queue<int> q;\n        level[s] = 0;\n        q.push(s);\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (auto &e : g[v]) {\n                if (e.cap > 0 && level[e.to] < 0) {\n                    level[e.to] = level[v] + 1;\n                    q.push(e.to);\n                }\n            }\n        }\n    }\n    int dfs(int v, int t, int f) {\n        if (v == t) return f;\n        for (int &i = iter[v]; i < (int)g[v].size(); ++i) {\n            Edge &e = g[v][i];\n            if (e.cap > 0 && level[v] < level[e.to]) {\n                int d = dfs(e.to, t, min(f, e.cap));\n                if (d > 0) {\n                    e.cap -= d;\n                    g[e.to][e.rev].cap += d;\n                    return d;\n                }\n            }\n        }\n        return 0;\n    }\n    int max_flow(int s, int t) {\n        int flow = 0;\n        level.resize(g.size());\n        iter.resize(g.size());\n        while (true) {\n            bfs(s);\n            if (level[t] < 0) break;\n            fill(iter.begin(), iter.end(), 0);\n            int f;\n            while ((f = dfs(s, t, 1e9)) > 0) flow += f;\n        }\n        return flow;\n    }\n};\n\n// ---------- Eulerian circuit ----------\nstruct EulerEdge {\n    int to, rev;\n    bool used;\n};\n\nvector<int> euler_circuit(vector<vector<EulerEdge>>& adj) {\n    vector<int> res;\n    stack<int> st;\n    st.push(0);\n    while (!st.empty()) {\n        int u = st.top();\n        if (!adj[u].empty()) {\n            EulerEdge &e = adj[u].back();\n            if (e.used) {\n                adj[u].pop_back();\n                continue;\n            }\n            int v = e.to;\n            e.used = true;\n            adj[v][e.rev].used = true;\n            st.push(v);\n        } else {\n            res.push_back(u);\n            st.pop();\n        }\n    }\n    reverse(res.begin(), res.end());\n    return res;\n}\n\n// ---------- helper for average dirtiness ----------\nint64_t calc_sum_sq(const vector<int>& times, int L) {\n    if (times.empty()) return 0;\n    int k = times.size();\n    int64_t res = 0;\n    for (int i = 0; i < k - 1; ++i) {\n        int64_t diff = times[i + 1] - times[i];\n        res += diff * diff;\n    }\n    int64_t diff = times[0] + L - times.back();\n    res += diff * diff;\n    return res;\n}\n\n// ---------- fallback : original greedy + SA ----------\nstring fallback_solution(int N, int V, const vector<int>& d,\n                         const vector<vector<int>>& adj,\n                         const vector<vector<bool>>& adjmat) {\n    // DFS double\n    vector<int> base_seq;\n    vector<bool> visited(V, false);\n    vector<int> stk = {0};\n    vector<int> edge_idx(V, 0);\n    visited[0] = true;\n    while (!stk.empty()) {\n        int u = stk.back();\n        if (edge_idx[u] < (int)adj[u].size()) {\n            int w = adj[u][edge_idx[u]++];\n            if (!visited[w]) {\n                visited[w] = true;\n                base_seq.push_back(w);\n                stk.push_back(w);\n            }\n        } else {\n            stk.pop_back();\n            if (!stk.empty())\n                base_seq.push_back(stk.back());\n        }\n    }\n\n    int L0 = base_seq.size();\n    vector<int> cur_k(V, 0);\n    for (int c : base_seq) cur_k[c]++;\n\n    int L_target = 100000;\n    vector<int> seq = base_seq;\n    int L = L0;\n\n    double sum_sqrt = 0;\n    for (int i = 0; i < V; ++i) sum_sqrt += sqrt(d[i]);\n    vector<double> target_k(V);\n    for (int i = 0; i < V; ++i) target_k[i] = L_target * sqrt(d[i]) / sum_sqrt;\n\n    vector<int> parent(V, -1);\n    queue<int> q;\n    q.push(0);\n    parent[0] = -2;\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (int w : adj[u]) {\n            if (parent[w] == -1) {\n                parent[w] = u;\n                q.push(w);\n            }\n        }\n    }\n\n    while (L < L_target) {\n        int best = -1;\n        double best_score = -1;\n        for (int i = 0; i < V; ++i) {\n            double deficit = target_k[i] - cur_k[i];\n            if (deficit > 0) {\n                double score = d[i] * deficit;\n                if (score > best_score) {\n                    best_score = score;\n                    best = i;\n                }\n            }\n        }\n        if (best == -1) break;\n        int dest = best;\n        vector<int> path;\n        for (int u = dest; u != 0; u = parent[u]) path.push_back(u);\n        reverse(path.begin(), path.end());\n        int cycle_len = 2 * (int)path.size();\n        if (L + cycle_len > L_target) break;\n\n        for (int c : path) seq.push_back(c);\n        for (int i = (int)path.size() - 2; i >= 0; --i) seq.push_back(path[i]);\n        seq.push_back(0);\n\n        for (int i = 0; i < (int)path.size(); ++i) {\n            int c = path[i];\n            if (i == (int)path.size() - 1) cur_k[c] += 1;\n            else cur_k[c] += 2;\n        }\n        cur_k[0] += 1;\n        L += cycle_len;\n    }\n\n    // SA\n    vector<vector<int>> times(V);\n    for (int t = 0; t < L; ++t) times[seq[t]].push_back(t);\n    int64_t total_O = 0;\n    for (int i = 0; i < V; ++i) total_O += d[i] * calc_sum_sq(times[i], L);\n    vector<int> best_seq = seq;\n    int64_t best_O = total_O;\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> uni01(0.0, 1.0);\n\n    double T_start = max(1e7, (double)total_O / 1000.0);\n    double T_end = 1e2;\n    double total_time = 1.95;\n    auto start_time = chrono::steady_clock::now();\n\n    vector<int> affected;\n    vector<bool> is_aff(V, false);\n    vector<vector<int>> old_pos(V);\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed >= total_time) break;\n        double ratio = elapsed / total_time;\n        if (ratio > 1.0) ratio = 1.0;\n        double T = T_start * pow(T_end / T_start, ratio);\n\n        for (int c : affected) {\n            old_pos[c].clear();\n            is_aff[c] = false;\n        }\n        affected.clear();\n\n        if (L < 3) break;\n        int max_len = min(2500, L - 2);\n        if (max_len < 1) continue;\n        uniform_int_distribution<int> l_dist(1, L - 3);\n        int l = l_dist(rng);\n        int max_r = min(L - 2, l + max_len - 1);\n        if (max_r < l) continue;\n        uniform_int_distribution<int> r_dist(l, max_r);\n        int r = r_dist(rng);\n\n        int u1 = seq[l - 1], v1 = seq[r];\n        int u2 = seq[l], v2 = seq[r + 1];\n        if (!adjmat[u1][v1] || !adjmat[u2][v2]) continue;\n\n        for (int p = l; p <= r; ++p) {\n            int c = seq[p];\n            if (!is_aff[c]) {\n                is_aff[c] = true;\n                affected.push_back(c);\n            }\n            old_pos[c].push_back(p);\n        }\n\n        int64_t delta = 0;\n        vector<pair<int, vector<int>>> updates;\n        for (int c : affected) {\n            const vector<int>& old_times = times[c];\n            const vector<int>& op = old_pos[c];\n            int64_t old_sq = calc_sum_sq(old_times, L);\n\n            vector<int> new_times;\n            for (int t : old_times) if (t < l) new_times.push_back(t);\n            vector<int> np;\n            for (int p : op) np.push_back(l + r - p);\n            sort(np.begin(), np.end());\n            for (int t : np) new_times.push_back(t);\n            for (int t : old_times) if (t > r) new_times.push_back(t);\n\n            int64_t new_sq = calc_sum_sq(new_times, L);\n            delta += d[c] * (new_sq - old_sq);\n            updates.emplace_back(c, std::move(new_times));\n        }\n\n        bool accept = (delta <= 0);\n        if (!accept) {\n            double prob = exp(-delta / T);\n            if (uni01(rng) < prob) accept = true;\n        }\n\n        if (accept) {\n            reverse(seq.begin() + l, seq.begin() + r + 1);\n            for (auto& p : updates) {\n                times[p.first] = std::move(p.second);\n            }\n            total_O += delta;\n            if (total_O < best_O) {\n                best_O = total_O;\n                best_seq = seq;\n            }\n        }\n    }\n\n    string ans;\n    int cur = 0;\n    for (int nxt : best_seq) {\n        int ci = cur / N, cj = cur % N;\n        int ni = nxt / N, nj = nxt % N;\n        if (ni == ci - 1) ans += 'U';\n        else if (ni == ci + 1) ans += 'D';\n        else if (nj == cj - 1) ans += 'L';\n        else if (nj == cj + 1) ans += 'R';\n        else ans += 'U';\n        cur = nxt;\n    }\n    return ans;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int N;\n    cin >> N;\n    int V = N * N;\n    vector<string> h(N - 1), v(N);\n    for (int i = 0; i < N - 1; ++i) cin >> h[i];\n    for (int i = 0; i < N; ++i) cin >> v[i];\n    vector<int> d(V);\n    for (int i = 0; i < V; ++i) cin >> d[i];\n\n    auto id = [&](int i, int j) { return i * N + j; };\n\n    // adjacency list with edge ids\n    vector<vector<pair<int,int>>> adj(V);  // (neighbor, edge_id)\n    vector<pair<int,int>> edge_uv;          // (u,v) for each edge\n    int E = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = id(i, j);\n            if (j + 1 < N && v[i][j] == '0') {\n                int w = id(i, j + 1);\n                adj[u].emplace_back(w, E);\n                adj[w].emplace_back(u, E);\n                edge_uv.emplace_back(u, w);\n                E++;\n            }\n            if (i + 1 < N && h[i][j] == '0') {\n                int w = id(i + 1, j);\n                adj[u].emplace_back(w, E);\n                adj[w].emplace_back(u, E);\n                edge_uv.emplace_back(u, w);\n                E++;\n            }\n        }\n    }\n\n    // simple adjacency and matrix\n    vector<vector<int>> simple_adj(V);\n    vector<vector<bool>> adjmat(V, vector<bool>(V, false));\n    for (int i = 0; i < V; ++i)\n        for (auto [w, _] : adj[i]) {\n            simple_adj[i].push_back(w);\n            adjmat[i][w] = true;\n        }\n\n    // BFS to build spanning tree and compute deg_T\n    vector<int> parent(V, -1);\n    vector<int> deg_T(V, 0);\n    vector<int> tree_edge(E, 0);\n    queue<int> q;\n    q.push(0);\n    parent[0] = -2;\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (auto [w, eid] : adj[u]) {\n            if (parent[w] == -1) {\n                parent[w] = u;\n                deg_T[u]++;\n                deg_T[w]++;\n                tree_edge[eid] = 1;\n                q.push(w);\n            }\n        }\n    }\n\n    // bipartition left/right\n    vector<bool> left(V, false);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            left[id(i,j)] = ((i + j) % 2 == 0);\n\n    int L_target = 100000;\n    int L_half = L_target / 2;\n\n    // minimum visits based on tree degree\n    vector<int> min_f(V);\n    for (int i = 0; i < V; ++i)\n        min_f[i] = max(1, (deg_T[i] + 1) / 2);\n\n    int min_left = 0, min_right = 0;\n    for (int i = 0; i < V; ++i) {\n        if (left[i]) min_left += min_f[i];\n        else min_right += min_f[i];\n    }\n\n    if (min_left > L_half || min_right > L_half) {\n        cout << fallback_solution(N, V, d, simple_adj, adjmat) << endl;\n        return 0;\n    }\n\n    vector<int> f(V, 0);\n\n    // Greedy allocation to minimize sum d_i / f_i (which approximates average dirtiness)\n    auto allocate_side_greedy = [&](bool is_left, int total, int sum_min) {\n        vector<int> idx;\n        for (int i = 0; i < V; ++i) if (left[i] == is_left) idx.push_back(i);\n        int n = idx.size();\n        if (n == 0) return;\n        vector<int> cur_f(n);\n        for (int i = 0; i < n; ++i) cur_f[i] = min_f[idx[i]];\n        int cur_sum = sum_min;\n\n        struct Item {\n            double gain;\n            int id;\n            bool operator<(const Item& o) const { return gain < o.gain; }\n        };\n        priority_queue<Item> pq;\n        for (int i = 0; i < n; ++i) {\n            int fi = cur_f[i];\n            double gain = (double)d[idx[i]] / ((int64_t)fi * (fi + 1));\n            pq.push({gain, i});\n        }\n\n        while (cur_sum < total) {\n            Item it = pq.top(); pq.pop();\n            int i = it.id;\n            cur_f[i]++;\n            cur_sum++;\n            int fi = cur_f[i];\n            double new_gain = (double)d[idx[i]] / ((int64_t)fi * (fi + 1));\n            pq.push({new_gain, i});\n        }\n\n        // assign back\n        for (int i = 0; i < n; ++i) f[idx[i]] = cur_f[i];\n    };\n\n    allocate_side_greedy(true, L_half, min_left);\n    allocate_side_greedy(false, L_half, min_right);\n\n    // sanity check\n    if (accumulate(f.begin(), f.end(), 0) != L_target) {\n        cout << fallback_solution(N, V, d, simple_adj, adjmat) << endl;\n        return 0;\n    }\n\n    // b_i = 2*f_i\n    vector<int> b(V), rem(V);\n    int rem_left_sum = 0;\n    for (int i = 0; i < V; ++i) {\n        b[i] = 2 * f[i];\n        rem[i] = b[i] - deg_T[i];\n        if (left[i]) rem_left_sum += rem[i];\n    }\n\n    // Dinic flow\n    int S = V, T = V + 1;\n    Dinic dinic(V + 2);\n    vector<int> flow_fwd_idx(E, -1);\n\n    for (int eid = 0; eid < E; ++eid) {\n        int u = edge_uv[eid].first, v = edge_uv[eid].second;\n        if (!left[u]) swap(u, v);\n        int idx = (int)dinic.g[u].size();\n        dinic.add_edge(u, v, 1000000);\n        flow_fwd_idx[eid] = idx;\n    }\n\n    for (int i = 0; i < V; ++i) {\n        if (left[i]) dinic.add_edge(S, i, rem[i]);\n        else dinic.add_edge(i, T, rem[i]);\n    }\n\n    int flow_val = dinic.max_flow(S, T);\n    if (flow_val != rem_left_sum) {\n        cout << fallback_solution(N, V, d, simple_adj, adjmat) << endl;\n        return 0;\n    }\n\n    // multiplicities\n    vector<int> mult(E, 0);\n    for (int eid = 0; eid < E; ++eid) {\n        int base = tree_edge[eid];\n        int u = edge_uv[eid].first, v = edge_uv[eid].second;\n        if (!left[u]) swap(u, v);\n        int fwd_idx = flow_fwd_idx[eid];\n        int fe = dinic.g[u][fwd_idx].init - dinic.g[u][fwd_idx].cap;\n        mult[eid] = base + fe;\n    }\n\n    // Build base Eulerian multigraph\n    vector<vector<EulerEdge>> euler_adj_base(V);\n    auto add_euler_edge_base = [&](int u, int v) {\n        euler_adj_base[u].push_back({v, (int)euler_adj_base[v].size(), false});\n        euler_adj_base[v].push_back({u, (int)euler_adj_base[u].size() - 1, false});\n    };\n    for (int eid = 0; eid < E; ++eid) {\n        int m = mult[eid];\n        int u = edge_uv[eid].first, v = edge_uv[eid].second;\n        for (int k = 0; k < m; ++k) add_euler_edge_base(u, v);\n    }\n\n    // randomize Euler circuits, pick best initial sequence\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    int trials = 20;\n    int64_t best_initial_O = 1e18;\n    vector<int> best_initial_seq;\n    for (int trial = 0; trial < trials; ++trial) {\n        auto euler_adj = euler_adj_base;\n        for (auto &lst : euler_adj) shuffle(lst.begin(), lst.end(), rng);\n        vector<int> circuit = euler_circuit(euler_adj);\n        int first0 = find(circuit.begin(), circuit.end(), 0) - circuit.begin();\n        vector<int> rot;\n        rot.insert(rot.end(), circuit.begin() + first0, circuit.end());\n        rot.insert(rot.end(), circuit.begin(), circuit.begin() + first0);\n        vector<int> seq(rot.begin() + 1, rot.end());\n        vector<vector<int>> times(V);\n        for (int t = 0; t < (int)seq.size(); ++t) times[seq[t]].push_back(t);\n        int64_t O = 0;\n        for (int i = 0; i < V; ++i) O += d[i] * calc_sum_sq(times[i], (int)seq.size());\n        if (O < best_initial_O) {\n            best_initial_O = O;\n            best_initial_seq = move(seq);\n        }\n    }\n\n    vector<int> seq = best_initial_seq;\n    int L = seq.size();\n\n    // ---------- Simulated Annealing ----------\n    vector<vector<int>> times(V);\n    for (int t = 0; t < L; ++t) times[seq[t]].push_back(t);\n    int64_t total_O = best_initial_O;\n    vector<int> best_seq = seq;\n    int64_t best_O = total_O;\n\n    uniform_real_distribution<double> uni01(0.0, 1.0);\n\n    double T_start = max(1e7, (double)total_O / 1000.0);\n    double T_end = 1e2;\n    double total_time = 1.95;\n    auto start_time = chrono::steady_clock::now();\n\n    vector<int> affected;\n    vector<bool> is_aff(V, false);\n    vector<vector<int>> old_pos(V);\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed >= total_time) break;\n        double ratio = elapsed / total_time;\n        if (ratio > 1.0) ratio = 1.0;\n        double T = T_start * pow(T_end / T_start, ratio);\n        int max_len = min(3000, L - 2);\n\n        // clear affected data\n        for (int c : affected) {\n            old_pos[c].clear();\n            is_aff[c] = false;\n        }\n        affected.clear();\n\n        if (L < 3) break;\n        uniform_int_distribution<int> l_dist(1, L - 3);\n        int l = l_dist(rng);\n        int max_r = min(L - 2, l + max_len - 1);\n        if (max_r < l) continue;\n        uniform_int_distribution<int> r_dist(l, max_r);\n        int r = r_dist(rng);\n\n        int u1 = seq[l - 1], v1 = seq[r];\n        int u2 = seq[l], v2 = seq[r + 1];\n        if (!adjmat[u1][v1] || !adjmat[u2][v2]) continue;\n\n        for (int p = l; p <= r; ++p) {\n            int c = seq[p];\n            if (!is_aff[c]) {\n                is_aff[c] = true;\n                affected.push_back(c);\n                old_pos[c].push_back(p);\n            } else {\n                old_pos[c].push_back(p);\n            }\n        }\n\n        int64_t delta = 0;\n        vector<pair<int, vector<int>>> updates;\n        for (int c : affected) {\n            const vector<int>& old_times = times[c];\n            const vector<int>& op = old_pos[c];\n            int64_t old_sq = calc_sum_sq(old_times, L);\n\n            vector<int> new_times;\n            for (int t : old_times) if (t < l) new_times.push_back(t);\n            vector<int> np;\n            for (int p : op) np.push_back(l + r - p);\n            sort(np.begin(), np.end());\n            for (int t : np) new_times.push_back(t);\n            for (int t : old_times) if (t > r) new_times.push_back(t);\n\n            int64_t new_sq = calc_sum_sq(new_times, L);\n            delta += d[c] * (new_sq - old_sq);\n            updates.emplace_back(c, std::move(new_times));\n        }\n\n        bool accept = (delta <= 0);\n        if (!accept) {\n            double prob = exp(-delta / T);\n            if (uni01(rng) < prob) accept = true;\n        }\n\n        if (accept) {\n            reverse(seq.begin() + l, seq.begin() + r + 1);\n            for (auto& p : updates) {\n                times[p.first] = std::move(p.second);\n            }\n            total_O += delta;\n            if (total_O < best_O) {\n                best_O = total_O;\n                best_seq = seq;\n            }\n        }\n    }\n\n    // Output best route\n    string ans;\n    int cur = 0;\n    for (int nxt : best_seq) {\n        int ci = cur / N, cj = cur % N;\n        int ni = nxt / N, nj = nxt % N;\n        if (ni == ci - 1) ans += 'U';\n        else if (ni == ci + 1) ans += 'D';\n        else if (nj == cj - 1) ans += 'L';\n        else if (nj == cj + 1) ans += 'R';\n        else ans += 'U';\n        cur = nxt;\n    }\n    cout << ans << endl;\n\n    return 0;\n}","ahc028":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <chrono>\n#include <cmath>\n#include <cstdlib>\n#include <numeric>\n#include <limits>\nusing namespace std;\n\nconst int INF = 1e9;\nint N, M;\nint start_i, start_j;\nchar grid[15][15];\nvector<string> t;\nvector<int> pos[26];\nint dist[225][225];\nint start_idx;\n\n// minDist[a][b] = minimum Manhattan distance between any cell of 'a' and any cell of 'b'\nint minDist[26][26];\n// minStartDist[letter] = min distance from start cell to any cell with that letter\nint minStartDist[26];\n\nstruct Xorshift {\n    unsigned int x, y, z, w;\n    Xorshift(unsigned int seed) {\n        x = seed; y = 362436069; z = 521288629; w = 88675123;\n        for (int i = 0; i < 4; ++i) next();\n    }\n    unsigned int next() {\n        unsigned int t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = w ^ (w >> 19) ^ t ^ (t >> 8);\n    }\n    int nextInt(int n) { return next() % n; }\n    double nextDouble() { return next() * (1.0 / 4294967296.0); }\n};\n\n// Exact DP cost (includes start cell)\nint compute_DP_cost(const string& S) {\n    if (S.empty()) return 0;\n    int sz = S.size();\n    int c0 = S[0] - 'A';\n    const auto& cells0 = pos[c0];\n    vector<int> cur(225, INF);\n    for (int cell : cells0) cur[cell] = 1 + dist[start_idx][cell];\n    for (int k = 1; k < sz; ++k) {\n        int pc = S[k-1] - 'A';\n        int nc = S[k] - 'A';\n        const auto& prev_cells = pos[pc];\n        const auto& next_cells = pos[nc];\n        vector<int> nxt(225, INF);\n        for (int j : prev_cells) {\n            int base = cur[j] + 1;\n            if (base >= INF) continue;\n            const int* drow = dist[j];\n            for (int i : next_cells) {\n                int cost = base + drow[i];\n                if (cost < nxt[i]) nxt[i] = cost;\n            }\n        }\n        cur.swap(nxt);\n    }\n    return *min_element(cur.begin(), cur.end());\n}\n\n// Fast lower bound\nint compute_LB(const string& S) {\n    if (S.empty()) return 0;\n    int lb = (int)S.size() + minStartDist[S[0] - 'A'];\n    for (size_t i = 0; i + 1 < S.size(); ++i)\n        lb += minDist[S[i] - 'A'][S[i+1] - 'A'];\n    return lb;\n}\n\n// Overlap between two words (5 letters)\nint word_overlap(const string& a, const string& b) {\n    for (int k = min(5, (int)a.size()); k >= 1; --k)\n        if (a.compare(a.size() - k, k, b, 0, k) == 0)\n            return k;\n    return 0;\n}\n\n// Build superstring from permutation, possibly using random overlaps\nstring build_S(const vector<int>& perm, Xorshift& rnd, bool random_overlap = false) {\n    if (perm.empty()) return \"\";\n    vector<bool> used(M, false);\n    string S = t[perm[0]];\n    used[perm[0]] = true;\n    for (size_t idx = 1; idx < perm.size(); ++idx) {\n        int w = perm[idx];\n        if (used[w]) continue;\n        used[w] = true;\n        int max_overlap = 0;\n        int limit = min(5, (int)S.size());\n        for (int k = limit; k >= 1; --k) {\n            if (S.compare(S.size() - k, k, t[w], 0, k) == 0) {\n                max_overlap = k; break;\n            }\n        }\n        int L = max_overlap;\n        if (random_overlap && L > 0 && rnd.nextDouble() < 0.3) {\n            L = rnd.nextInt(L + 1); // sometimes use a smaller overlap\n        }\n        S += t[w].substr(L);\n    }\n    // ensure all words present\n    for (int i = 0; i < M; ++i) {\n        if (!used[i]) {\n            if (S.empty()) S = t[i];\n            else {\n                int L = word_overlap(S, t[i]);\n                S += t[i].substr(L);\n            }\n            used[i] = true;\n        }\n    }\n    return S;\n}\n\n// Greedy maximum overlap\nvoid overlap_greedy(Xorshift& rnd, string& S, vector<int>& perm) {\n    S.clear(); perm.clear();\n    vector<bool> used(M, false);\n    int first = rnd.nextInt(M);\n    used[first] = true;\n    perm.push_back(first);\n    S = t[first];\n    while (perm.size() < M) {\n        int best_ov = -1;\n        vector<int> best;\n        for (int i = 0; i < M; ++i) {\n            if (used[i]) continue;\n            int ov = word_overlap(S, t[i]);\n            if (ov > best_ov) { best_ov = ov; best.clear(); best.push_back(i); }\n            else if (ov == best_ov) best.push_back(i);\n        }\n        int pick = best[rnd.nextInt(best.size())];\n        used[pick] = true;\n        perm.push_back(pick);\n        S += t[pick].substr(best_ov);\n    }\n}\n\n// DP greedy: choose word that minimizes additional true DP cost\nvoid dp_greedy(const vector<int>& init_dp, char init_letter, Xorshift& rnd,\n               string& S_out, vector<int>& perm_out) {\n    vector<int> dp = init_dp;\n    char last_char = init_letter;\n    string S;\n    vector<bool> done(M, false);\n    vector<int> perm;\n    while (true) {\n        for (int i = 0; i < M; ++i)\n            if (!done[i] && S.find(t[i]) != string::npos)\n                done[i] = true;\n        vector<int> cand;\n        for (int i = 0; i < M; ++i) if (!done[i]) cand.push_back(i);\n        if (cand.empty()) break;\n\n        struct Cand { int idx, L, cost; vector<int> ndp; char nl; };\n        vector<Cand> candidates;\n        int s_len = S.size();\n        for (int idx : cand) {\n            const string& w = t[idx];\n            int L = word_overlap(S, w);\n            if (L == 5) { done[idx] = true; continue; }\n            string suffix = w.substr(L);\n            // simulate typing suffix from current dp\n            int ci = last_char - 'A';\n            const vector<int>* cur_cells = &pos[ci];\n            vector<int> cur_vals(225, INF);\n            for (int cell : *cur_cells) cur_vals[cell] = dp[cell];\n            for (char ch : suffix) {\n                int nci = ch - 'A';\n                const vector<int>& next_cells = pos[nci];\n                vector<int> nxt(225, INF);\n                for (int j : *cur_cells) {\n                    int base = cur_vals[j] + 1;\n                    if (base >= INF) continue;\n                    const int* drow = dist[j];\n                    for (int i : next_cells) {\n                        int cost = base + drow[i];\n                        if (cost < nxt[i]) nxt[i] = cost;\n                    }\n                }\n                cur_vals = move(nxt);\n                cur_cells = &next_cells;\n            }\n            int cost = INF;\n            for (int cell : *cur_cells) cost = min(cost, cur_vals[cell]);\n            candidates.push_back({idx, L, cost, move(cur_vals), suffix.back()});\n        }\n        if (candidates.empty()) continue;\n        sort(candidates.begin(), candidates.end(),\n             [](const Cand& a, const Cand& b) { return a.cost < b.cost; });\n        int top = min(3, (int)candidates.size());\n        int pick = (rnd.nextDouble() < 0.8) ? 0 : rnd.nextInt(top);\n        Cand& chosen = candidates[pick];\n        S += t[chosen.idx].substr(chosen.L);\n        dp = move(chosen.ndp);\n        last_char = chosen.nl;\n        done[chosen.idx] = true;\n        perm.push_back(chosen.idx);\n    }\n    S_out = S;\n    perm_out = perm;\n}\n\n// Compute optimal cell path for a given string S\nvoid compute_DP_path(const string& S, vector<int>& path) {\n    int L = S.size();\n    path.resize(L);\n    if (L == 0) return;\n    vector<vector<int>> dp(L, vector<int>(225, INF));\n    vector<vector<int>> prv(L, vector<int>(225, -1));\n    int c0 = S[0] - 'A';\n    for (int cell : pos[c0]) dp[0][cell] = 1 + dist[start_idx][cell];\n    for (int k = 1; k < L; ++k) {\n        int pc = S[k-1] - 'A';\n        int nc = S[k] - 'A';\n        for (int j : pos[pc]) {\n            int base = dp[k-1][j] + 1;\n            if (base >= INF) continue;\n            const int* drow = dist[j];\n            for (int i : pos[nc]) {\n                int cost = base + drow[i];\n                if (cost < dp[k][i]) {\n                    dp[k][i] = cost;\n                    prv[k][i] = j;\n                }\n            }\n        }\n    }\n    int lst = S.back() - 'A';\n    int best = INF, best_cell = -1;\n    for (int cell : pos[lst]) if (dp[L-1][cell] < best) { best = dp[L-1][cell]; best_cell = cell; }\n    for (int k = L-1; k >= 0; --k) {\n        path[k] = best_cell;\n        best_cell = prv[k][best_cell];\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start_clock = chrono::steady_clock::now();\n    const double time_limit = 1.95;\n\n    // ---- input ----\n    cin >> N >> M;\n    cin >> start_i >> start_j;\n    for (int i = 0; i < N; ++i) {\n        string line; cin >> line;\n        for (int j = 0; j < N; ++j) grid[i][j] = line[j];\n    }\n    t.resize(M);\n    for (int i = 0; i < M; ++i) cin >> t[i];\n\n    // ---- precompute positions ----\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            pos[grid[i][j] - 'A'].push_back(i * N + j);\n    start_idx = start_i * N + start_j;\n\n    // ---- precompute distances between all cells ----\n    for (int i = 0; i < 225; ++i) {\n        int xi = i / N, yi = i % N;\n        int* drow = dist[i];\n        for (int j = 0; j < 225; ++j) {\n            int xj = j / N, yj = j % N;\n            drow[j] = abs(xi - xj) + abs(yi - yj);\n        }\n    }\n\n    // ---- precompute minDist between letters ----\n    for (int a = 0; a < 26; ++a) {\n        for (int b = 0; b < 26; ++b) {\n            if (pos[a].empty() || pos[b].empty()) {\n                minDist[a][b] = INF;\n                continue;\n            }\n            int best = INF;\n            for (int i : pos[a]) {\n                const int* drow = dist[i];\n                for (int j : pos[b]) {\n                    int d = drow[j];\n                    if (d < best) best = d;\n                }\n            }\n            minDist[a][b] = best;\n        }\n    }\n    // precompute minStartDist\n    for (int c = 0; c < 26; ++c) {\n        int best = INF;\n        for (int cell : pos[c]) {\n            int d = dist[start_idx][cell];\n            if (d < best) best = d;\n        }\n        minStartDist[c] = best;\n    }\n\n    unsigned int seed = chrono::steady_clock::now().time_since_epoch().count();\n    Xorshift rnd(seed);\n\n    // ---- initial solutions (true DP cost) ----\n    // We'll keep best true cost solution.\n    string best_S;\n    int best_true_cost = INF;\n\n    auto update_best = [&](const string& S) {\n        int cost = compute_DP_cost(S);\n        if (cost < best_true_cost) {\n            best_true_cost = cost;\n            best_S = S;\n        }\n    };\n\n    // Run many overlap greedies (fast generation)\n    for (int i = 0; i < 100; ++i) {\n        string S; vector<int> perm;\n        overlap_greedy(rnd, S, perm);\n        update_best(S);\n    }\n\n    // DP greedies (slower, use true DP)\n    vector<int> init_dp(225, INF);\n    init_dp[start_idx] = 0;\n    char init_letter = grid[start_i][start_j];\n    for (int i = 0; i < 30; ++i) {\n        string S; vector<int> perm;\n        dp_greedy(init_dp, init_letter, rnd, S, perm);\n        update_best(S);\n    }\n\n    // ---- SA with lower bound (fast) ----\n    vector<int> cur_perm;\n    { // start from a fresh overlap greedy\n        string dummy; vector<int> perm;\n        overlap_greedy(rnd, dummy, perm);\n        cur_perm = perm;\n    }\n    string cur_S = build_S(cur_perm, rnd, false);\n    int cur_LB = compute_LB(cur_S);\n    int best_LB = cur_LB;\n    string best_LB_S = cur_S;\n    vector<int> best_LB_perm = cur_perm;\n\n    // keep a pool of top candidates by LB\n    vector<pair<int, string>> lb_candidates; // (LB, S)\n    lb_candidates.emplace_back(cur_LB, cur_S);\n\n    double T0 = 500.0;\n    int iter = 0;\n    while (true) {\n        chrono::duration<double> elapsed = chrono::steady_clock::now() - start_clock;\n        if (elapsed.count() > time_limit) break;\n        double progress = elapsed.count() / time_limit;\n        double T = T0 * exp(-progress * 5.0);\n        if (T < 0.01) T = 0.01;\n\n        for (int batch = 0; batch < 20; ++batch) {\n            iter++;\n            vector<int> new_perm = cur_perm;\n            int type = rnd.nextInt(3);\n            if (type == 0) {\n                int i = rnd.nextInt(M), j = rnd.nextInt(M);\n                while (i == j) j = rnd.nextInt(M);\n                swap(new_perm[i], new_perm[j]);\n            } else if (type == 1) {\n                int l = rnd.nextInt(M), r = rnd.nextInt(M);\n                if (l > r) swap(l, r);\n                if (l < r) reverse(new_perm.begin() + l, new_perm.begin() + r + 1);\n            } else {\n                int i = rnd.nextInt(M), j = rnd.nextInt(M);\n                if (i == j) continue;\n                int val = new_perm[i];\n                new_perm.erase(new_perm.begin() + i);\n                new_perm.insert(new_perm.begin() + j, val);\n            }\n            string new_S = build_S(new_perm, rnd, true);\n            int new_LB = compute_LB(new_S);\n            int delta = new_LB - cur_LB;\n            if (delta <= 0 || rnd.nextDouble() < exp(-delta / T)) {\n                cur_perm = new_perm;\n                cur_S = new_S;\n                cur_LB = new_LB;\n                if (cur_LB < best_LB) {\n                    best_LB = cur_LB;\n                    best_LB_S = cur_S;\n                    best_LB_perm = cur_perm;\n                }\n                // update lb_candidates\n                if (lb_candidates.size() < 20 || cur_LB < lb_candidates.back().first) {\n                    lb_candidates.emplace_back(cur_LB, cur_S);\n                    sort(lb_candidates.begin(), lb_candidates.end());\n                    if (lb_candidates.size() > 20) lb_candidates.pop_back();\n                }\n            }\n            // Occasionally evaluate true cost on current string\n            if (iter % 500 == 0) {\n                int true_cost = compute_DP_cost(cur_S);\n                if (true_cost < best_true_cost) {\n                    best_true_cost = true_cost;\n                    best_S = cur_S;\n                }\n            }\n        }\n    }\n\n    // After SA, evaluate true cost on top LB candidates to ensure we didn't miss better true cost\n    for (auto& p : lb_candidates) {\n        int cost = compute_DP_cost(p.second);\n        if (cost < best_true_cost) {\n            best_true_cost = cost;\n            best_S = p.second;\n        }\n    }\n    // Also evaluate true cost on the best LB string (already might be in candidates)\n    {\n        int cost = compute_DP_cost(best_LB_S);\n        if (cost < best_true_cost) {\n            best_true_cost = cost;\n            best_S = best_LB_S;\n        }\n    }\n\n    // ---- final output ----\n    vector<int> path;\n    compute_DP_path(best_S, path);\n    for (int cell : path) {\n        int i = cell / N;\n        int j = cell % N;\n        cout << i << \" \" << j << \"\\n\";\n    }\n\n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <bitset>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\nconstexpr int MAX_N2 = 400;   // 20*20 = 400\nconstexpr double INF = 1e100;\n\ndouble normal_cdf(double x) {\n    return 0.5 * erfc(-x / sqrt(2.0));\n}\n\nint N, M;\ndouble eps;\nint V_total;\n\nstruct Placement {\n    bitset<MAX_N2> cells;\n    vector<int> q_overlap;   // size Q, contribution to each query\n    vector<char> d_contrib;  // dynamic, size D, 1 if placement covers the drilled cell\n};\n\nstruct FieldInfo {\n    vector<Placement> placements;\n    vector<int> valid;       // indices of placements currently valid\n};\nvector<FieldInfo> fields;\n\n// queries\nint Q = 0;\nvector<bitset<MAX_N2>> query_sets;\nvector<int> query_results;\nvector<vector<double>> log_prob;  // Q x (V_total+1)\n\n// drills\nint D = 0;\nvector<int> drill_cells;\nvector<int> observed;\n\n// Random engine\nmt19937 gen(chrono::steady_clock::now().time_since_epoch().count());\n\ninline int idx(int i, int j) { return i * N + j; }\ninline pair<int,int> unidx(int id) { return {id / N, id % N}; }\n\nvoid read_input() {\n    cin >> N >> M >> eps;\n    fields.resize(M);\n    V_total = 0;\n    for (int k = 0; k < M; ++k) {\n        int d; cin >> d;\n        fields[k].placements.reserve( (N-0)*(N-0) ); // upper bound\n        vector<pair<int,int>> shape(d);\n        for (int a = 0; a < d; ++a) {\n            cin >> shape[a].first >> shape[a].second;\n        }\n        int max_i = 0, max_j = 0;\n        for (auto &p : shape) {\n            max_i = max(max_i, p.first);\n            max_j = max(max_j, p.second);\n        }\n        for (int dx = 0; dx <= N - 1 - max_i; ++dx) {\n            for (int dy = 0; dy <= N - 1 - max_j; ++dy) {\n                Placement pl;\n                bitset<MAX_N2> b;\n                for (auto &p : shape) {\n                    int r = dx + p.first;\n                    int c = dy + p.second;\n                    b.set(idx(r, c));\n                }\n                pl.cells = b;\n                fields[k].placements.push_back(pl);\n            }\n        }\n        V_total += d;\n        // initially all placements are valid\n        fields[k].valid.resize(fields[k].placements.size());\n        iota(fields[k].valid.begin(), fields[k].valid.end(), 0);\n    }\n}\n\nvoid generate_initial_queries(int num_queries) {\n    Q = num_queries;\n    if (Q > 2 * N * N - 10) Q = max(0, 2 * N * N - 10);\n    query_sets.resize(Q);\n    query_results.resize(Q);\n    \n    uniform_int_distribution<int> k_dist(max(2, N*N/2), N*N);\n    vector<int> indices(N*N);\n    iota(indices.begin(), indices.end(), 0);\n    \n    for (int i = 0; i < Q; ++i) {\n        int k = k_dist(gen);\n        shuffle(indices.begin(), indices.end(), gen);\n        bitset<MAX_N2> s;\n        for (int t = 0; t < k; ++t) s.set(indices[t]);\n        query_sets[i] = s;\n        \n        // output query\n        cout << \"q \" << k;\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                if (s.test(idx(r, c))) cout << \" \" << r << \" \" << c;\n            }\n        }\n        cout << \"\\n\" << flush;\n    }\n    \n    for (int i = 0; i < Q; ++i) {\n        cin >> query_results[i];\n    }\n}\n\nvoid precompute_log_prob() {\n    log_prob.resize(Q, vector<double>(V_total + 1));\n    for (int i = 0; i < Q; ++i) {\n        int k = (int)query_sets[i].count();\n        int y = query_results[i];\n        double sigma = sqrt(k * eps * (1.0 - eps));\n        for (int v = 0; v <= V_total; ++v) {\n            double mu = k * eps + v * (1.0 - 2.0 * eps);\n            double prob;\n            if (y == 0) {\n                prob = normal_cdf((0.5 - mu) / sigma);\n            } else {\n                prob = normal_cdf((y + 0.5 - mu) / sigma) - normal_cdf((y - 0.5 - mu) / sigma);\n            }\n            if (prob <= 0.0) prob = 1e-300;\n            log_prob[i][v] = log(prob);\n        }\n    }\n}\n\nvoid precompute_overlaps() {\n    for (int k = 0; k < M; ++k) {\n        for (auto &pl : fields[k].placements) {\n            pl.q_overlap.resize(Q);\n            for (int i = 0; i < Q; ++i) {\n                pl.q_overlap[i] = (pl.cells & query_sets[i]).count();\n            }\n        }\n    }\n}\n\n// ----------------------------------------------------------------------\n// Simulated Annealing\n\nstruct SAState {\n    vector<int> assign;        // absolute placement index for each field\n    vector<int> qover;         // sum of overlaps for each query\n    vector<int> dcnt;          // drill counts (matched exactly)\n    double energy;\n};\n\nSAState create_random_state() {\n    SAState st;\n    st.assign.resize(M);\n    for (int k = 0; k < M; ++k) {\n        const auto &valid = fields[k].valid;\n        uniform_int_distribution<int> dis(0, valid.size() - 1);\n        st.assign[k] = valid[dis(gen)];\n    }\n    st.qover.assign(Q, 0);\n    st.dcnt.assign(D, 0);\n    for (int k = 0; k < M; ++k) {\n        int p = st.assign[k];\n        const auto &pl = fields[k].placements[p];\n        for (int i = 0; i < Q; ++i) st.qover[i] += pl.q_overlap[i];\n        for (int d = 0; d < D; ++d) st.dcnt[d] += pl.d_contrib[d];\n    }\n    st.energy = 0;\n    for (int i = 0; i < Q; ++i) {\n        st.energy += log_prob[i][st.qover[i]];\n    }\n    return st;\n}\n\nSAState run_sa(int moves) {\n    SAState state = create_random_state();\n    vector<int> assign = state.assign;\n    vector<int> qover = state.qover;\n    vector<int> dcnt = state.dcnt;\n    double energy = state.energy;\n\n    double best_energy = energy;\n    vector<int> best_assign = assign;\n\n    uniform_real_distribution<double> real_dis(0.0, 1.0);\n    uniform_int_distribution<int> field_dis(0, M - 1);\n\n    double T_start = 10.0, T_end = 0.01;\n    for (int step = 0; step < moves; ++step) {\n        double frac = (double)step / moves;\n        double T = T_start * pow(T_end / T_start, frac);\n        int k = field_dis(gen);\n        const auto &valid = fields[k].valid;\n        if (valid.size() <= 1) continue;\n        int old_p = assign[k];\n        int idx_new = uniform_int_distribution<int>(0, valid.size() - 1)(gen);\n        int new_p = valid[idx_new];\n        if (new_p == old_p) continue;\n\n        const auto &old_pl = fields[k].placements[old_p];\n        const auto &new_pl = fields[k].placements[new_p];\n\n        // hard drill constraints\n        bool ok = true;\n        for (int d = 0; d < D; ++d) {\n            int new_cnt = dcnt[d] - old_pl.d_contrib[d] + new_pl.d_contrib[d];\n            if (new_cnt != observed[d]) { ok = false; break; }\n        }\n        if (!ok) continue;\n\n        // compute new energy\n        double new_energy = energy;\n        for (int i = 0; i < Q; ++i) {\n            int old_val = qover[i];\n            int new_val = old_val - old_pl.q_overlap[i] + new_pl.q_overlap[i];\n            new_energy += log_prob[i][new_val] - log_prob[i][old_val];\n        }\n\n        if (new_energy >= energy || real_dis(gen) < exp((new_energy - energy) / T)) {\n            assign[k] = new_p;\n            energy = new_energy;\n            for (int i = 0; i < Q; ++i) {\n                qover[i] = qover[i] - old_pl.q_overlap[i] + new_pl.q_overlap[i];\n            }\n            for (int d = 0; d < D; ++d) {\n                dcnt[d] = dcnt[d] - old_pl.d_contrib[d] + new_pl.d_contrib[d];\n            }\n            if (energy > best_energy) {\n                best_energy = energy;\n                best_assign = assign;\n            }\n        }\n    }\n\n    SAState result;\n    result.assign = best_assign;\n    result.qover.assign(Q, 0);\n    result.dcnt.assign(D, 0);\n    for (int k = 0; k < M; ++k) {\n        int p = best_assign[k];\n        const auto &pl = fields[k].placements[p];\n        for (int i = 0; i < Q; ++i) result.qover[i] += pl.q_overlap[i];\n        for (int d = 0; d < D; ++d) result.dcnt[d] += pl.d_contrib[d];\n    }\n    result.energy = 0;\n    for (int i = 0; i < Q; ++i) result.energy += log_prob[i][result.qover[i]];\n    return result;\n}\n\nbitset<MAX_N2> get_mask(const vector<int> &assign) {\n    bitset<MAX_N2> mask;\n    for (int k = 0; k < M; ++k) {\n        mask |= fields[k].placements[assign[k]].cells;\n    }\n    return mask;\n}\n\n// ----------------------------------------------------------------------\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cout << fixed << setprecision(10);\n\n    read_input();\n    int max_ops = 2 * N * N;\n    int ops_used = 0;\n\n    // Phase 1: a few cheap large queries\n    int Q_planned = 50;\n    if (Q_planned > max_ops - 5) Q_planned = max(0, max_ops - 5);\n    generate_initial_queries(Q_planned);\n    ops_used += Q;\n    \n    precompute_log_prob();\n    precompute_overlaps();\n\n    // Phase 2: run SA to quickly guess\n    SAState best;\n    double best_energy = -INF;\n    // run 3 independent SA runs and keep the best\n    for (int r = 0; r < 3; ++r) {\n        SAState st = run_sa(20000);   // 20k moves each\n        if (st.energy > best_energy) {\n            best_energy = st.energy;\n            best = st;\n        }\n    }\n\n    // Guess based on best state\n    bitset<MAX_N2> guess_mask = get_mask(best.assign);\n    vector<pair<int,int>> guess_cells;\n    for (int r = 0; r < N; ++r)\n        for (int c = 0; c < N; ++c)\n            if (guess_mask.test(idx(r, c)))\n                guess_cells.emplace_back(r, c);\n    \n    cout << \"a \" << guess_cells.size();\n    for (auto &p : guess_cells) cout << \" \" << p.first << \" \" << p.second;\n    cout << \"\\n\" << flush;\n    ++ops_used;\n\n    int answer_result;\n    cin >> answer_result;\n    if (answer_result == 1) return 0;\n\n    // Phase 3: guess was wrong \u2014 fallback to full drill\n    // We drill every cell not yet drilled (currently none) and record v>0.\n    vector<pair<int,int>> positive;\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            if (ops_used >= max_ops - 1) break; // need one op for final guess\n            cout << \"q 1 \" << r << \" \" << c << \"\\n\" << flush;\n            ++ops_used;\n            int v;\n            cin >> v;\n            if (v > 0) positive.emplace_back(r, c);\n        }\n    }\n\n    // Final guess with exactly the true positive cells\n    cout << \"a \" << positive.size();\n    for (auto &p : positive) cout << \" \" << p.first << \" \" << p.second;\n    cout << \"\\n\" << flush;\n    // Expect 1\n    cin >> answer_result;\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int i0, j0, i1, j1;\n    int area() const { return (i1 - i0) * (j1 - j0); }\n};\n\nint W, D, N;\nconst int HORIZ_COUNT = (1000 - 1) * 1000;   // (W-1)*W = 999*1000\nconst int VERT_COUNT = 1000 * (1000 - 1);    // W*(W-1) = 1000*999\nconst int SEG = HORIZ_COUNT + VERT_COUNT;    // 1998000\n\nunsigned rng_state = 123456789;\nunsigned xorshift() {\n    rng_state ^= rng_state << 13;\n    rng_state ^= rng_state >> 17;\n    rng_state ^= rng_state << 5;\n    return rng_state;\n}\ninline double rnd_double() { return (xorshift() & 0xFFFFFFFF) / 4294967296.0; }\ninline int rnd_int(int n) { return xorshift() % n; }\n\nvector<vector<int>> a;\nvector<vector<Rect>> rects;\nvector<uint8_t> cnt;         // D * SEG, wall segment counts\nvector<int> pen_day;         // area penalty per day\nint total_area_penalty = 0;\nint total_L_sum = 0;\n\n// best found solution\nvector<vector<Rect>> best_rects;\nint best_cost = INT_MAX;\n\nvoid fill_boundaries(const Rect& r, vector<int>& out) {\n    out.clear();\n    if (r.i0 >= 1 && r.i0 <= W - 1) {\n        int base = (r.i0 - 1) * W + r.j0;\n        for (int j = 0; j < r.j1 - r.j0; ++j) out.push_back(base + j);\n    }\n    if (r.i1 >= 1 && r.i1 <= W - 1) {\n        int base = (r.i1 - 1) * W + r.j0;\n        for (int j = 0; j < r.j1 - r.j0; ++j) out.push_back(base + j);\n    }\n    if (r.j0 >= 1 && r.j0 <= W - 1) {\n        int base = HORIZ_COUNT + (r.j0 - 1) * W + r.i0;\n        for (int i = 0; i < r.i1 - r.i0; ++i) out.push_back(base + i);\n    }\n    if (r.j1 >= 1 && r.j1 <= W - 1) {\n        int base = HORIZ_COUNT + (r.j1 - 1) * W + r.i0;\n        for (int i = 0; i < r.i1 - r.i0; ++i) out.push_back(base + i);\n    }\n}\n\ninline int update_L_delta(int d, int seg, bool old_st, bool new_st) {\n    int delta = 0;\n    if (d > 0) {\n        bool prev = cnt[(d - 1) * SEG + seg] > 0;\n        delta += (prev ^ new_st) - (prev ^ old_st);\n    }\n    if (d + 1 < D) {\n        bool next = cnt[(d + 1) * SEG + seg] > 0;\n        delta += (next ^ new_st) - (next ^ old_st);\n    }\n    return delta;\n}\n\nvector<Rect> pack_exact(const vector<int>& targets) {\n    struct FreeRect { int i0, j0, i1, j1; };\n    vector<FreeRect> free;\n    free.push_back({0, 0, W, W});\n    vector<Rect> res(N);\n\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int x, int y) { return targets[x] > targets[y]; });\n\n    for (int idx : order) {\n        long long req = targets[idx];\n        int best = -1;\n        long long best_area = 0;\n        for (int i = 0; i < (int)free.size(); ++i) {\n            long long a = 1LL * (free[i].i1 - free[i].i0) * (free[i].j1 - free[i].j0);\n            if (a >= req) {\n                if (best == -1 || a < best_area) {\n                    best = i; best_area = a;\n                }\n            }\n        }\n        if (best == -1) {\n            long long max_a = -1;\n            for (int i = 0; i < (int)free.size(); ++i) {\n                long long a = 1LL * (free[i].i1 - free[i].i0) * (free[i].j1 - free[i].j0);\n                if (a > max_a) { max_a = a; best = i; }\n            }\n        }\n        FreeRect fr = free[best];\n        swap(free[best], free.back());\n        free.pop_back();\n\n        int avW = fr.j1 - fr.j0;\n        int avH = fr.i1 - fr.i0;\n        int w = min(avW, max(1, (int)ceil(sqrt(req))));\n        int h = max(1, (int)((req + w - 1) / w));\n        if (h > avH) {\n            h = avH;\n            w = max(1, (int)((req + h - 1) / h));\n            if (w > avW) w = avW;\n        }\n        w = max(1, min(w, avW));\n        h = max(1, min(h, avH));\n        res[idx] = {fr.i0, fr.j0, fr.i0 + h, fr.j0 + w};\n        if (w < avW) free.push_back({fr.i0, fr.j0 + w, fr.i0 + h, fr.j1});\n        if (h < avH) free.push_back({fr.i0 + h, fr.j0, fr.i1, fr.j1});\n    }\n    return res;\n}\n\nint compute_L_between(int d) {\n    int L = 0;\n    int off0 = (d - 1) * SEG, off1 = d * SEG;\n    for (int s = 0; s < SEG; ++s) {\n        bool p = cnt[off0 + s] > 0;\n        bool c = cnt[off1 + s] > 0;\n        L += (p != c);\n    }\n    return L;\n}\n\nvoid build_from_greedy() {\n    // greedy per\u2011day decision (same as previous accepted solution)\n    rects.resize(D, vector<Rect>(N));\n    rects[0] = pack_exact(a[0]);\n\n    vector<uint64_t> prev_bits((SEG + 63) / 64, 0);\n    auto set_bit = [&](int seg) {\n        prev_bits[seg >> 6] |= (1ULL << (seg & 63));\n    };\n    auto get_wall_bits = [&](const vector<Rect>& r, vector<uint64_t>& bits) {\n        fill(bits.begin(), bits.end(), 0ULL);\n        vector<int> tmp; tmp.reserve(4000);\n        for (const auto& rect : r) {\n            fill_boundaries(rect, tmp);\n            for (int s : tmp) bits[s >> 6] |= (1ULL << (s & 63));\n        }\n    };\n    get_wall_bits(rects[0], prev_bits);\n\n    vector<int> prev_areas(N);\n    for (int k = 0; k < N; ++k) prev_areas[k] = rects[0][k].area();\n    total_area_penalty = 0;\n    auto area_penalty_vec = [&](const vector<int>& areas, const vector<int>& dem) {\n        int pen = 0;\n        for (int k = 0; k < N; ++k)\n            if (areas[k] < dem[k]) pen += 100 * (dem[k] - areas[k]);\n        return pen;\n    };\n    total_area_penalty = area_penalty_vec(prev_areas, a[0]);\n    total_L_sum = 0;\n\n    for (int d = 1; d < D; ++d) {\n        auto cand = pack_exact(a[d]);\n        vector<uint64_t> cand_bits((SEG + 63) / 64, 0);\n        get_wall_bits(cand, cand_bits);\n        vector<int> cand_areas(N);\n        for (int k = 0; k < N; ++k) cand_areas[k] = cand[k].area();\n        int pen_keep   = area_penalty_vec(prev_areas, a[d]);\n        int pen_switch = area_penalty_vec(cand_areas, a[d]);\n        int L = 0;\n        for (int i = 0; i < (int)prev_bits.size(); ++i)\n            L += __builtin_popcountll(prev_bits[i] ^ cand_bits[i]);\n\n        if (pen_switch + L < pen_keep) {\n            total_area_penalty += pen_switch;\n            total_L_sum += L;\n            rects[d] = move(cand);\n            prev_bits.swap(cand_bits);\n            prev_areas.swap(cand_areas);\n        } else {\n            total_area_penalty += pen_keep;\n            rects[d] = rects[d - 1];\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false); cin.tie(nullptr);\n    cin >> W >> D >> N;\n    a.resize(D, vector<int>(N));\n    for (int d = 0; d < D; ++d)\n        for (int k = 0; k < N; ++k)\n            cin >> a[d][k];\n\n    // 1) initial greedy solution (day\u2011by\u2011day greedy switch)\n    build_from_greedy();\n\n    // 2) build count array and exact cost\n    cnt.assign(D * SEG, uint8_t(0));\n    vector<int> seg_buf; seg_buf.reserve(4000);\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            fill_boundaries(rects[d][k], seg_buf);\n            int base = d * SEG;\n            for (int s : seg_buf) cnt[base + s]++;\n        }\n    }\n\n    pen_day.resize(D, 0);\n    total_area_penalty = 0;\n    for (int d = 0; d < D; ++d) {\n        int pen = 0;\n        for (int k = 0; k < N; ++k) {\n            int ar = rects[d][k].area();\n            if (ar < a[d][k]) pen += 100 * (a[d][k] - ar);\n        }\n        pen_day[d] = pen;\n        total_area_penalty += pen;\n    }\n\n    total_L_sum = 0;\n    for (int d = 1; d < D; ++d) {\n        total_L_sum += compute_L_between(d);\n    }\n\n    best_cost = total_area_penalty + total_L_sum;\n    best_rects = rects;\n\n    // 3) simulated annealing\n    vector<int> old_segs, new_segs;\n    old_segs.reserve(4000); new_segs.reserve(4000);\n\n    auto start = chrono::steady_clock::now();\n    const double TL = 2.9;\n    while (true) {\n        double elap = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n        if (elap > TL) break;\n        double T = 500.0 * (1.0 - elap / TL);\n        if (T < 0.1) T = 0.1;\n\n        for (int iter = 0; iter < 100; ++iter) {\n            int d = rnd_int(D);\n            int k = rnd_int(N);\n            Rect old_rect = rects[d][k];\n            Rect new_rect;\n\n            int move_type = rnd_int(3);\n            if (move_type == 0) {           // shift\n                int dx = rnd_int(5) - 2;\n                int dy = rnd_int(5) - 2;\n                if (dx == 0 && dy == 0) continue;\n                new_rect = {old_rect.i0 + dx, old_rect.j0 + dy,\n                            old_rect.i1 + dx, old_rect.j1 + dy};\n            } else if (move_type == 1) {    // resize\n                int side = rnd_int(4);\n                int delta = rnd_int(9) - 4;\n                if (delta == 0) continue;\n                new_rect = old_rect;\n                if (side == 0) new_rect.i0 += delta;\n                else if (side == 1) new_rect.i1 += delta;\n                else if (side == 2) new_rect.j0 += delta;\n                else new_rect.j1 += delta;\n            } else {                        // copy from neighbour day\n                int adj = d + (rnd_int(2) ? -1 : 1);\n                if (adj < 0 || adj >= D) continue;\n                new_rect = rects[adj][k];\n            }\n\n            if (new_rect.i0 < 0 || new_rect.j0 < 0 || new_rect.i1 > W || new_rect.j1 > W) continue;\n            if (new_rect.i0 >= new_rect.i1 || new_rect.j0 >= new_rect.j1) continue;\n            bool conflict = false;\n            for (int k2 = 0; k2 < N; ++k2) {\n                if (k2 == k) continue;\n                const Rect& o = rects[d][k2];\n                if (new_rect.i0 < o.i1 && o.i0 < new_rect.i1 &&\n                    new_rect.j0 < o.j1 && o.j0 < new_rect.j1) {\n                    conflict = true; break;\n                }\n            }\n            if (conflict) continue;\n\n            int old_ar = old_rect.area(), new_ar = new_rect.area();\n            int old_short = max(0, a[d][k] - old_ar);\n            int new_short = max(0, a[d][k] - new_ar);\n            int delta_area = 100 * (new_short - old_short);\n\n            fill_boundaries(old_rect, old_segs);\n            fill_boundaries(new_rect, new_segs);\n            int delta_L = 0;\n            int d_base = d * SEG;\n\n            // tentatively apply changes\n            for (int s : old_segs) {\n                uint8_t& c = cnt[d_base + s];\n                bool old_st = (c > 0);\n                c--;\n                bool new_st = (c > 0);\n                if (old_st != new_st) delta_L += update_L_delta(d, s, old_st, new_st);\n            }\n            for (int s : new_segs) {\n                uint8_t& c = cnt[d_base + s];\n                bool old_st = (c > 0);\n                c++;\n                bool new_st = (c > 0);\n                if (old_st != new_st) delta_L += update_L_delta(d, s, old_st, new_st);\n            }\n\n            int delta_cost = delta_area + delta_L;\n            if (delta_cost <= 0 || rnd_double() < exp(-delta_cost / T)) {\n                rects[d][k] = new_rect;\n                total_area_penalty += delta_area;\n                total_L_sum += delta_L;\n                pen_day[d] += delta_area;\n            } else {\n                // revert\n                for (int s : old_segs) cnt[d_base + s]++;\n                for (int s : new_segs) cnt[d_base + s]--;\n            }\n\n            int cur_cost = total_area_penalty + total_L_sum;\n            if (cur_cost < best_cost) {\n                best_cost = cur_cost;\n                best_rects = rects;\n            }\n        }\n    }\n\n    // output best found solution\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            const Rect& r = best_rects[d][k];\n            cout << r.i0 << ' ' << r.j0 << ' ' << r.i1 << ' ' << r.j1 << '\\n';\n        }\n    }\n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <chrono>\n#include <random>\n#include <cmath>\n#include <cstring>\n#include <algorithm>\n\nusing namespace std;\nusing ll = long long;\nusing ull = unsigned long long;\n\nconst int MOD = 998244353;\nconst int N = 9;\nconst int K = 81;\nconst int M = 20;\n\nstruct Move {\n    int cells[9];\n    int vals[9];\n    int m, p, q;\n};\n\n// fast RNG\nstruct XorShift {\n    ull s;\n    XorShift(ull seed = 12345678ULL) : s(seed) {}\n    ull next() {\n        s ^= s << 13;\n        s ^= s >> 7;\n        s ^= s << 17;\n        return s;\n    }\n    int next_int(int mod) { return next() % mod; }\n    double next_double() { return (next() >> 11) * (1.0 / (1ULL << 53)); }\n    double uniform(double a, double b) { return a + (b - a) * next_double(); }\n};\n\n// board operations (inlined)\ninline void apply_add(const Move& mv, int* b, ll& sc) {\n    for (int i = 0; i < 9; ++i) {\n        int c = mv.cells[i];\n        int v = mv.vals[i];\n        int old = b[c];\n        int nv = old + v;\n        if (nv >= MOD) nv -= MOD;\n        b[c] = nv;\n        sc += nv - old;\n    }\n}\ninline ll eval_add(const Move& mv, const int* b) {\n    ll d = 0;\n    for (int i = 0; i < 9; ++i) {\n        int c = mv.cells[i];\n        int v = mv.vals[i];\n        int old = b[c];\n        int nv = old + v;\n        if (nv >= MOD) nv -= MOD;\n        d += nv - old;\n    }\n    return d;\n}\ninline void apply_remove(const Move& mv, int* b, ll& sc) {\n    for (int i = 0; i < 9; ++i) {\n        int c = mv.cells[i];\n        int v = mv.vals[i];\n        int old = b[c];\n        int nv = old - v;\n        if (nv < 0) nv += MOD;\n        b[c] = nv;\n        sc += nv - old;\n    }\n}\ninline ll eval_remove(const Move& mv, const int* b) {\n    ll d = 0;\n    for (int i = 0; i < 9; ++i) {\n        int c = mv.cells[i];\n        int v = mv.vals[i];\n        int old = b[c];\n        int nv = old - v;\n        if (nv < 0) nv += MOD;\n        d += nv - old;\n    }\n    return d;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // ---- input ----\n    int N_in, M_in, K_in;\n    cin >> N_in >> M_in >> K_in;\n    (void)N_in; (void)M_in; (void)K_in;\n\n    int init_board[N * N];\n    ll init_sum = 0;\n    for (int i = 0; i < N * N; ++i) {\n        cin >> init_board[i];\n        init_sum += init_board[i];\n    }\n\n    int stamps[M][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                cin >> stamps[m][i][j];\n\n    // ---- precompute moves ----\n    const int rows = N - 2;\n    const int cols = N - 2;\n    const int total_moves = M * rows * cols;  // 980\n\n    vector<Move> moves(total_moves);\n    for (int m = 0; m < M; ++m) {\n        for (int p = 0; p < rows; ++p) {\n            for (int q = 0; q < cols; ++q) {\n                int idx = m * rows * cols + p * cols + q;\n                moves[idx].m = m;\n                moves[idx].p = p;\n                moves[idx].q = q;\n                int ci = 0;\n                for (int i = 0; i < 3; ++i)\n                    for (int j = 0; j < 3; ++j) {\n                        moves[idx].cells[ci] = (p + i) * N + (q + j);\n                        moves[idx].vals[ci] = stamps[m][i][j];\n                        ++ci;\n                    }\n            }\n        }\n    }\n\n    // ---- timing ----\n    auto global_start = chrono::steady_clock::now();\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - global_start).count();\n    };\n    const double time_limit = 1.95;\n\n    // ---- global best ----\n    vector<int> global_best_applied;\n    ll global_best_score = 0;\n\n    random_device rd;\n    ull base_seed = (((ull)rd() << 32) | rd());\n    XorShift rng(base_seed);\n\n    // deterministic hill\u2011climbing helper\n    auto hill_climb = [&](vector<int>& cur, int* board, ll& score, bool apply_to_global = false) {\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            int L = cur.size();\n\n            // add best move\n            if (L < K) {\n                int best = -1;\n                ll best_delta = 0;\n                for (int mid = 0; mid < total_moves; ++mid) {\n                    ll d = eval_add(moves[mid], board);\n                    if (d > best_delta) { best_delta = d; best = mid; }\n                }\n                if (best_delta > 0) {\n                    apply_add(moves[best], board, score);\n                    cur.push_back(best);\n                    improved = true;\n                    if (apply_to_global && score > global_best_score) {\n                        global_best_score = score;\n                        global_best_applied = cur;\n                    }\n                    continue;\n                }\n            }\n\n            // remove worst move\n            if (L > 0) {\n                int best_i = -1;\n                ll best_delta = 0;\n                for (int i = 0; i < L; ++i) {\n                    ll d = eval_remove(moves[cur[i]], board);\n                    if (d > best_delta) { best_delta = d; best_i = i; }\n                }\n                if (best_delta > 0) {\n                    apply_remove(moves[cur[best_i]], board, score);\n                    cur[best_i] = cur.back();\n                    cur.pop_back();\n                    improved = true;\n                    if (apply_to_global && score > global_best_score) {\n                        global_best_score = score;\n                        global_best_applied = cur;\n                    }\n                    continue;\n                }\n            }\n\n            // replace move with better one\n            if (L > 0) {\n                bool found = false;\n                for (int i = 0; i < L && !found; ++i) {\n                    int old_id = cur[i];\n                    ll score_before = score;\n                    apply_remove(moves[old_id], board, score);\n                    int best_new = -1;\n                    ll best_total = 0;\n                    for (int nm = 0; nm < total_moves; ++nm) {\n                        ll delta_add = eval_add(moves[nm], board);\n                        ll total_delta = (score - score_before) + delta_add;\n                        if (total_delta > best_total) {\n                            best_total = total_delta;\n                            best_new = nm;\n                        }\n                    }\n                    if (best_total > 0) {\n                        apply_add(moves[best_new], board, score);\n                        cur[i] = best_new;\n                        improved = true;\n                        found = true;\n                        if (apply_to_global && score > global_best_score) {\n                            global_best_score = score;\n                            global_best_applied = cur;\n                        }\n                    } else {\n                        apply_add(moves[old_id], board, score);\n                    }\n                }\n                if (found) continue;\n            }\n        }\n    };\n\n    // ---- multi\u2011start episodes ----\n    while (elapsed() < time_limit - 0.05) {\n        int board[N * N];\n        memcpy(board, init_board, sizeof(board));\n        ll score = init_sum;\n        vector<int> applied;\n\n        // 1) Randomised greedy\n        double greediness = 0.8 + rng.next_double() * 0.2;\n        for (int step = 0; step < K; ++step) {\n            ll best_delta = 0;\n            for (int mid = 0; mid < total_moves; ++mid) {\n                ll d = eval_add(moves[mid], board);\n                if (d > best_delta) best_delta = d;\n            }\n            if (best_delta <= 0) break;\n            ll threshold = (ll)(best_delta * greediness);\n            vector<int> cands;\n            cands.reserve(total_moves);\n            for (int mid = 0; mid < total_moves; ++mid) {\n                ll d = eval_add(moves[mid], board);\n                if (d >= threshold) cands.push_back(mid);\n            }\n            if (cands.empty()) break;\n            int pick = cands[rng.next_int(cands.size())];\n            apply_add(moves[pick], board, score);\n            applied.push_back(pick);\n        }\n        hill_climb(applied, board, score, false);   // initial polish\n\n        vector<int> ep_best = applied;\n        ll ep_best_score = score;\n\n        // 2) SA\n        double remaining = time_limit - elapsed();\n        double sa_budget = min(0.5, remaining * 0.8);   // generous SA time\n        if (sa_budget < 0.02) break;\n\n        auto sa_start = chrono::steady_clock::now();\n        auto sa_elapsed = [&]() -> double {\n            return chrono::duration<double>(chrono::steady_clock::now() - sa_start).count();\n        };\n\n        double T_start = 1e9;\n        double T_end   = 1.0;\n        double log_ratio = log(T_end / T_start);\n\n        while (sa_elapsed() < sa_budget) {\n            double progress = sa_elapsed() / sa_budget;\n            double T = T_start * exp(progress * log_ratio);\n            if (T < T_end) T = T_end;\n\n            int L = applied.size();\n            double rd_val = rng.next_double();\n\n            if (L == 0) {\n                int nm = rng.next_int(total_moves);\n                ll delta = eval_add(moves[nm], board);\n                if (delta >= 0 || rng.next_double() < exp(delta / T)) {\n                    apply_add(moves[nm], board, score);\n                    applied.push_back(nm);\n                }\n            } else if (L == K) {\n                if (rd_val < 0.55) {   // replace\n                    int idx = rng.next_int(L);\n                    int old = applied[idx];\n                    ll score_before = score;\n                    apply_remove(moves[old], board, score);\n                    int nm = rng.next_int(total_moves);\n                    ll delta_add = eval_add(moves[nm], board);\n                    ll total_delta = (score - score_before) + delta_add;\n                    if (total_delta >= 0 || rng.next_double() < exp(total_delta / T)) {\n                        apply_add(moves[nm], board, score);\n                        applied[idx] = nm;\n                    } else {\n                        apply_add(moves[old], board, score);\n                    }\n                } else if (rd_val < 0.80) {   // remove\n                    int idx = rng.next_int(L);\n                    int old = applied[idx];\n                    ll delta = eval_remove(moves[old], board);\n                    if (delta >= 0 || rng.next_double() < exp(delta / T)) {\n                        apply_remove(moves[old], board, score);\n                        applied[idx] = applied.back();\n                        applied.pop_back();\n                    }\n                } else {                       // shift\n                    int idx = rng.next_int(L);\n                    int old_id = applied[idx];\n                    const Move& old_mv = moves[old_id];\n                    int new_id;\n                    if (rng.next_int(2) == 0) {\n                        int nm = rng.next_int(M);\n                        if (nm == old_mv.m) nm = (nm + 1) % M;\n                        new_id = nm * rows * cols + old_mv.p * cols + old_mv.q;\n                    } else {\n                        int np = old_mv.p, nq = old_mv.q;\n                        int d = rng.next_int(3) - 1;\n                        np = max(0, min(rows - 1, np + d));\n                        d = rng.next_int(3) - 1;\n                        nq = max(0, min(cols - 1, nq + d));\n                        if (np == old_mv.p && nq == old_mv.q) {\n                            int nm = rng.next_int(M);\n                            if (nm == old_mv.m) nm = (nm + 1) % M;\n                            new_id = nm * rows * cols + old_mv.p * cols + old_mv.q;\n                        } else {\n                            new_id = old_mv.m * rows * cols + np * cols + nq;\n                        }\n                    }\n                    ll score_before = score;\n                    apply_remove(moves[old_id], board, score);\n                    ll delta_add = eval_add(moves[new_id], board);\n                    ll total_delta = (score - score_before) + delta_add;\n                    if (total_delta >= 0 || rng.next_double() < exp(total_delta / T)) {\n                        apply_add(moves[new_id], board, score);\n                        applied[idx] = new_id;\n                    } else {\n                        apply_add(moves[old_id], board, score);\n                    }\n                }\n            } else {\n                if (rd_val < 0.25) {           // add\n                    int nm = rng.next_int(total_moves);\n                    ll delta = eval_add(moves[nm], board);\n                    if (delta >= 0 || rng.next_double() < exp(delta / T)) {\n                        apply_add(moves[nm], board, score);\n                        applied.push_back(nm);\n                    }\n                } else if (rd_val < 0.45) {    // remove\n                    int idx = rng.next_int(L);\n                    int old = applied[idx];\n                    ll delta = eval_remove(moves[old], board);\n                    if (delta >= 0 || rng.next_double() < exp(delta / T)) {\n                        apply_remove(moves[old], board, score);\n                        applied[idx] = applied.back();\n                        applied.pop_back();\n                    }\n                } else if (rd_val < 0.75) {    // replace\n                    int idx = rng.next_int(L);\n                    int old = applied[idx];\n                    ll score_before = score;\n                    apply_remove(moves[old], board, score);\n                    int nm = rng.next_int(total_moves);\n                    ll delta_add = eval_add(moves[nm], board);\n                    ll total_delta = (score - score_before) + delta_add;\n                    if (total_delta >= 0 || rng.next_double() < exp(total_delta / T)) {\n                        apply_add(moves[nm], board, score);\n                        applied[idx] = nm;\n                    } else {\n                        apply_add(moves[old], board, score);\n                    }\n                } else {                        // shift\n                    int idx = rng.next_int(L);\n                    int old_id = applied[idx];\n                    const Move& old_mv = moves[old_id];\n                    int new_id;\n                    if (rng.next_int(2) == 0) {\n                        int nm = rng.next_int(M);\n                        if (nm == old_mv.m) nm = (nm + 1) % M;\n                        new_id = nm * rows * cols + old_mv.p * cols + old_mv.q;\n                    } else {\n                        int np = old_mv.p, nq = old_mv.q;\n                        int d = rng.next_int(3) - 1;\n                        np = max(0, min(rows - 1, np + d));\n                        d = rng.next_int(3) - 1;\n                        nq = max(0, min(cols - 1, nq + d));\n                        if (np == old_mv.p && nq == old_mv.q) {\n                            int nm = rng.next_int(M);\n                            if (nm == old_mv.m) nm = (nm + 1) % M;\n                            new_id = nm * rows * cols + old_mv.p * cols + old_mv.q;\n                        } else {\n                            new_id = old_mv.m * rows * cols + np * cols + nq;\n                        }\n                    }\n                    ll score_before = score;\n                    apply_remove(moves[old_id], board, score);\n                    ll delta_add = eval_add(moves[new_id], board);\n                    ll total_delta = (score - score_before) + delta_add;\n                    if (total_delta >= 0 || rng.next_double() < exp(total_delta / T)) {\n                        apply_add(moves[new_id], board, score);\n                        applied[idx] = new_id;\n                    } else {\n                        apply_add(moves[old_id], board, score);\n                    }\n                }\n            }\n\n            if (score > ep_best_score) {\n                ep_best_score = score;\n                ep_best = applied;\n            }\n        }\n\n        // restore best and polish\n        memcpy(board, init_board, sizeof(board));\n        score = init_sum;\n        for (int mid : ep_best) apply_add(moves[mid], board, score);\n        hill_climb(ep_best, board, score, false);\n        if (score > ep_best_score) {\n            ep_best_score = score;\n        }\n\n        // update global best\n        if (ep_best_score > global_best_score) {\n            global_best_score = ep_best_score;\n            global_best_applied = ep_best;\n        }\n    }\n\n    // ---- final low\u2011T SA polish on global best if time left ----\n    if (!global_best_applied.empty() && elapsed() < time_limit - 0.02) {\n        int board[N * N];\n        memcpy(board, init_board, sizeof(board));\n        ll score = init_sum;\n        vector<int> cur = global_best_applied;\n        for (int mid : cur) apply_add(moves[mid], board, score);\n\n        auto polish_start = chrono::steady_clock::now();\n        double polish_budget = min(0.2, time_limit - elapsed() - 0.01);\n        if (polish_budget > 0) {\n            double T_s = 1e5;\n            double T_e = 1.0;\n            double lr = log(T_e / T_s);\n\n            while (chrono::duration<double>(chrono::steady_clock::now() - polish_start).count() < polish_budget) {\n                double progress = chrono::duration<double>(chrono::steady_clock::now() - polish_start).count() / polish_budget;\n                double T = T_s * exp(progress * lr);\n                if (T < T_e) T = T_e;\n\n                int L = cur.size();\n                if (L == 0) break;\n                if (L < K) {\n                    // either add or replace\n                    if (rng.next_double() < 0.3) {\n                        int nm = rng.next_int(total_moves);\n                        ll delta = eval_add(moves[nm], board);\n                        if (delta >= 0 || rng.next_double() < exp(delta / T)) {\n                            apply_add(moves[nm], board, score);\n                            cur.push_back(nm);\n                        }\n                    } else {\n                        int idx = rng.next_int(L);\n                        int old = cur[idx];\n                        ll score_before = score;\n                        apply_remove(moves[old], board, score);\n                        int nm = rng.next_int(total_moves);\n                        ll delta_add = eval_add(moves[nm], board);\n                        ll total_delta = (score - score_before) + delta_add;\n                        if (total_delta >= 0 || rng.next_double() < exp(total_delta / T)) {\n                            apply_add(moves[nm], board, score);\n                            cur[idx] = nm;\n                        } else {\n                            apply_add(moves[old], board, score);\n                        }\n                    }\n                } else {\n                    // replace or remove\n                    if (rng.next_double() < 0.6) {\n                        int idx = rng.next_int(L);\n                        int old = cur[idx];\n                        ll score_before = score;\n                        apply_remove(moves[old], board, score);\n                        int nm = rng.next_int(total_moves);\n                        ll delta_add = eval_add(moves[nm], board);\n                        ll total_delta = (score - score_before) + delta_add;\n                        if (total_delta >= 0 || rng.next_double() < exp(total_delta / T)) {\n                            apply_add(moves[nm], board, score);\n                            cur[idx] = nm;\n                        } else {\n                            apply_add(moves[old], board, score);\n                        }\n                    } else {\n                        int idx = rng.next_int(L);\n                        int old = cur[idx];\n                        ll delta = eval_remove(moves[old], board);\n                        if (delta >= 0 || rng.next_double() < exp(delta / T)) {\n                            apply_remove(moves[old], board, score);\n                            cur[idx] = cur.back();\n                            cur.pop_back();\n                        }\n                    }\n                }\n\n                if (score > global_best_score) {\n                    global_best_score = score;\n                    global_best_applied = cur;\n                }\n            }\n            // final deterministic hill\u2011climb\n            memcpy(board, init_board, sizeof(board));\n            score = init_sum;\n            for (int mid : global_best_applied) apply_add(moves[mid], board, score);\n            hill_climb(global_best_applied, board, score, true);\n        }\n    }\n\n    // ---- output ----\n    cout << global_best_applied.size() << \"\\n\";\n    for (int mid : global_best_applied) {\n        cout << moves[mid].m << \" \" << moves[mid].p << \" \" << moves[mid].q << \"\\n\";\n    }\n\n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\nusing namespace std;\n\nconst int N = 5;\nconst int MAX_TURNS = 10000;\n\nint A[N][N];\nint arrival_gate[25];\nint arrival_pos[25];\nint arrival_idx[N];\nint grid[N][N];\nint container_pos[25]; // -1: not on ground, -2: dispatched, else r*N+c\nint next_needed[N];\nint crane_r, crane_c, holding;\nint total_dispatched;\n\n// Count empty cells in columns 1..3\nint count_empty_buffers() {\n    int cnt = 0;\n    for (int r = 0; r < N; ++r)\n        for (int c = 1; c <= 3; ++c)\n            if (grid[r][c] == -1) ++cnt;\n    return cnt;\n}\n\n// Find an empty buffer cell, prefer columns 1..3 of the given row, then any.\n// Returns {-1,-1} if no empty buffer exists (should not happen when called properly).\npair<int,int> find_buffer_cell(int pref_row) {\n    // first try preferred row\n    for (int c = 1; c <= 3; ++c)\n        if (grid[pref_row][c] == -1) return {pref_row, c};\n    // then any row\n    for (int r = 0; r < N; ++r) {\n        for (int c = 1; c <= 3; ++c) {\n            if (grid[r][c] == -1) return {r, c};\n        }\n    }\n    return {-1, -1}; // should not reach if we checked count > 0\n}\n\nchar move_towards(int tr, int tc) {\n    if (crane_r < tr) return 'D';\n    if (crane_r > tr) return 'U';\n    if (crane_c < tc) return 'R';\n    if (crane_c > tc) return 'L';\n    return '.';\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            cin >> A[i][j];\n            arrival_gate[A[i][j]] = i;\n            arrival_pos[A[i][j]] = j;\n        }\n\n    // Initialize state\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            grid[i][j] = -1;\n    for (int i = 0; i < 25; ++i) container_pos[i] = -1;\n    for (int i = 0; i < N; ++i) {\n        arrival_idx[i] = 0;\n        next_needed[i] = i * N;\n    }\n    crane_r = 0; crane_c = 0; holding = -1;\n    total_dispatched = 0;\n    string L_actions;\n    int turn = 0;\n\n    while (total_dispatched < N * N && turn < MAX_TURNS) {\n        // ---------- Step 1: Receiving ----------\n        for (int i = 0; i < N; ++i) {\n            if (grid[i][0] == -1 && arrival_idx[i] < N) {\n                bool blocked = (holding != -1 && crane_r == i && crane_c == 0);\n                if (!blocked) {\n                    int cont = A[i][arrival_idx[i]++];\n                    grid[i][0] = cont;\n                    container_pos[cont] = i * N + 0;\n                }\n            }\n        }\n\n        int empty_buf = count_empty_buffers();\n        char act = '.';\n\n        if (holding == -1) {\n            // 1) favor the smallest next_needed that is already on the ground\n            int best_id = -1;\n            int best_dist = 1000000;\n            for (int i = 0; i < N; ++i) {\n                int t = next_needed[i];\n                if (t >= N * N) continue;\n                if (container_pos[t] >= 0) {\n                    int pos = container_pos[t];\n                    int tr = pos / N, tc = pos % N;\n                    int d = abs(crane_r - tr) + abs(crane_c - tc);\n                    if (d < best_dist) {\n                        best_dist = d;\n                        best_id = t;\n                    }\n                }\n            }\n\n            if (best_id != -1) {\n                // target on ground\n                int pos = container_pos[best_id];\n                int tr = pos / N, tc = pos % N;\n                if (crane_r == tr && crane_c == tc) act = 'P';\n                else act = move_towards(tr, tc);\n            } else if (empty_buf > 0) {\n                // no target on ground, but we can clear a gate\n                int chosen_gate = -1;\n                int dist_gate = 1000000;\n                for (int i = 0; i < N; ++i) {\n                    if (grid[i][0] != -1) {\n                        int d = abs(crane_r - i) + abs(crane_c - 0);\n                        if (d < dist_gate) {\n                            dist_gate = d;\n                            chosen_gate = i;\n                        }\n                    }\n                }\n                if (chosen_gate != -1) {\n                    if (crane_r == chosen_gate && crane_c == 0) act = 'P';\n                    else act = move_towards(chosen_gate, 0);\n                } else {\n                    // all gates empty, wait near a gate that still has arrivals\n                    int wait_row = -1;\n                    int wait_dist = 1000000;\n                    for (int i = 0; i < N; ++i) {\n                        if (arrival_idx[i] < N) {\n                            int d = abs(crane_r - i) + abs(crane_c - 1);\n                            if (d < wait_dist) {\n                                wait_dist = d;\n                                wait_row = i;\n                            }\n                        }\n                    }\n                    if (wait_row != -1) {\n                        if (crane_r == wait_row && crane_c == 1) act = '.';\n                        else act = move_towards(wait_row, 1);\n                    }\n                }\n            } else {\n                // buffers full, no target on ground -> dispatch a target from a buffer\n                int best_buf_target = -1;\n                int best_buf_dist = 1000000;\n                for (int r = 0; r < N; ++r) {\n                    for (int c = 1; c <= 3; ++c) {\n                        int cont = grid[r][c];\n                        if (cont != -1 && cont == next_needed[cont / N]) {\n                            int d = abs(crane_r - r) + abs(crane_c - c);\n                            if (d < best_buf_dist) {\n                                best_buf_dist = d;\n                                best_buf_target = cont;\n                            }\n                        }\n                    }\n                }\n                if (best_buf_target != -1) {\n                    int pos = container_pos[best_buf_target];\n                    int tr = pos / N, tc = pos % N;\n                    if (crane_r == tr && crane_c == tc) act = 'P';\n                    else act = move_towards(tr, tc);\n                } else {\n                    // no dispatchable target in buffer, wait near a gate that will receive a target\n                    // (this should be rare)\n                    int wait_row = -1;\n                    int wait_dist = 1000000;\n                    for (int i = 0; i < N; ++i) {\n                        if (arrival_idx[i] < N) {\n                            int d = abs(crane_r - i) + abs(crane_c - 1);\n                            if (d < wait_dist) {\n                                wait_dist = d;\n                                wait_row = i;\n                            }\n                        }\n                    }\n                    if (wait_row != -1) {\n                        if (crane_r == wait_row && crane_c == 1) act = '.';\n                        else act = move_towards(wait_row, 1);\n                    }\n                }\n            }\n        } else { // holding a container\n            int C = holding;\n            if (C == next_needed[C / N]) {\n                // deliver to dispatch gate\n                int tr = C / N, tc = 4;\n                if (crane_r == tr && crane_c == tc) act = 'Q';\n                else act = move_towards(tr, tc);\n            } else {\n                // store in buffer\n                auto buf = find_buffer_cell(C / N); // prefer same row\n                if (buf.first != -1) {\n                    if (crane_r == buf.first && crane_c == buf.second) act = 'Q';\n                    else act = move_towards(buf.first, buf.second);\n                } else {\n                    // should not happen if we checked empty_buf before picking\n                    act = '.';\n                }\n            }\n        }\n\n        // Apply action\n        if (act == 'U') crane_r--;\n        else if (act == 'D') crane_r++;\n        else if (act == 'L') crane_c--;\n        else if (act == 'R') crane_c++;\n        else if (act == 'P') {\n            int cont = grid[crane_r][crane_c];\n            grid[crane_r][crane_c] = -1;\n            holding = cont;\n            container_pos[cont] = -1;\n        } else if (act == 'Q') {\n            grid[crane_r][crane_c] = holding;\n            container_pos[holding] = crane_r * N + crane_c;\n            holding = -1;\n        }\n        L_actions.push_back(act);\n\n        // ---------- Step 3: Dispatching ----------\n        for (int i = 0; i < N; ++i) {\n            if (grid[i][4] != -1) {\n                int cont = grid[i][4];\n                grid[i][4] = -1;\n                container_pos[cont] = -2;\n                if (cont == next_needed[i]) {\n                    next_needed[i]++;\n                    total_dispatched++;\n                }\n            }\n        }\n\n        ++turn;\n    }\n\n    // Output\n    cout << L_actions << \"\\n\";\n    // bomb all small cranes on the first turn (they do nothing)\n    for (int i = 1; i < N; ++i) cout << \"B\\n\";\n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <climits>\nusing namespace std;\n\nstruct Task {\n    int r, c, h;\n};\n\nconst int MAX_S = 400;\n\nint main() {\n    auto start_time = chrono::steady_clock::now();\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto rand_int = [&](int lo, int hi) {\n        return uniform_int_distribution<int>(lo, hi)(rng);\n    };\n    auto rand_double = [&]() {\n        return uniform_real_distribution<double>(0.0, 1.0)(rng);\n    };\n    auto getTime = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<vector<int>> H(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> H[i][j];\n\n    vector<Task> tasks;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (H[i][j] != 0)\n                tasks.push_back({i, j, H[i][j]});\n\n    int S = tasks.size();\n    if (S == 0) return 0;\n\n    auto manhattan = [](int r1, int c1, int r2, int c2) {\n        return abs(r1 - r2) + abs(c1 - c2);\n    };\n\n    vector<int> startDist(S);\n    for (int i = 0; i < S; ++i) startDist[i] = manhattan(0, 0, tasks[i].r, tasks[i].c);\n    vector<vector<int>> dist(S, vector<int>(S));\n    for (int i = 0; i < S; ++i)\n        for (int j = 0; j < S; ++j)\n            dist[i][j] = manhattan(tasks[i].r, tasks[i].c, tasks[j].r, tasks[j].c);\n\n    auto evaluate = [&](const vector<int>& perm) -> long long {\n        long long cost = 0;\n        int load = 0;\n        int prev = -1;\n        for (int idx : perm) {\n            int d = (prev == -1) ? startDist[idx] : dist[prev][idx];\n            cost += (100LL + load) * d;\n            load += tasks[idx].h;\n            if (load < 0) return -1;\n            prev = idx;\n        }\n        if (load != 0) return -1;\n        return cost;\n    };\n\n    vector<int> posIdx, negIdx;\n    for (int i = 0; i < S; ++i)\n        (tasks[i].h > 0 ? posIdx : negIdx).push_back(i);\n\n    vector<int> bestPerm;\n    long long bestCost = LLONG_MAX;\n\n    auto update_best = [&](const vector<int>& cand) {\n        long long c = evaluate(cand);\n        if (c != -1 && c < bestCost) {\n            bestCost = c;\n            bestPerm = cand;\n        }\n    };\n\n    // initial solutions: all positives then negatives (shuffled)\n    for (int rep = 0; rep < 30; ++rep) {\n        vector<int> cand = posIdx;\n        shuffle(cand.begin(), cand.end(), rng);\n        vector<int> negCand = negIdx;\n        shuffle(negCand.begin(), negCand.end(), rng);\n        cand.insert(cand.end(), negCand.begin(), negCand.end());\n        update_best(cand);\n    }\n\n    // greedy interleaved\n    auto greedy_interleaved = [&]() -> vector<int> {\n        vector<int> order;\n        vector<bool> used(S, false);\n        int cur_r = 0, cur_c = 0;\n        int load = 0;\n        while ((int)order.size() < S) {\n            vector<pair<long long, int>> cands;\n            for (int i = 0; i < S; ++i) {\n                if (used[i]) continue;\n                if (load + tasks[i].h < 0) continue;\n                int d = manhattan(cur_r, cur_c, tasks[i].r, tasks[i].c);\n                long long mc = (100LL + load) * d;\n                cands.emplace_back(mc, i);\n            }\n            if (cands.empty()) break;\n            sort(cands.begin(), cands.end());\n            int topK = min(8, (int)cands.size());\n            int pick = cands[rand_int(0, topK - 1)].second;\n            order.push_back(pick);\n            used[pick] = true;\n            cur_r = tasks[pick].r;\n            cur_c = tasks[pick].c;\n            load += tasks[pick].h;\n        }\n        return order;\n    };\n\n    for (int rep = 0; rep < 50; ++rep) {\n        vector<int> cand = greedy_interleaved();\n        if ((int)cand.size() != S) continue;\n        update_best(cand);\n    }\n\n    if (bestCost == LLONG_MAX) {\n        bestPerm = posIdx;\n        bestPerm.insert(bestPerm.end(), negIdx.begin(), negIdx.end());\n        bestCost = evaluate(bestPerm);\n    }\n\n    vector<int> curPerm = bestPerm;\n    long long curCost = bestCost;\n\n    // SA parameters\n    double T = 1500.0;\n    double T_min = 0.01;\n    double alpha = 0.9998;\n    int step = 0;\n    const int TIME_CHECK_INTERVAL = 500;\n\n    while (true) {\n        if (step % TIME_CHECK_INTERVAL == 0 && getTime() > 1.85) break;\n        int moveType = rand_int(0, 2);\n        if (moveType == 0) { // swap\n            int i = rand_int(0, S - 1);\n            int j = rand_int(0, S - 1);\n            if (i == j) continue;\n            swap(curPerm[i], curPerm[j]);\n            long long newCost = evaluate(curPerm);\n            if (newCost != -1) {\n                long long delta = newCost - curCost;\n                if (delta <= 0 || rand_double() < exp(-delta / T)) {\n                    curCost = newCost;\n                    if (curCost < bestCost) {\n                        bestCost = curCost;\n                        bestPerm = curPerm;\n                    }\n                } else {\n                    swap(curPerm[i], curPerm[j]);\n                }\n            } else {\n                swap(curPerm[i], curPerm[j]);\n            }\n        } else if (moveType == 1) { // reverse\n            if (S < 2) continue;\n            int l = rand_int(0, S - 2);\n            int r = rand_int(l + 1, S - 1);\n            reverse(curPerm.begin() + l, curPerm.begin() + r + 1);\n            long long newCost = evaluate(curPerm);\n            if (newCost != -1) {\n                long long delta = newCost - curCost;\n                if (delta <= 0 || rand_double() < exp(-delta / T)) {\n                    curCost = newCost;\n                    if (curCost < bestCost) {\n                        bestCost = curCost;\n                        bestPerm = curPerm;\n                    }\n                } else {\n                    reverse(curPerm.begin() + l, curPerm.begin() + r + 1);\n                }\n            } else {\n                reverse(curPerm.begin() + l, curPerm.begin() + r + 1);\n            }\n        } else { // insert\n            int from = rand_int(0, S - 1);\n            int to = rand_int(0, S - 1);\n            if (from == to || from == to + 1) continue;\n            vector<int> cand = curPerm;\n            int val = cand[from];\n            cand.erase(cand.begin() + from);\n            int ins = (to > from) ? to - 1 : to;\n            cand.insert(cand.begin() + ins, val);\n            long long newCost = evaluate(cand);\n            if (newCost != -1) {\n                long long delta = newCost - curCost;\n                if (delta <= 0 || rand_double() < exp(-delta / T)) {\n                    curPerm = move(cand);\n                    curCost = newCost;\n                    if (curCost < bestCost) {\n                        bestCost = curCost;\n                        bestPerm = curPerm;\n                    }\n                }\n            }\n        }\n        T *= alpha;\n        if (T < T_min) T = T_min;\n        ++step;\n    }\n\n    // final hill climbing (random moves)\n    int noImprove = 0;\n    const int MAX_HILL = 30000;\n    for (int rep = 0; rep < MAX_HILL; ++rep) {\n        if (getTime() > 1.95) break;\n        int moveType = rand_int(0, 2);\n        if (moveType == 0) {\n            int i = rand_int(0, S - 1), j = rand_int(0, S - 1);\n            if (i == j) continue;\n            swap(curPerm[i], curPerm[j]);\n            long long newCost = evaluate(curPerm);\n            if (newCost != -1 && newCost < curCost) {\n                curCost = newCost;\n                if (curCost < bestCost) {\n                    bestCost = curCost;\n                    bestPerm = curPerm;\n                }\n                noImprove = 0;\n            } else {\n                swap(curPerm[i], curPerm[j]);\n                ++noImprove;\n            }\n        } else if (moveType == 1) {\n            if (S < 2) continue;\n            int l = rand_int(0, S - 2), r = rand_int(l + 1, S - 1);\n            reverse(curPerm.begin() + l, curPerm.begin() + r + 1);\n            long long newCost = evaluate(curPerm);\n            if (newCost != -1 && newCost < curCost) {\n                curCost = newCost;\n                if (curCost < bestCost) {\n                    bestCost = curCost;\n                    bestPerm = curPerm;\n                }\n                noImprove = 0;\n            } else {\n                reverse(curPerm.begin() + l, curPerm.begin() + r + 1);\n                ++noImprove;\n            }\n        } else {\n            int from = rand_int(0, S - 1), to = rand_int(0, S - 1);\n            if (from == to || from == to + 1) continue;\n            vector<int> cand = curPerm;\n            int val = cand[from];\n            cand.erase(cand.begin() + from);\n            int ins = (to > from) ? to - 1 : to;\n            cand.insert(cand.begin() + ins, val);\n            long long newCost = evaluate(cand);\n            if (newCost != -1 && newCost < curCost) {\n                curPerm = move(cand);\n                curCost = newCost;\n                if (curCost < bestCost) {\n                    bestCost = curCost;\n                    bestPerm = curPerm;\n                }\n                noImprove = 0;\n            } else {\n                ++noImprove;\n            }\n        }\n        if (noImprove >= 2000) break;\n    }\n\n    // Output\n    vector<string> ops;\n    int cur_r = 0, cur_c = 0;\n    for (int idx : bestPerm) {\n        int tr = tasks[idx].r, tc = tasks[idx].c;\n        while (cur_r < tr) { ops.push_back(\"D\"); cur_r++; }\n        while (cur_r > tr) { ops.push_back(\"U\"); cur_r--; }\n        while (cur_c < tc) { ops.push_back(\"R\"); cur_c++; }\n        while (cur_c > tc) { ops.push_back(\"L\"); cur_c--; }\n        if (tasks[idx].h > 0) {\n            ops.push_back(\"+\" + to_string(tasks[idx].h));\n        } else {\n            ops.push_back(\"-\" + to_string(-tasks[idx].h));\n        }\n    }\n    for (const auto& s : ops) cout << s << '\\n';\n\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <chrono>\n#include <cstdint>\n#include <cstring>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, T;\n    cin >> N >> M >> T;\n    const int seed_cnt = 2 * N * (N - 1);   // 60\n    const int cells = N * N;                // 36\n\n    // initial pool\n    vector<vector<int>> seeds(seed_cnt, vector<int>(M));\n    for (int i = 0; i < seed_cnt; ++i)\n        for (int j = 0; j < M; ++j)\n            cin >> seeds[i][j];\n\n    // grid helper: linear index of cell (r,c) = r*N + c\n    auto idx = [&](int r, int c) { return r * N + c; };\n\n    // adjacency list for cells\n    vector<vector<int>> adj(cells);\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int id = idx(r, c);\n            if (r > 0) adj[id].push_back(idx(r - 1, c));\n            if (r < N - 1) adj[id].push_back(idx(r + 1, c));\n            if (c > 0) adj[id].push_back(idx(r, c - 1));\n            if (c < N - 1) adj[id].push_back(idx(r, c + 1));\n        }\n    }\n\n    // list of edges (each unordered pair once)\n    vector<pair<int, int>> edges;\n    for (int i = 0; i < cells; ++i)\n        for (int nb : adj[i])\n            if (i < nb) edges.push_back({i, nb});\n\n    // cell ordering by degree (descending) \u2013 used later if needed\n    vector<int> deg(cells);\n    for (int i = 0; i < cells; ++i) deg[i] = adj[i].size();\n    vector<int> cell_order(cells);\n    iota(cell_order.begin(), cell_order.end(), 0);\n    sort(cell_order.begin(), cell_order.end(), [&](int a, int b) {\n        if (deg[a] != deg[b]) return deg[a] > deg[b];\n        return a < b;\n    });\n\n    // random generator\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> cell_dist(0, cells - 1);\n\n    // time limit per turn (2 sec total for 10 turns \u2192 0.2 sec per turn)\n    const auto turn_time_limit = chrono::milliseconds(180);\n\n    for (int t = 0; t < T; ++t) {\n        // ----- compute current feature maximums and seed statistics -----\n        vector<int> cur_max(M, 0);\n        for (int i = 0; i < seed_cnt; ++i)\n            for (int j = 0; j < M; ++j)\n                if (seeds[i][j] > cur_max[j]) cur_max[j] = seeds[i][j];\n\n        vector<uint16_t> mask(seed_cnt, 0);\n        vector<int> sum_val(seed_cnt, 0);\n        for (int i = 0; i < seed_cnt; ++i) {\n            uint16_t m = 0;\n            int s = 0;\n            for (int j = 0; j < M; ++j) {\n                s += seeds[i][j];\n                if (seeds[i][j] == cur_max[j]) m |= (1 << j);\n            }\n            mask[i] = m;\n            sum_val[i] = s;\n        }\n\n        // pairwise potential (sum of feature\u2011wise max)\n        vector<vector<int>> pot(seed_cnt, vector<int>(seed_cnt, 0));\n        for (int i = 0; i < seed_cnt; ++i)\n            for (int j = i + 1; j < seed_cnt; ++j) {\n                int p = 0;\n                for (int l = 0; l < M; ++l) p += max(seeds[i][l], seeds[j][l]);\n                pot[i][j] = pot[j][i] = p;\n            }\n\n        // ----- seed selection -----\n        vector<bool> selected_flag(seed_cnt, false);\n        vector<int> selected;\n\n        // greedy set cover for current maximum features\n        uint16_t uncovered = (1 << M) - 1;\n        while (uncovered) {\n            int best_i = -1, best_cnt = 0, best_score = -1;\n            for (int i = 0; i < seed_cnt; ++i) {\n                if (selected_flag[i]) continue;\n                int cnt = __builtin_popcount((unsigned int)(mask[i] & uncovered));\n                if (cnt == 0) continue;\n                int score = __builtin_popcount((unsigned int)mask[i]) * 1000 + sum_val[i];\n                if (cnt > best_cnt || (cnt == best_cnt && score > best_score)) {\n                    best_cnt = cnt;\n                    best_score = score;\n                    best_i = i;\n                }\n            }\n            if (best_i == -1) break;   // should never happen\n            selected_flag[best_i] = true;\n            selected.push_back(best_i);\n            uncovered &= ~mask[best_i];\n        }\n\n        // fill remaining slots using pair potential with already selected seeds\n        while ((int)selected.size() < cells) {\n            int best_i = -1;\n            long long best_score = -1;\n            for (int i = 0; i < seed_cnt; ++i) {\n                if (selected_flag[i]) continue;\n                int max_pot = 0;\n                for (int s : selected) max_pot = max(max_pot, pot[s][i]);\n                long long score = max_pot * 10LL + sum_val[i];\n                if (score > best_score) {\n                    best_score = score;\n                    best_i = i;\n                }\n            }\n            selected_flag[best_i] = true;\n            selected.push_back(best_i);\n        }\n\n        // ----- intra\u2011edge score (based on current maximum masks) -----\n        auto pair_score_fn = [&](uint16_t m1, uint16_t m2) {\n            return 2 * __builtin_popcount((unsigned int)(m1 & m2))\n                 + __builtin_popcount((unsigned int)(m1 ^ m2));\n        };\n\n        vector<vector<int>> pair_score(seed_cnt, vector<int>(seed_cnt));\n        for (int i = 0; i < seed_cnt; ++i)\n            for (int j = 0; j < seed_cnt; ++j)\n                pair_score[i][j] = pair_score_fn(mask[i], mask[j]);\n\n        // ----- initial placement: greedy, starting from the best pair -----\n        // find best pair among selected\n        int best_pair_val = -1;\n        int best_a = -1, best_b = -1;\n        for (int i = 0; i < (int)selected.size(); ++i)\n            for (int j = i + 1; j < (int)selected.size(); ++j) {\n                int val = pot[selected[i]][selected[j]];\n                if (val > best_pair_val) {\n                    best_pair_val = val;\n                    best_a = i;   // index in selected\n                    best_b = j;\n                }\n            }\n\n        vector<int> assign(cells, -1);\n        vector<bool> cell_used(cells, false);\n        vector<int> seeds_to_place = selected; // copy\n\n        // start with a high\u2011degree edge (we pick (2,2)-(2,3) if N=6)\n        int start_cell1 = idx(2, 2), start_cell2 = idx(2, 3);\n        assign[start_cell1] = seeds_to_place[best_a];\n        assign[start_cell2] = seeds_to_place[best_b];\n        cell_used[start_cell1] = cell_used[start_cell2] = true;\n\n        // mark those two seeds as placed\n        vector<bool> seed_placed(seed_cnt, false);\n        seed_placed[seeds_to_place[best_a]] = seed_placed[seeds_to_place[best_b]] = true;\n\n        // list of frontier cells (empty cells adjacent to a placed cell)\n        vector<int> frontier;\n        auto add_frontier = [&](int cell) {\n            for (int nb : adj[cell])\n                if (!cell_used[nb]) {\n                    bool already = false;\n                    for (int f : frontier) if (f == nb) { already = true; break; }\n                    if (!already) frontier.push_back(nb);\n                }\n        };\n        add_frontier(start_cell1);\n        add_frontier(start_cell2);\n\n        // place remaining seeds\n        vector<int> unplaced;\n        for (int idx : selected)\n            if (!seed_placed[idx]) unplaced.push_back(idx);\n\n        while (!unplaced.empty()) {\n            int best_cell = -1, best_seed = -1;\n            int best_gain = -1;\n            // for each frontier cell and each unplaced seed, compute gain = sum of pair_score with all placed neighbours\n            for (int cell : frontier) {\n                // compute neighbour masks already placed\n                int base_gain = 0;   // could be precomputed but small\n                for (int nb : adj[cell])\n                    if (assign[nb] != -1)\n                        base_gain = 0; // we'll compute per seed\n                for (int sidx = 0; sidx < (int)unplaced.size(); ++sidx) {\n                    int seed = unplaced[sidx];\n                    int gain = 0;\n                    for (int nb : adj[cell]) {\n                        if (assign[nb] != -1)\n                            gain += pair_score[seed][assign[nb]];\n                    }\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        best_cell = cell;\n                        best_seed = sidx;\n                    }\n                }\n            }\n            // place the best found\n            assign[best_cell] = unplaced[best_seed];\n            cell_used[best_cell] = true;\n            seed_placed[unplaced[best_seed]] = true;\n            // update frontier: remove the cell just filled and add its empty neighbours\n            frontier.erase(remove(frontier.begin(), frontier.end(), best_cell), frontier.end());\n            add_frontier(best_cell);\n            // remove the placed seed from unplaced\n            unplaced.erase(unplaced.begin() + best_seed);\n        }\n\n        // ----- hill climbing with delta swaps -----\n        // delta function\n        auto delta_swap = [&](int u, int v) {\n            int delta = 0;\n            for (int nb : adj[u]) {\n                if (nb == v) continue;\n                delta -= pair_score[assign[u]][assign[nb]];\n                delta += pair_score[assign[v]][assign[nb]];\n            }\n            for (int nb : adj[v]) {\n                if (nb == u) continue;\n                delta -= pair_score[assign[v]][assign[nb]];\n                delta += pair_score[assign[u]][assign[nb]];\n            }\n            return delta;\n        };\n\n        int cur_total = 0;\n        for (auto &e : edges)\n            cur_total += pair_score[assign[e.first]][assign[e.second]];\n\n        int best_total = cur_total;\n        vector<int> best_assign = assign;\n\n        auto turn_start = chrono::steady_clock::now();\n        for (int it = 0; ; ++it) {\n            if (it % 1024 == 0) {\n                auto now = chrono::steady_clock::now();\n                if (now - turn_start > turn_time_limit) break;\n            }\n            int u = cell_dist(rng);\n            int v = cell_dist(rng);\n            if (u == v) continue;\n\n            int delta = delta_swap(u, v);\n            if (delta > 0) {\n                swap(assign[u], assign[v]);\n                cur_total += delta;\n                if (cur_total > best_total) {\n                    best_total = cur_total;\n                    best_assign = assign;\n                }\n            }\n        }\n\n        assign = best_assign;\n\n        // ----- output -----\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                if (c) cout << ' ';\n                cout << assign[idx(r, c)];\n            }\n            cout << '\\n';\n        }\n        cout.flush();\n\n        // ----- read next generation -----\n        for (int i = 0; i < seed_cnt; ++i)\n            for (int j = 0; j < M; ++j)\n                cin >> seeds[i][j];\n    }\n\n    return 0;\n}","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <functional>\n#include <numeric>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    int N, M, V;\n    cin >> N >> M >> V;\n    vector<string> s_str(N), t_str(N);\n    for (int i = 0; i < N; ++i) cin >> s_str[i];\n    for (int i = 0; i < N; ++i) cin >> t_str[i];\n    \n    vector<vector<int>> s(N, vector<int>(N));\n    vector<vector<int>> t(N, vector<int>(N));\n    int sources = 0, targets = 0;   // sources: s=1,t=0  targets: t=1,s=0\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            s[i][j] = (s_str[i][j] == '1');\n            t[i][j] = (t_str[i][j] == '1');\n            if (s[i][j] && !t[i][j]) sources++;\n            if (t[i][j] && !s[i][j]) targets++;\n        }\n    }\n    \n    int Vp = V;\n    int C = Vp - 1;                     // number of leaves (arms)\n    vector<int> arm_len(C);\n    for (int i = 0; i < C; ++i) arm_len[i] = i + 1;   // lengths 1 .. C\n    \n    // Output tree design and initial root\n    cout << Vp << \"\\n\";\n    for (int i = 0; i < C; ++i) {\n        cout << 0 << \" \" << arm_len[i] << \"\\n\";\n    }\n    int init_rx = 0, init_ry = 0;\n    cout << init_rx << \" \" << init_ry << \"\\n\";\n    \n    int rx = init_rx, ry = init_ry;\n    vector<bool> hold(C, false);\n    vector<int> cur_dir(C, 0);          // current arm direction: 0:R, 1:D, 2:L, 3:U\n    const int dx[4] = {0, 1, 0, -1};    // row change\n    const int dy[4] = {1, 0, -1, 0};    // col change\n    \n    // Build a snake path covering the whole grid\n    vector<pair<int,int>> path;\n    for (int r = 0; r < N; ++r) {\n        if (r % 2 == 0) {\n            for (int c = 0; c < N; ++c) path.emplace_back(r, c);\n        } else {\n            for (int c = N - 1; c >= 0; --c) path.emplace_back(r, c);\n        }\n    }\n    \n    const int MAX_TURNS = 100000;\n    int turn_cnt = 0;\n    \n    auto output_turn = [&](char move_char, const string& rot, const string& act) {\n        string S(2 * Vp, '.');\n        S[0] = move_char;\n        for (int i = 0; i < C; ++i) S[1 + i] = rot[i];\n        for (int i = 0; i < Vp; ++i) S[Vp + i] = act[i];\n        cout << S << \"\\n\";\n        ++turn_cnt;\n    };\n    \n    int path_idx = 0;\n    while (turn_cnt < MAX_TURNS) {\n        // termination condition\n        if (sources == 0 && targets == 0 &&\n            none_of(hold.begin(), hold.end(), [](bool v) { return v; })) {\n            break;\n        }\n        \n        if (path_idx >= (int)path.size()) path_idx = 0;\n        auto [tr, tc] = path[path_idx];\n        \n        // If we are not at the planned target, move one step towards it\n        if (rx != tr || ry != tc) {\n            int dr = 0, dc = 0;\n            if (tr > rx) dr = 1;\n            else if (tr < rx) dr = -1;\n            else if (tc > ry) dc = 1;\n            else if (tc < ry) dc = -1;\n            char move_c = '.';\n            if (dr == 1) move_c = 'D';\n            else if (dr == -1) move_c = 'U';\n            else if (dc == 1) move_c = 'R';\n            else if (dc == -1) move_c = 'L';\n            string rot(C, '.'), act(Vp, '.');\n            output_turn(move_c, rot, act);\n            rx += dr;\n            ry += dc;\n            continue;\n        }\n        \n        // At target: try to perform pick/place actions\n        // Build bipartite matching: arm i -> cell id\n        vector<vector<pair<int,int>>> opts(C); // (cell_id, direction)\n        for (int i = 0; i < C; ++i) {\n            if (!hold[i]) {\n                // empty arm: can pick from a source cell\n                for (int d = 0; d < 4; ++d) {\n                    int nx = rx + arm_len[i] * dx[d];\n                    int ny = ry + arm_len[i] * dy[d];\n                    if (nx >= 0 && nx < N && ny >= 0 && ny < N &&\n                        s[nx][ny] == 1 && t[nx][ny] == 0) {\n                        opts[i].emplace_back(nx * N + ny, d);\n                    }\n                }\n            } else {\n                // holding arm: can place on a target cell\n                for (int d = 0; d < 4; ++d) {\n                    int nx = rx + arm_len[i] * dx[d];\n                    int ny = ry + arm_len[i] * dy[d];\n                    if (nx >= 0 && nx < N && ny >= 0 && ny < N &&\n                        t[nx][ny] == 1 && s[nx][ny] == 0) {\n                        opts[i].emplace_back(nx * N + ny, d);\n                    }\n                }\n            }\n        }\n        \n        // Maximum bipartite matching (Kuhn)\n        vector<int> matchR(N * N, -1);\n        vector<int> matched_arm(C, -1);\n        vector<int> matched_dir(C, -1);\n        vector<bool> vis;\n        function<bool(int)> dfs = [&](int u) -> bool {\n            for (auto [cell_id, dir] : opts[u]) {\n                if (vis[cell_id]) continue;\n                vis[cell_id] = true;\n                if (matchR[cell_id] == -1 || dfs(matchR[cell_id])) {\n                    matchR[cell_id] = u;\n                    matched_arm[u] = cell_id;\n                    matched_dir[u] = dir;\n                    return true;\n                }\n            }\n            return false;\n        };\n        for (int i = 0; i < C; ++i) {\n            vis.assign(N * N, false);\n            dfs(i);\n        }\n        \n        vector<int> target_dir(C, -1);\n        bool any_match = false;\n        for (int i = 0; i < C; ++i) {\n            if (matched_arm[i] != -1) {\n                any_match = true;\n                target_dir[i] = matched_dir[i];\n            }\n        }\n        \n        if (!any_match) {\n            // Nothing can be done at this root position, proceed to next target\n            ++path_idx;\n            continue;\n        }\n        \n        // Align arms by rotating towards target directions\n        while (true) {\n            bool all_aligned = true;\n            string rot(C, '.');\n            for (int i = 0; i < C; ++i) {\n                if (target_dir[i] != -1 && cur_dir[i] != target_dir[i]) {\n                    all_aligned = false;\n                    int diff = (target_dir[i] - cur_dir[i] + 4) % 4;\n                    int step;\n                    if (diff == 1) step = 1;\n                    else if (diff == 3) step = -1;\n                    else step = 1;  // diff == 2, arbitrarily choose clockwise first\n                    rot[i] = (step == 1 ? 'R' : 'L');\n                    cur_dir[i] = (cur_dir[i] + step + 4) % 4;\n                }\n            }\n            if (all_aligned) break;\n            if (turn_cnt >= MAX_TURNS) break;\n            output_turn('.', rot, string(Vp, '.'));\n        }\n        if (turn_cnt >= MAX_TURNS) break;\n        \n        // Perform actions in one turn\n        string act(Vp, '.');\n        vector<int> pick_list, place_list;\n        for (int i = 0; i < C; ++i) {\n            if (target_dir[i] != -1) {\n                act[1 + i] = 'P';\n                if (!hold[i]) pick_list.push_back(i);\n                else          place_list.push_back(i);\n            }\n        }\n        output_turn('.', string(C, '.'), act);\n        \n        // Update grid and arm states\n        for (int i : pick_list) {\n            int nx = rx + arm_len[i] * dx[matched_dir[i]];\n            int ny = ry + arm_len[i] * dy[matched_dir[i]];\n            s[nx][ny] = 0;\n            --sources;\n            hold[i] = true;\n        }\n        for (int i : place_list) {\n            int nx = rx + arm_len[i] * dx[matched_dir[i]];\n            int ny = ry + arm_len[i] * dy[matched_dir[i]];\n            s[nx][ny] = 1;\n            --targets;\n            hold[i] = false;\n        }\n        \n        // Stay at the same root position to possibly perform more actions\n    }\n    \n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <unordered_map>\nusing namespace std;\n\nconst int S = 4000;                // cell size\nconst int W = 100000 / S;          // grid width  (25)\nconst int H = 100000 / S;          // grid height (25)\nconst int MAX_PERIMETER = 400000;\n\nstruct Edge {\n    int to, rev, cap;\n};\n\nstruct Dinic {\n    int N;\n    vector<vector<Edge>> g;\n    vector<int> level, iter;\n\n    Dinic(int n) : N(n), g(n), level(n), iter(n) {}\n\n    void add_edge(int from, int to, int cap) {\n        g[from].push_back({to, (int)g[to].size(), cap});\n        g[to].push_back({from, (int)g[from].size() - 1, 0});\n    }\n\n    void add_undirected(int u, int v, int cap) {\n        add_edge(u, v, cap);\n        add_edge(v, u, cap);\n    }\n\n    void bfs(int s) {\n        fill(level.begin(), level.end(), -1);\n        queue<int> q;\n        level[s] = 0;\n        q.push(s);\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (auto &e : g[v]) {\n                if (e.cap > 0 && level[e.to] == -1) {\n                    level[e.to] = level[v] + 1;\n                    q.push(e.to);\n                }\n            }\n        }\n    }\n\n    int dfs(int v, int t, int f) {\n        if (v == t) return f;\n        for (int &i = iter[v]; i < (int)g[v].size(); ++i) {\n            Edge &e = g[v][i];\n            if (e.cap > 0 && level[v] + 1 == level[e.to]) {\n                int d = dfs(e.to, t, min(f, e.cap));\n                if (d > 0) {\n                    e.cap -= d;\n                    g[e.to][e.rev].cap += d;\n                    return d;\n                }\n            }\n        }\n        return 0;\n    }\n\n    int max_flow(int s, int t) {\n        int flow = 0;\n        while (true) {\n            bfs(s);\n            if (level[t] == -1) break;\n            fill(iter.begin(), iter.end(), 0);\n            int f;\n            while ((f = dfs(s, t, 1e9)) > 0) {\n                flow += f;\n            }\n        }\n        return flow;\n    }\n\n    vector<bool> get_source_set(int s) {\n        vector<bool> vis(N, false);\n        queue<int> q;\n        q.push(s);\n        vis[s] = true;\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (auto &e : g[v]) {\n                if (e.cap > 0 && !vis[e.to]) {\n                    vis[e.to] = true;\n                    q.push(e.to);\n                }\n            }\n        }\n        return vis;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    cin >> N;\n    vector<int> x(2 * N), y(2 * N);\n    for (int i = 0; i < 2 * N; ++i) cin >> x[i] >> y[i];\n    \n    // weight = mackerels - sardines in each cell\n    vector<vector<int>> weight(H, vector<int>(W, 0));\n    for (int i = 0; i < N; ++i) {\n        int cx = min(x[i] / S, W - 1);\n        int cy = min(y[i] / S, H - 1);\n        weight[cy][cx]++;\n    }\n    for (int i = N; i < 2 * N; ++i) {\n        int cx = min(x[i] / S, W - 1);\n        int cy = min(y[i] / S, H - 1);\n        weight[cy][cx]--;\n    }\n    \n    // trade-off parameters (perimeter penalty)\n    vector<int> lambdas = {0, 1, 2, 5, 10, 20, 50, 100, 200, 500};\n    \n    int best_score = -1;\n    vector<vector<bool>> best_inside(H, vector<bool>(W, false));\n    \n    const int dx[4] = {1, -1, 0, 0};\n    const int dy[4] = {0, 0, 1, -1};\n    \n    for (int lambda : lambdas) {\n        Dinic dinic(W * H + 2);\n        int source = W * H, sink = source + 1;\n        \n        // unary terms\n        for (int j = 0; j < H; ++j) {\n            for (int i = 0; i < W; ++i) {\n                int id = i + j * W;\n                int w = weight[j][i];\n                if (w > 0) dinic.add_edge(source, id, w);\n                else if (w < 0) dinic.add_edge(id, sink, -w);\n            }\n        }\n        \n        // pairwise terms (grid edges)\n        for (int j = 0; j < H; ++j) {\n            for (int i = 0; i < W; ++i) {\n                int id = i + j * W;\n                if (i + 1 < W) dinic.add_undirected(id, id + 1, lambda);\n                if (j + 1 < H) dinic.add_undirected(id, id + W, lambda);\n            }\n        }\n        \n        dinic.max_flow(source, sink);\n        auto vis = dinic.get_source_set(source);\n        vector<vector<bool>> inside(H, vector<bool>(W, false));\n        for (int j = 0; j < H; ++j)\n            for (int i = 0; i < W; ++i)\n                inside[j][i] = vis[i + j * W];\n        \n        // connected components of the selected cells\n        vector<vector<int>> comp_id(H, vector<int>(W, -1));\n        int comp_cnt = 0;\n        for (int j = 0; j < H; ++j) {\n            for (int i = 0; i < W; ++i) {\n                if (inside[j][i] && comp_id[j][i] == -1) {\n                    queue<pair<int, int>> q;\n                    q.push({i, j});\n                    comp_id[j][i] = comp_cnt;\n                    while (!q.empty()) {\n                        auto [cx, cy] = q.front(); q.pop();\n                        for (int d = 0; d < 4; ++d) {\n                            int nx = cx + dx[d], ny = cy + dy[d];\n                            if (nx >= 0 && nx < W && ny >= 0 && ny < H &&\n                                inside[ny][nx] && comp_id[ny][nx] == -1) {\n                                comp_id[ny][nx] = comp_cnt;\n                                q.push({nx, ny});\n                            }\n                        }\n                    }\n                    ++comp_cnt;\n                }\n            }\n        }\n        \n        // evaluate each component (after filling holes)\n        for (int c = 0; c < comp_cnt; ++c) {\n            int min_i = W, max_i = -1, min_j = H, max_j = -1;\n            for (int j = 0; j < H; ++j) {\n                for (int i = 0; i < W; ++i) {\n                    if (comp_id[j][i] == c) {\n                        min_i = min(min_i, i); max_i = max(max_i, i);\n                        min_j = min(min_j, j); max_j = max(max_j, j);\n                    }\n                }\n            }\n            int lw = max_i - min_i + 3;\n            int lh = max_j - min_j + 3;\n            vector<vector<bool>> local(lh, vector<bool>(lw, false));\n            for (int j = min_j; j <= max_j; ++j)\n                for (int i = min_i; i <= max_i; ++i)\n                    if (comp_id[j][i] == c)\n                        local[j - min_j + 1][i - min_i + 1] = true;\n            \n            // flood fill from the borders\n            vector<vector<bool>> vis_local(lh, vector<bool>(lw, false));\n            queue<pair<int, int>> q;\n            for (int y = 0; y < lh; ++y) {\n                if (!local[y][0]) { q.push({0, y}); vis_local[y][0] = true; }\n                if (!local[y][lw - 1]) { q.push({lw - 1, y}); vis_local[y][lw - 1] = true; }\n            }\n            for (int x = 0; x < lw; ++x) {\n                if (!local[0][x]) { q.push({x, 0}); vis_local[0][x] = true; }\n                if (!local[lh - 1][x]) { q.push({x, lh - 1}); vis_local[lh - 1][x] = true; }\n            }\n            while (!q.empty()) {\n                auto [cx, cy] = q.front(); q.pop();\n                for (int d = 0; d < 4; ++d) {\n                    int nx = cx + dx[d], ny = cy + dy[d];\n                    if (nx >= 0 && nx < lw && ny >= 0 && ny < lh &&\n                        !vis_local[ny][nx] && !local[ny][nx]) {\n                        vis_local[ny][nx] = true;\n                        q.push({nx, ny});\n                    }\n                }\n            }\n            // fill holes\n            for (int y = 0; y < lh; ++y)\n                for (int x = 0; x < lw; ++x)\n                    if (!vis_local[y][x] && !local[y][x])\n                        local[y][x] = true;\n            \n            auto is_inside = [&](int i, int j) -> bool {\n                if (i < min_i || i > max_i || j < min_j || j > max_j) return false;\n                return local[j - min_j + 1][i - min_i + 1];\n            };\n            \n            int cur_w = 0;\n            int cur_perim = 0;\n            for (int j = min_j; j <= max_j; ++j) {\n                for (int i = min_i; i <= max_i; ++i) {\n                    if (is_inside(i, j)) {\n                        cur_w += weight[j][i];\n                        if (!is_inside(i + 1, j)) ++cur_perim;\n                        if (!is_inside(i - 1, j)) ++cur_perim;\n                        if (!is_inside(i, j + 1)) ++cur_perim;\n                        if (!is_inside(i, j - 1)) ++cur_perim;\n                    }\n                }\n            }\n            \n            if ((long long)cur_perim * S <= MAX_PERIMETER) {\n                int score = max(0, cur_w + 1);\n                if (score > best_score) {\n                    best_score = score;\n                    best_inside.assign(H, vector<bool>(W, false));\n                    for (int j = min_j; j <= max_j; ++j)\n                        for (int i = min_i; i <= max_i; ++i)\n                            if (is_inside(i, j))\n                                best_inside[j][i] = true;\n                }\n            }\n        }\n    }\n    \n    // fallback: tiny 1x1 square around a single mackerel\n    if (best_score <= 0) {\n        int bx = x[0], by = y[0];\n        for (int i = 0; i < N; ++i) {\n            int px = x[i], py = y[i];\n            bool ok = true;\n            for (int j = N; j < 2 * N; ++j) {\n                if (x[j] >= px && x[j] <= px + 1 && y[j] >= py && y[j] <= py + 1) {\n                    ok = false;\n                    break;\n                }\n            }\n            if (ok) { bx = px; by = py; break; }\n        }\n        if (bx == 100000) bx = 99999;\n        if (by == 100000) by = 99999;\n        cout << \"4\\n\";\n        cout << bx << \" \" << by << \"\\n\";\n        cout << bx + 1 << \" \" << by << \"\\n\";\n        cout << bx + 1 << \" \" << by + 1 << \"\\n\";\n        cout << bx << \" \" << by + 1 << \"\\n\";\n        return 0;\n    }\n    \n    // if the whole grid is selected -> output outer bounding rectangle\n    int inside_cnt = 0;\n    for (int j = 0; j < H; ++j)\n        for (int i = 0; i < W; ++i)\n            if (best_inside[j][i]) ++inside_cnt;\n    if (inside_cnt == W * H) {\n        cout << \"4\\n0 0\\n100000 0\\n100000 100000\\n0 100000\\n\";\n        return 0;\n    }\n    \n    // trace the outer boundary\n    struct Seg { int x1, y1, x2, y2; };\n    vector<Seg> segs;\n    for (int j = 0; j < H; ++j) {\n        for (int i = 0; i < W; ++i) {\n            if (!best_inside[j][i]) continue;\n            int x = i * S, y = j * S;\n            if (j == 0 || !best_inside[j - 1][i])\n                segs.push_back({x, y, x + S, y});\n            if (j == H - 1 || !best_inside[j + 1][i])\n                segs.push_back({x, y + S, x + S, y + S});\n            if (i == 0 || !best_inside[j][i - 1])\n                segs.push_back({x, y, x, y + S});\n            if (i == W - 1 || !best_inside[j][i + 1])\n                segs.push_back({x + S, y, x + S, y + S});\n        }\n    }\n    \n    unordered_map<long long, vector<int>> vmap;\n    for (int idx = 0; idx < (int)segs.size(); ++idx) {\n        long long k1 = ((long long)segs[idx].x1 << 32) | segs[idx].y1;\n        long long k2 = ((long long)segs[idx].x2 << 32) | segs[idx].y2;\n        vmap[k1].push_back(idx);\n        vmap[k2].push_back(idx);\n    }\n    \n    vector<pair<int, int>> poly;\n    int start_x = segs[0].x1, start_y = segs[0].y1;\n    poly.push_back({start_x, start_y});\n    int cur_x = segs[0].x2, cur_y = segs[0].y2;\n    poly.push_back({cur_x, cur_y});\n    int prev_seg = 0;\n    while (true) {\n        long long key = ((long long)cur_x << 32) | cur_y;\n        int next_seg = -1;\n        for (int sid : vmap[key]) {\n            if (sid != prev_seg) { next_seg = sid; break; }\n        }\n        if (next_seg == -1) break;\n        int nx, ny;\n        if (segs[next_seg].x1 == cur_x && segs[next_seg].y1 == cur_y) {\n            nx = segs[next_seg].x2;\n            ny = segs[next_seg].y2;\n        } else {\n            nx = segs[next_seg].x1;\n            ny = segs[next_seg].y1;\n        }\n        if (nx == start_x && ny == start_y) break;\n        poly.push_back({nx, ny});\n        cur_x = nx; cur_y = ny;\n        prev_seg = next_seg;\n    }\n    \n    // remove collinear vertices\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        for (size_t i = 0; i < poly.size(); ++i) {\n            size_t prv = (i == 0) ? poly.size() - 1 : i - 1;\n            size_t nxt = (i + 1) % poly.size();\n            if (poly[prv].first == poly[i].first && poly[i].first == poly[nxt].first) {\n                poly.erase(poly.begin() + i);\n                changed = true;\n                break;\n            }\n            if (poly[prv].second == poly[i].second && poly[i].second == poly[nxt].second) {\n                poly.erase(poly.begin() + i);\n                changed = true;\n                break;\n            }\n        }\n    }\n    \n    cout << poly.size() << \"\\n\";\n    for (auto [xx, yy] : poly)\n        cout << xx << \" \" << yy << \"\\n\";\n    \n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <string>\n#include <utility>\n#include <random>\n#include <chrono>\nusing namespace std;\nusing namespace std::chrono;\n\n// ------------------------------------------------------------\nstruct PlacedRect {\n    int index;          // original index (0..N-1)\n    long long x, y;     // position\n    long long w, h;     // size after rotation\n    int rot;            // 0 or 1\n    char dir;           // 'U' or 'L'\n    int base;           // -1 or original index of reference\n};\n\nstruct Decision {\n    bool placed;\n    int rot;\n    char dir;\n    int base;\n};\n\n// ------------------------------------------------------------\npair<long long, long long> get_position(const vector<PlacedRect>& rects,\n                                         int base, char dir,\n                                         long long w, long long h) {\n    long long x, y;\n    if (dir == 'U') {\n        if (base == -1) {\n            x = 0;\n        } else {\n            auto it = find_if(rects.begin(), rects.end(),\n                              [base](const PlacedRect& r){ return r.index == base; });\n            x = it->x + it->w;\n        }\n        y = 0;\n        for (const auto& pr : rects) {\n            if (x + w > pr.x && pr.x + pr.w > x) {\n                if (pr.y + pr.h > y) y = pr.y + pr.h;\n            }\n        }\n    } else { // 'L'\n        if (base == -1) {\n            y = 0;\n        } else {\n            auto it = find_if(rects.begin(), rects.end(),\n                              [base](const PlacedRect& r){ return r.index == base; });\n            y = it->y + it->h;\n        }\n        x = 0;\n        for (const auto& pr : rects) {\n            if (y + h > pr.y && pr.y + pr.h > y) {\n                if (pr.x + pr.w > x) x = pr.x + pr.w;\n            }\n        }\n    }\n    return {x, y};\n}\n\n// ------------------------------------------------------------\nlong long evaluate_full(const vector<Decision>& dec,\n                         const vector<long long>& ew,\n                         const vector<long long>& eh) {\n    int N = (int)dec.size();\n    vector<PlacedRect> rects;\n    vector<bool> placed_flag(N, false);\n    long long W = 0, H = 0, sum_skip = 0;\n    for (int i = 0; i < N; ++i) {\n        if (!dec[i].placed) {\n            sum_skip += ew[i] + eh[i];\n            continue;\n        }\n        long long w = (dec[i].rot ? eh[i] : ew[i]);\n        long long h = (dec[i].rot ? ew[i] : eh[i]);\n        int base = dec[i].base;\n        if (base != -1 && !placed_flag[base]) {\n            base = -1;\n        }\n        auto [x, y] = get_position(rects, base, dec[i].dir, w, h);\n        rects.push_back({i, x, y, w, h, dec[i].rot, dec[i].dir, base});\n        placed_flag[i] = true;\n        W = max(W, x + w);\n        H = max(H, y + h);\n    }\n    return W + H + sum_skip;\n}\n\n// ------------------------------------------------------------\nvoid fix_base_consistency(vector<Decision>& dec) {\n    int N = (int)dec.size();\n    vector<bool> placed(N, false);\n    for (int i = 0; i < N; ++i) {\n        if (dec[i].placed) {\n            if (dec[i].base != -1 && !placed[dec[i].base]) {\n                dec[i].base = -1;\n            }\n            placed[i] = true;\n        }\n    }\n}\n\n// ------------------------------------------------------------\nlong long compute_est_skip(const vector<Decision>& dec,\n                           const vector<long long>& ew,\n                           const vector<long long>& eh) {\n    long long sk = 0;\n    int N = (int)dec.size();\n    for (int i = 0; i < N; ++i)\n        if (!dec[i].placed) sk += ew[i] + eh[i];\n    return sk;\n}\n\n// ------------------------------------------------------------\nvector<PlacedRect> decisions_to_rects(const vector<Decision>& dec,\n                                       const vector<long long>& ew,\n                                       const vector<long long>& eh) {\n    int N = (int)dec.size();\n    vector<PlacedRect> rects;\n    vector<bool> placed(N, false);\n    for (int i = 0; i < N; ++i) {\n        if (dec[i].placed) {\n            long long w = (dec[i].rot ? eh[i] : ew[i]);\n            long long h = (dec[i].rot ? ew[i] : eh[i]);\n            int base = dec[i].base;\n            if (base != -1 && !placed[base]) base = -1;\n            auto [x, y] = get_position(rects, base, dec[i].dir, w, h);\n            rects.push_back({i, x, y, w, h, dec[i].rot, dec[i].dir, base});\n            placed[i] = true;\n        }\n    }\n    return rects;\n}\n\n// ------------------------------------------------------------\n// A fast hill-climbing call (no time check).\nvoid hill_climb(vector<Decision>& cur_dec, long long& cur_best,\n                const vector<long long>& ew, const vector<long long>& eh,\n                int iterations, mt19937& rng) {\n    int N = (int)ew.size();\n    auto get_valid_bases = [&](const vector<Decision>& dec, int idx) -> vector<int> {\n        vector<int> valid = {-1};\n        for (int j = 0; j < idx; ++j)\n            if (dec[j].placed) valid.push_back(j);\n        return valid;\n    };\n    uniform_int_distribution<int> idx_dist(0, N - 1);\n    uniform_int_distribution<int> rot_dist(0, 1);\n    uniform_int_distribution<int> dir_dist(0, 1);\n\n    for (int iter = 0; iter < iterations; ++iter) {\n        int i = idx_dist(rng);\n        auto old_dec = cur_dec;\n        bool improved = false;\n\n        if (cur_dec[i].placed) {\n            // flip rotation\n            {\n                auto cand = cur_dec;\n                cand[i].rot = 1 - cur_dec[i].rot;\n                long long val = evaluate_full(cand, ew, eh);\n                if (val < cur_best) { cur_best = val; cur_dec = cand; improved = true; }\n            }\n            // flip direction\n            {\n                auto cand = cur_dec;\n                cand[i].dir = (cur_dec[i].dir == 'U' ? 'L' : 'U');\n                long long val = evaluate_full(cand, ew, eh);\n                if (val < cur_best) { cur_best = val; cur_dec = cand; improved = true; }\n            }\n            // change base\n            {\n                auto bases = get_valid_bases(cur_dec, i);\n                if (!bases.empty()) {\n                    uniform_int_distribution<int> base_dist(0, (int)bases.size() - 1);\n                    int nb = bases[base_dist(rng)];\n                    auto cand = cur_dec;\n                    cand[i].base = nb;\n                    long long val = evaluate_full(cand, ew, eh);\n                    if (val < cur_best) { cur_best = val; cur_dec = cand; improved = true; }\n                }\n            }\n            // change to skip\n            {\n                auto cand = cur_dec;\n                cand[i].placed = false;\n                long long val = evaluate_full(cand, ew, eh);\n                if (val < cur_best) { cur_best = val; cur_dec = cand; improved = true; }\n            }\n        } else {\n            // currently skipped \u2013 try to place\n            auto bases = get_valid_bases(cur_dec, i);\n            if (!bases.empty()) {\n                int rot = rot_dist(rng);\n                char dir = (dir_dist(rng) == 0 ? 'U' : 'L');\n                uniform_int_distribution<int> base_dist(0, (int)bases.size() - 1);\n                int nb = bases[base_dist(rng)];\n                auto cand = cur_dec;\n                cand[i].placed = true;\n                cand[i].rot = rot;\n                cand[i].dir = dir;\n                cand[i].base = nb;\n                long long val = evaluate_full(cand, ew, eh);\n                if (val < cur_best) { cur_best = val; cur_dec = cand; improved = true; }\n            }\n        }\n        if (!improved)\n            cur_dec = old_dec;\n    }\n}\n\n// ------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    auto start_time = steady_clock::now();\n\n    int N, T, sigma;\n    cin >> N >> T >> sigma;\n    vector<int> w_obs(N), h_obs(N);\n    for (int i = 0; i < N; ++i)\n        cin >> w_obs[i] >> h_obs[i];\n\n    // ----- 1. Measurement phase -----\n    vector<double> sum_w(N), sum_h(N);\n    vector<int> cnt(N);\n    for (int i = 0; i < N; ++i) {\n        sum_w[i] = w_obs[i];\n        sum_h[i] = h_obs[i];\n        cnt[i] = 1;\n    }\n\n    int measure_count = min(2 * N, T - 1);   // leave at least one turn for final\n    int rot0_num = min(N, measure_count);\n    int rot1_num = min(N, measure_count - rot0_num);\n\n    for (int i = 0; i < rot0_num; ++i) {\n        cout << 1 << \"\\n\" << i << \" 0 U -1\\n\" << flush;\n        long long Wp, Hp;\n        cin >> Wp >> Hp;\n        sum_w[i] += Wp; sum_h[i] += Hp; cnt[i]++;\n    }\n    for (int i = 0; i < rot1_num; ++i) {\n        cout << 1 << \"\\n\" << i << \" 1 U -1\\n\" << flush;\n        long long Wp, Hp;\n        cin >> Wp >> Hp;\n        sum_w[i] += Hp;   // rotated: measured H' approximates true w\n        sum_h[i] += Wp;   // measured W' approximates true h\n        cnt[i]++;\n    }\n\n    int turns_done = rot0_num + rot1_num;\n\n    vector<long long> ew(N), eh(N);\n    for (int i = 0; i < N; ++i) {\n        ew[i] = (long long)round(sum_w[i] / cnt[i]);\n        eh[i] = (long long)round(sum_h[i] / cnt[i]);\n    }\n\n    // ----- 2. Suffix sum for beam heuristic -----\n    vector<long long> suffix_sum(N + 1, 0);\n    for (int i = N - 1; i >= 0; --i)\n        suffix_sum[i] = suffix_sum[i + 1] + ew[i] + eh[i];\n\n    // ----- 3. Beam search -----\n    const int BEAM_WIDTH = 80;\n    struct State {\n        vector<PlacedRect> rects;\n        long long W, H, sum_skip;\n    };\n    vector<State> beam;\n    beam.push_back(State{ {}, 0LL, 0LL, 0LL });\n\n    for (int i = 0; i < N; ++i) {\n        vector<State> next;\n        next.reserve(BEAM_WIDTH * 30);\n\n        for (const auto& st : beam) {\n            // skip child\n            State skip_child = st;\n            skip_child.sum_skip += ew[i] + eh[i];\n            next.push_back(move(skip_child));\n\n            // place children\n            for (int rot = 0; rot <= 1; ++rot) {\n                long long w = (rot ? eh[i] : ew[i]);\n                long long h = (rot ? ew[i] : eh[i]);\n                for (char dir : {'U', 'L'}) {\n                    vector<int> bases = {-1};\n                    int sz = (int)st.rects.size();\n                    for (int k = max(0, sz - 5); k < sz; ++k)\n                        bases.push_back(st.rects[k].index);\n                    sort(bases.begin(), bases.end());\n                    bases.erase(unique(bases.begin(), bases.end()), bases.end());\n\n                    for (int base : bases) {\n                        auto [x, y] = get_position(st.rects, base, dir, w, h);\n                        long long nW = max(st.W, x + w);\n                        long long nH = max(st.H, y + h);\n                        State child = st;\n                        child.rects.push_back({i, x, y, w, h, rot, dir, base});\n                        child.W = nW;\n                        child.H = nH;\n                        next.push_back(move(child));\n                    }\n                }\n            }\n        }\n\n        // keep top BEAM_WIDTH according to heuristic (W+H+skip + suffix)\n        vector<pair<long long, int>> costs(next.size());\n        for (int j = 0; j < (int)next.size(); ++j) {\n            const auto& ns = next[j];\n            costs[j] = { ns.W + ns.H + ns.sum_skip + suffix_sum[i + 1], j };\n        }\n        sort(costs.begin(), costs.end());\n        beam.clear();\n        for (int j = 0; j < min(BEAM_WIDTH, (int)costs.size()); ++j)\n            beam.push_back(move(next[costs[j].second]));\n    }\n\n    // choose best complete state\n    long long best_cost = beam[0].W + beam[0].H + beam[0].sum_skip;\n    const State* best_state = &beam[0];\n    for (const auto& st : beam) {\n        long long cost = st.W + st.H + st.sum_skip;\n        if (cost < best_cost) {\n            best_cost = cost;\n            best_state = &st;\n        }\n    }\n\n    vector<Decision> base_decisions(N);\n    for (int i = 0; i < N; ++i)\n        base_decisions[i].placed = false;\n    for (const auto& pr : best_state->rects)\n        base_decisions[pr.index] = {true, pr.rot, pr.dir, pr.base};\n\n    // ----- 4. Hill climbing on the beam best -----\n    mt19937 rng(1234);\n    auto cur_dec = base_decisions;\n    long long cur_best = best_cost;\n    hill_climb(cur_dec, cur_best, ew, eh, 3000, rng);\n    fix_base_consistency(cur_dec);\n\n    // ----- 5. Generate extra candidates -----\n    int rem = T - turns_done;\n    int max_extra = min(20, max(0, rem - 1));  // leave at least one turn for main\n    vector<vector<Decision>> candidates;\n    vector<long long> est_skip_cand;\n    candidates.push_back(cur_dec);\n    est_skip_cand.push_back(compute_est_skip(cur_dec, ew, eh));\n\n    if (max_extra > 0) {\n        auto get_valid_bases = [&](const vector<Decision>& dec, int idx) -> vector<int> {\n            vector<int> valid = {-1};\n            for (int j = 0; j < idx; ++j)\n                if (dec[j].placed) valid.push_back(j);\n            return valid;\n        };\n        for (int k = 0; k < max_extra; ++k) {\n            auto dec = cur_dec;  // start from the hill-climbed best\n            // perturb: with 15% probability flip each rectangle's status/settings\n            for (int i = 0; i < N; ++i) {\n                if (rng() % 100 < 15) {\n                    if (dec[i].placed) {\n                        if (rng() % 2) {\n                            dec[i].placed = false;\n                        } else {\n                            dec[i].rot = rng() % 2;\n                            dec[i].dir = (rng() % 2 ? 'U' : 'L');\n                            auto bases = get_valid_bases(dec, i);\n                            if (!bases.empty())\n                                dec[i].base = bases[rng() % bases.size()];\n                        }\n                    } else {\n                        dec[i].placed = true;\n                        dec[i].rot = rng() % 2;\n                        dec[i].dir = (rng() % 2 ? 'U' : 'L');\n                        auto bases = get_valid_bases(dec, i);\n                        if (!bases.empty())\n                            dec[i].base = bases[rng() % bases.size()];\n                        else\n                            dec[i].placed = false;\n                    }\n                }\n            }\n            long long val = evaluate_full(dec, ew, eh);\n            hill_climb(dec, val, ew, eh, 200, rng);\n            fix_base_consistency(dec);\n            candidates.push_back(dec);\n            est_skip_cand.push_back(compute_est_skip(dec, ew, eh));\n        }\n    }\n\n    // ----- 6. Remaining turns: output candidates, track best measured -----\n    int best_cand_idx = 0;\n    long long best_meas = 1e18;\n    vector<long long> meas_scores(candidates.size(), -1);\n\n    for (int t = 0; t < rem; ++t) {\n        int idx = (t < (int)candidates.size()) ? t : best_cand_idx;\n        auto& dec = candidates[idx];\n        auto rects = decisions_to_rects(dec, ew, eh);\n        int n = (int)rects.size();\n        cout << n << \"\\n\";\n        for (const auto& pr : rects)\n            cout << pr.index << \" \" << pr.rot << \" \" << pr.dir << \" \" << pr.base << \"\\n\";\n        cout << flush;\n\n        long long Wp, Hp;\n        cin >> Wp >> Hp;\n        long long est_score = Wp + Hp + est_skip_cand[idx];\n        if (t < (int)candidates.size()) {\n            meas_scores[idx] = est_score;\n            if (est_score < best_meas) {\n                best_meas = est_score;\n                best_cand_idx = idx;\n            }\n        }\n        // if t >= candidates.size(), we just repeat the current best_idx, which may have been updated.\n    }\n\n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <stack>\n#include <ctime>\n#include <cmath>\n#include <cstdint>\n#include <random>\n\nusing namespace std;\n\n// fast random number generator\nuint32_t xor_state;\nvoid init_random() {\n    random_device rd;\n    xor_state = rd();\n    if(xor_state == 0) xor_state = 123456789;\n}\nuint32_t xorshift32() {\n    uint32_t x = xor_state;\n    x ^= x << 13;\n    x ^= x >> 17;\n    x ^= x << 5;\n    return xor_state = x;\n}\ninline double random_double() {\n    return (xorshift32() >> 8) / double(1 << 24);\n}\ninline int random_int(int n) {\n    return xorshift32() % n;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    init_random();\n\n    int N, M, H;\n    cin >> N >> M >> H;\n    vector<int> A(N);\n    for(int i=0; i<N; i++) cin >> A[i];\n    vector<vector<int>> adj(N);\n    for(int i=0; i<M; i++){\n        int u, v; cin >> u >> v;\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n    // skip coordinates\n    for(int i=0; i<N; i++){\n        int x, y; cin >> x >> y;\n    }\n\n    // state\n    vector<int> parent(N, -1);\n    vector<int> depth(N, 0);\n    vector<vector<int>> children(N);\n    vector<int> subtree_sum_A = A;\n    vector<int> subtree_max_depth(N, 0);\n    vector<int> root_of(N);\n    iota(root_of.begin(), root_of.end(), 0);\n\n    // greedy initialization (process vertices in descending A)\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int i, int j){ return A[i] > A[j]; });\n\n    for(int v : order){\n        if(parent[v] != -1) continue;\n        int best_u = -1;\n        int best_udepth = -1;\n        for(int u : adj[v]){\n            if(root_of[u] == v) continue;\n            int new_d = depth[u] + 1;\n            if(new_d + subtree_max_depth[v] <= H){\n                if(depth[u] > best_udepth){\n                    best_udepth = depth[u];\n                    best_u = u;\n                }\n            }\n        }\n        if(best_u != -1){\n            int delta = depth[best_u] + 1;\n            int new_root = root_of[best_u];\n            parent[v] = best_u;\n            children[best_u].push_back(v);\n            stack<int> st;\n            st.push(v);\n            while(!st.empty()){\n                int node = st.top(); st.pop();\n                depth[node] += delta;\n                root_of[node] = new_root;\n                for(int child : children[node]){\n                    st.push(child);\n                }\n            }\n            // update ancestors\n            vector<int> to_update;\n            int cur = best_u;\n            while(cur != -1){\n                to_update.push_back(cur);\n                cur = parent[cur];\n            }\n            sort(to_update.begin(), to_update.end(), [&](int a, int b){ return depth[a] > depth[b]; });\n            for(int node : to_update){\n                int sum = A[node];\n                int max_d = 0;\n                for(int child : children[node]){\n                    sum += subtree_sum_A[child];\n                    max_d = max(max_d, subtree_max_depth[child] + 1);\n                }\n                subtree_sum_A[node] = sum;\n                subtree_max_depth[node] = max_d;\n            }\n        }\n    }\n\n    // initial score\n    long long score = 0;\n    for(int i=0; i<N; i++){\n        score += (depth[i] + 1LL) * A[i];\n    }\n    long long best_score = score;\n    vector<int> best_parent = parent;\n\n    // helper functions for SA\n    auto is_descendant = [&](int anc, int desc) -> bool {\n        if(depth[desc] < depth[anc]) return false;\n        int cur = desc;\n        while(cur != -1 && depth[cur] > depth[anc]){\n            cur = parent[cur];\n        }\n        return cur == anc;\n    };\n\n    auto apply_move = [&](int v, int new_p, int delta) {\n        int old_p = parent[v];\n        int old_d = depth[v];\n        int new_d = (new_p == -1) ? 0 : depth[new_p] + 1;\n        int depth_delta = new_d - old_d;\n        // remove from old parent\n        if(old_p != -1){\n            auto it = find(children[old_p].begin(), children[old_p].end(), v);\n            if(it != children[old_p].end()) children[old_p].erase(it);\n        }\n        // add to new parent\n        if(new_p != -1){\n            children[new_p].push_back(v);\n        }\n        parent[v] = new_p;\n        // update depths in subtree of v\n        if(depth_delta != 0){\n            stack<int> st;\n            st.push(v);\n            while(!st.empty()){\n                int node = st.top(); st.pop();\n                depth[node] += depth_delta;\n                for(int child : children[node]){\n                    st.push(child);\n                }\n            }\n        }\n        // update subtree properties for affected ancestors\n        vector<int> to_update;\n        if(old_p != -1){\n            int cur = old_p;\n            while(cur != -1){\n                to_update.push_back(cur);\n                cur = parent[cur];\n            }\n        }\n        if(new_p != -1){\n            int cur = new_p;\n            while(cur != -1){\n                to_update.push_back(cur);\n                cur = parent[cur];\n            }\n        }\n        sort(to_update.begin(), to_update.end(), [&](int a, int b){ return depth[a] > depth[b]; });\n        to_update.erase(unique(to_update.begin(), to_update.end()), to_update.end());\n        for(int node : to_update){\n            int sum = A[node];\n            int max_d = 0;\n            for(int child : children[node]){\n                sum += subtree_sum_A[child];\n                max_d = max(max_d, subtree_max_depth[child] + 1);\n            }\n            subtree_sum_A[node] = sum;\n            subtree_max_depth[node] = max_d;\n        }\n    };\n\n    // simulated annealing\n    clock_t start_clock = clock();\n    double time_limit_sec = 1.95;\n    double T_start = 20000.0;\n    double T_end = 0.1;\n    double T = T_start;\n    int iter_count = 0;\n\n    while(true){\n        if(iter_count % 1000 == 0){\n            double elapsed = double(clock() - start_clock) / CLOCKS_PER_SEC;\n            if(elapsed >= time_limit_sec) break;\n            T = T_start * pow(T_end / T_start, elapsed / time_limit_sec);\n        }\n        iter_count++;\n        bool moved = false;\n        for(int attempt = 0; attempt < 5; attempt++){\n            int v = random_int(N);\n            int old_p = parent[v];\n            int u;\n            if(old_p != -1 && random_double() < 0.1){\n                u = -1;  // make root\n            } else {\n                if(adj[v].empty()) continue;\n                u = adj[v][random_int(adj[v].size())];\n            }\n            if(u == old_p) continue;\n            int new_d;\n            if(u == -1){\n                new_d = 0;\n            } else {\n                if(is_descendant(v, u) || is_descendant(u, v)) continue;\n                new_d = depth[u] + 1;\n                if(new_d + subtree_max_depth[v] > H) continue;\n            }\n            int delta = (new_d - depth[v]) * subtree_sum_A[v];\n            if(delta >= 0 || random_double() < exp(delta / T)){\n                apply_move(v, u, delta);\n                score += delta;\n                moved = true;\n                if(score > best_score){\n                    best_score = score;\n                    best_parent = parent;\n                }\n                break;\n            }\n        }\n    }\n\n    for(int i=0; i<N; i++){\n        cout << best_parent[i] << (i==N-1 ? \"\\n\" : \" \");\n    }\n\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <cstring>\nusing namespace std;\n\nconst int N = 20;\nconst int INF = 1e9;\n\nenum Mode { ROWS_ONE_WAY, COLS_ONE_WAY, NONE };\n\nstruct Solver {\n    vector<string> C;\n    bool fuku[N][N];\n    bool row_has_fuku[N], col_has_fuku[N];\n    int L_max[N], R_min[N], U_max[N], D_min[N];\n    vector<pair<int,int>> oni;\n    int K;\n    bool allowed_row[2*N], allowed_col[2*N];\n    vector<int> forced_row, forced_col, optional;\n\n    // working state\n    vector<int> row_cols[N], col_rows[N];\n    bool assign_row[2*N];\n    int total_cost;\n\n    void init() {\n        memset(row_has_fuku, 0, sizeof row_has_fuku);\n        memset(col_has_fuku, 0, sizeof col_has_fuku);\n        oni.clear();\n        for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) fuku[i][j] = false;\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (C[i][j] == 'x') oni.push_back({i,j});\n                else if (C[i][j] == 'o') {\n                    fuku[i][j] = true;\n                    row_has_fuku[i] = true;\n                    col_has_fuku[j] = true;\n                }\n            }\n        }\n        K = oni.size();\n        for (int i = 0; i < N; ++i) {\n            L_max[i] = N-1;\n            for (int j = 0; j < N; ++j) if (fuku[i][j]) { L_max[i] = j-1; break; }\n            R_min[i] = 0;\n            for (int j = N-1; j >= 0; --j) if (fuku[i][j]) { R_min[i] = j+1; break; }\n        }\n        for (int j = 0; j < N; ++j) {\n            U_max[j] = N-1;\n            for (int i = 0; i < N; ++i) if (fuku[i][j]) { U_max[j] = i-1; break; }\n            D_min[j] = 0;\n            for (int i = N-1; i >= 0; --i) if (fuku[i][j]) { D_min[j] = i+1; break; }\n        }\n        forced_row.clear(); forced_col.clear(); optional.clear();\n        for (int k = 0; k < K; ++k) {\n            int i = oni[k].first, j = oni[k].second;\n            allowed_row[k] = (j <= L_max[i]) || (j >= R_min[i]);\n            allowed_col[k] = (i <= U_max[j]) || (i >= D_min[j]);\n            if (allowed_row[k] && allowed_col[k]) optional.push_back(k);\n            else if (allowed_row[k]) forced_row.push_back(k);\n            else forced_col.push_back(k);\n        }\n    }\n\n    void clear_state() {\n        for (int i = 0; i < N; ++i) { row_cols[i].clear(); col_rows[i].clear(); }\n    }\n\n    void add_to_row(int i, int j) {\n        auto& v = row_cols[i];\n        v.insert(lower_bound(v.begin(), v.end(), j), j);\n    }\n    void add_to_col(int j, int i) {\n        auto& v = col_rows[j];\n        v.insert(lower_bound(v.begin(), v.end(), i), i);\n    }\n    void remove_from_row(int i, int j) {\n        auto& v = row_cols[i];\n        v.erase(lower_bound(v.begin(), v.end(), j));\n    }\n    void remove_from_col(int j, int i) {\n        auto& v = col_rows[j];\n        v.erase(lower_bound(v.begin(), v.end(), i));\n    }\n\n    // symmetric cost for a row\n    int cost_row_sym(int i) const {\n        const auto& cols = row_cols[i];\n        int m = cols.size();\n        if (m == 0) return 0;\n        int L_safe = L_max[i] + 1;\n        int R_safe = N - R_min[i];\n        vector<int> suf(m+1, 0);\n        for (int idx = m-1; idx >= 0; --idx) suf[idx] = max(suf[idx+1], N - cols[idx]);\n        int best = INF;\n        for (int L = 0; L <= L_safe; ++L) {\n            int idx = lower_bound(cols.begin(), cols.end(), L) - cols.begin();\n            int R = suf[idx];\n            if (R <= R_safe) {\n                int cost = 2 * (L + R);\n                if (cost < best) best = cost;\n            }\n        }\n        return best;\n    }\n    // symmetric cost for a column\n    int cost_col_sym(int j) const {\n        const auto& rows = col_rows[j];\n        int m = rows.size();\n        if (m == 0) return 0;\n        int U_safe = U_max[j] + 1;\n        int D_safe = N - D_min[j];\n        vector<int> suf(m+1, 0);\n        for (int idx = m-1; idx >= 0; --idx) suf[idx] = max(suf[idx+1], N - rows[idx]);\n        int best = INF;\n        for (int U = 0; U <= U_safe; ++U) {\n            int idx = lower_bound(rows.begin(), rows.end(), U) - rows.begin();\n            int D = suf[idx];\n            if (D <= D_safe) {\n                int cost = 2 * (U + D);\n                if (cost < best) best = cost;\n            }\n        }\n        return best;\n    }\n\n    // one\u2011way possible & cost for a row (only if all oni are on the same side of fuku)\n    bool one_way_possible_row(int i) const {\n        const auto& cols = row_cols[i];\n        if (cols.empty()) return true;\n        if (!row_has_fuku[i]) return true;\n        bool left = false, right = false;\n        for (int j : cols) {\n            if (j <= L_max[i]) left = true;\n            else if (j >= R_min[i]) right = true;\n        }\n        return !(left && right);\n    }\n    int one_way_cost_row(int i) const {\n        const auto& cols = row_cols[i];\n        if (cols.empty()) return 0;\n        if (!row_has_fuku[i]) {\n            // just push everything left (or right) whichever is smaller\n            int d_left = cols.back() + 1;\n            int d_right = N - cols[0];\n            return min(d_left, d_right);\n        }\n        int L = 0, R = 0;\n        for (int j : cols) {\n            if (j <= L_max[i]) L = max(L, j+1);\n            else if (j >= R_min[i]) R = max(R, N - j);\n        }\n        return L + R; // one direction is 0\n    }\n\n    bool one_way_possible_col(int j) const {\n        const auto& rows = col_rows[j];\n        if (rows.empty()) return true;\n        if (!col_has_fuku[j]) return true;\n        bool up = false, down = false;\n        for (int i : rows) {\n            if (i <= U_max[j]) up = true;\n            else if (i >= D_min[j]) down = true;\n        }\n        return !(up && down);\n    }\n    int one_way_cost_col(int j) const {\n        const auto& rows = col_rows[j];\n        if (rows.empty()) return 0;\n        if (!col_has_fuku[j]) {\n            int d_up = rows.back() + 1;\n            int d_down = N - rows[0];\n            return min(d_up, d_down);\n        }\n        int U = 0, D = 0;\n        for (int i : rows) {\n            if (i <= U_max[j]) U = max(U, i+1);\n            else if (i >= D_min[j]) D = max(D, N - i);\n        }\n        return U + D;\n    }\n\n    // mode aware costs\n    int cost_row_mode(int i, Mode mode) const {\n        if (mode == ROWS_ONE_WAY && one_way_possible_row(i))\n            return one_way_cost_row(i);\n        return cost_row_sym(i);\n    }\n    int cost_col_mode(int j, Mode mode) const {\n        if (mode == COLS_ONE_WAY && one_way_possible_col(j))\n            return one_way_cost_col(j);\n        return cost_col_sym(j);\n    }\n\n    int compute_total_cost(Mode mode) const {\n        int sum = 0;\n        for (int i = 0; i < N; ++i) sum += cost_row_mode(i, mode);\n        for (int j = 0; j < N; ++j) sum += cost_col_mode(j, mode);\n        return sum;\n    }\n\n    void apply_flip(int k, Mode mode) {\n        int i = oni[k].first, j = oni[k].second;\n        int old_r = cost_row_mode(i, mode);\n        int old_c = cost_col_mode(j, mode);\n        if (assign_row[k]) {\n            remove_from_row(i, j);\n            add_to_col(j, i);\n            assign_row[k] = false;\n        } else {\n            remove_from_col(j, i);\n            add_to_row(i, j);\n            assign_row[k] = true;\n        }\n        int new_r = cost_row_mode(i, mode);\n        int new_c = cost_col_mode(j, mode);\n        total_cost += (new_r - old_r) + (new_c - old_c);\n    }\n\n    void initialize_assignment(mt19937& rng) {\n        // forced\n        for (int k : forced_row) {\n            assign_row[k] = true;\n            add_to_row(oni[k].first, oni[k].second);\n        }\n        for (int k : forced_col) {\n            assign_row[k] = false;\n            add_to_col(oni[k].second, oni[k].first);\n        }\n        // greedy for optional\n        auto row_dist = [&](int k) {\n            int i = oni[k].first, j = oni[k].second;\n            int best = INF;\n            if (j <= L_max[i]) best = min(best, j+1);\n            if (j >= R_min[i]) best = min(best, N-j);\n            return best;\n        };\n        auto col_dist = [&](int k) {\n            int i = oni[k].first, j = oni[k].second;\n            int best = INF;\n            if (i <= U_max[j]) best = min(best, i+1);\n            if (i >= D_min[j]) best = min(best, N-i);\n            return best;\n        };\n        vector<int> opt = optional;\n        shuffle(opt.begin(), opt.end(), rng);\n        for (int k : opt) {\n            int rd = row_dist(k);\n            int cd = col_dist(k);\n            if (rd < cd) {\n                assign_row[k] = true;\n                add_to_row(oni[k].first, oni[k].second);\n            } else {\n                assign_row[k] = false;\n                add_to_col(oni[k].second, oni[k].first);\n            }\n        }\n    }\n\n    void hill_climb(Mode mode) {\n        if (optional.empty()) return;\n        mt19937 rng(random_device{}());\n        auto shuf = optional;\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            shuffle(shuf.begin(), shuf.end(), rng);\n            for (int k : shuf) {\n                int old = total_cost;\n                apply_flip(k, mode);\n                if (total_cost < old) improved = true;\n                else apply_flip(k, mode); // revert\n            }\n        }\n    }\n\n    void sa_run(Mode mode, double time_limit) {\n        if (optional.empty()) return;\n        mt19937 rng(random_device{}());\n        uniform_real_distribution<double> dist01(0.0, 1.0);\n        auto start_time = chrono::steady_clock::now();\n        int best_cost_local = total_cost;\n        bool best_assign_local[2*N];\n        for (int k = 0; k < K; ++k) best_assign_local[k] = assign_row[k];\n\n        while (true) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed >= time_limit) break;\n            double T = 5.0 * exp(-elapsed / time_limit * 10.0);\n            for (int b = 0; b < 100; ++b) {\n                int k = optional[rng() % optional.size()];\n                int old = total_cost;\n                apply_flip(k, mode);\n                int delta = total_cost - old;\n                if (delta <= 0 || dist01(rng) < exp(-delta / T)) {\n                    if (total_cost < best_cost_local) {\n                        best_cost_local = total_cost;\n                        for (int kk = 0; kk < K; ++kk) best_assign_local[kk] = assign_row[kk];\n                    }\n                } else {\n                    apply_flip(k, mode); // revert\n                }\n            }\n        }\n        // restore best found in this SA\n        clear_state();\n        for (int k = 0; k < K; ++k) {\n            assign_row[k] = best_assign_local[k];\n            if (assign_row[k]) add_to_row(oni[k].first, oni[k].second);\n            else add_to_col(oni[k].second, oni[k].first);\n        }\n        total_cost = best_cost_local;\n    }\n\n    // output the solution for a given partition and mode\n    void output_solution(Mode mode) {\n        // symmetric moves for lines not using one-way\n        auto row_sym = [&](int i) {\n            const auto& cols = row_cols[i];\n            if (cols.empty()) return;\n            int L_safe = L_max[i] + 1;\n            int R_safe = N - R_min[i];\n            int m = cols.size();\n            vector<int> suf(m+1,0);\n            for (int idx = m-1; idx >= 0; --idx) suf[idx] = max(suf[idx+1], N - cols[idx]);\n            int best_c = INF, best_L = 0, best_R = 0;\n            for (int L = 0; L <= L_safe; ++L) {\n                int idx = lower_bound(cols.begin(), cols.end(), L) - cols.begin();\n                int R = suf[idx];\n                if (R <= R_safe) {\n                    int cost = 2*(L+R);\n                    if (cost < best_c) { best_c = cost; best_L = L; best_R = R; }\n                }\n            }\n            for (int t = 0; t < best_L; ++t) cout << \"L \" << i << \"\\n\";\n            for (int t = 0; t < best_L; ++t) cout << \"R \" << i << \"\\n\";\n            for (int t = 0; t < best_R; ++t) cout << \"R \" << i << \"\\n\";\n            for (int t = 0; t < best_R; ++t) cout << \"L \" << i << \"\\n\";\n        };\n        auto col_sym = [&](int j) {\n            const auto& rows = col_rows[j];\n            if (rows.empty()) return;\n            int U_safe = U_max[j] + 1;\n            int D_safe = N - D_min[j];\n            int m = rows.size();\n            vector<int> suf(m+1,0);\n            for (int idx = m-1; idx >= 0; --idx) suf[idx] = max(suf[idx+1], N - rows[idx]);\n            int best_c = INF, best_U = 0, best_D = 0;\n            for (int U = 0; U <= U_safe; ++U) {\n                int idx = lower_bound(rows.begin(), rows.end(), U) - rows.begin();\n                int D = suf[idx];\n                if (D <= D_safe) {\n                    int cost = 2*(U+D);\n                    if (cost < best_c) { best_c = cost; best_U = U; best_D = D; }\n                }\n            }\n            for (int t = 0; t < best_U; ++t) cout << \"U \" << j << \"\\n\";\n            for (int t = 0; t < best_U; ++t) cout << \"D \" << j << \"\\n\";\n            for (int t = 0; t < best_D; ++t) cout << \"D \" << j << \"\\n\";\n            for (int t = 0; t < best_D; ++t) cout << \"U \" << j << \"\\n\";\n        };\n\n        // symmetric phase\n        if (mode != ROWS_ONE_WAY) {\n            for (int i = 0; i < N; ++i) row_sym(i);\n        } else {\n            // rows that cannot use one-way must be symmetric\n            for (int i = 0; i < N; ++i) if (!one_way_possible_row(i)) row_sym(i);\n        }\n        if (mode != COLS_ONE_WAY) {\n            for (int j = 0; j < N; ++j) col_sym(j);\n        } else {\n            for (int j = 0; j < N; ++j) if (!one_way_possible_col(j)) col_sym(j);\n        }\n\n        // one-way phase at the end\n        if (mode == ROWS_ONE_WAY) {\n            for (int i = 0; i < N; ++i) {\n                if (!one_way_possible_row(i) || row_cols[i].empty()) continue;\n                int cost = one_way_cost_row(i);\n                if (cost == 0) continue;\n                if (!row_has_fuku[i]) {\n                    int d_left = row_cols[i].back() + 1;\n                    int d_right = N - row_cols[i][0];\n                    if (d_left <= d_right) for (int t=0; t<d_left; ++t) cout << \"L \" << i << \"\\n\";\n                    else for (int t=0; t<d_right; ++t) cout << \"R \" << i << \"\\n\";\n                } else {\n                    int L = 0, R = 0;\n                    for (int j : row_cols[i]) {\n                        if (j <= L_max[i]) L = max(L, j+1);\n                        else if (j >= R_min[i]) R = max(R, N - j);\n                    }\n                    // only one of L,R >0\n                    if (L) for (int t=0; t<L; ++t) cout << \"L \" << i << \"\\n\";\n                    else for (int t=0; t<R; ++t) cout << \"R \" << i << \"\\n\";\n                }\n            }\n        }\n        if (mode == COLS_ONE_WAY) {\n            for (int j = 0; j < N; ++j) {\n                if (!one_way_possible_col(j) || col_rows[j].empty()) continue;\n                int cost = one_way_cost_col(j);\n                if (cost == 0) continue;\n                if (!col_has_fuku[j]) {\n                    int d_up = col_rows[j].back() + 1;\n                    int d_down = N - col_rows[j][0];\n                    if (d_up <= d_down) for (int t=0; t<d_up; ++t) cout << \"U \" << j << \"\\n\";\n                    else for (int t=0; t<d_down; ++t) cout << \"D \" << j << \"\\n\";\n                } else {\n                    int U = 0, D = 0;\n                    for (int i : col_rows[j]) {\n                        if (i <= U_max[j]) U = max(U, i+1);\n                        else if (i >= D_min[j]) D = max(D, N - i);\n                    }\n                    if (U) for (int t=0; t<U; ++t) cout << \"U \" << j << \"\\n\";\n                    else for (int t=0; t<D; ++t) cout << \"D \" << j << \"\\n\";\n                }\n            }\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    int n;\n    cin >> n;\n    solver.C.resize(n);\n    for (int i = 0; i < n; ++i) cin >> solver.C[i];\n    solver.init();\n\n    int best_cost_overall = INF;\n    bool best_assign_overall[2*N];\n    Mode best_mode = NONE;\n    auto copy_assign = [&](bool* src) {\n        for (int k = 0; k < solver.K; ++k) best_assign_overall[k] = src[k];\n    };\n\n    auto start_total = chrono::steady_clock::now();\n    mt19937 rng_init(random_device{}());\n\n    // try all three modes with multiple restarts within time\n    const Mode modes[3] = {ROWS_ONE_WAY, COLS_ONE_WAY, NONE};\n    double total_time_budget = 1.9;\n    double time_per_mode = total_time_budget / 3.0;\n    auto run_mode = [&](Mode mode, double time_limit) {\n        auto mode_start = chrono::steady_clock::now();\n        int best_local = INF;\n        bool best_assign_local[2*N];\n        while (true) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - mode_start).count();\n            if (elapsed >= time_limit) break;\n            double sa_time = min(0.25, time_limit - elapsed);\n            solver.clear_state();\n            solver.initialize_assignment(rng_init);\n            solver.total_cost = solver.compute_total_cost(mode);\n            solver.hill_climb(mode);\n            solver.sa_run(mode, sa_time);\n            if (solver.total_cost < best_local) {\n                best_local = solver.total_cost;\n                for (int k = 0; k < solver.K; ++k) best_assign_local[k] = solver.assign_row[k];\n            }\n        }\n        // restore best for this mode\n        solver.clear_state();\n        for (int k = 0; k < solver.K; ++k) {\n            solver.assign_row[k] = best_assign_local[k];\n            if (solver.assign_row[k]) solver.add_to_row(solver.oni[k].first, solver.oni[k].second);\n            else solver.add_to_col(solver.oni[k].second, solver.oni[k].first);\n        }\n        solver.total_cost = best_local;\n        return best_local;\n    };\n\n    for (int mi = 0; mi < 3; ++mi) {\n        Mode mode = modes[mi];\n        int cost = run_mode(mode, time_per_mode);\n        if (cost < best_cost_overall) {\n            best_cost_overall = cost;\n            best_mode = mode;\n            copy_assign(solver.assign_row);\n        }\n    }\n\n    // restore overall best\n    solver.clear_state();\n    for (int k = 0; k < solver.K; ++k) {\n        solver.assign_row[k] = best_assign_overall[k];\n        if (solver.assign_row[k]) solver.add_to_row(solver.oni[k].first, solver.oni[k].second);\n        else solver.add_to_col(solver.oni[k].second, solver.oni[k].first);\n    }\n    solver.total_cost = best_cost_overall;\n\n    solver.output_solution(best_mode);\n    return 0;\n}","ahc044":"#include <iostream>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n#include <cstring>\n#include <random>\n#include <vector>\nusing namespace std;\n\nconst int N = 100;\nconst int L = 500000;\nint T[N];\n\n// fast simulation: we need this many times, keep it simple\nint real_error(const int a[N], const int b[N]) {\n    int t[N] = {0};\n    int cur = 0;\n    t[0] = 1;\n    for (int step = 1; step < L; ++step) {\n        cur = (t[cur] & 1) ? a[cur] : b[cur];\n        t[cur]++;\n    }\n    int err = 0;\n    for (int i = 0; i < N; ++i) {\n        int diff = t[i] - T[i];\n        if (diff < 0) diff = -diff;\n        err += diff;\n    }\n    return err;\n}\n\n// surrogate: stationary distribution of the random walk (a_i and b_i with equal probability)\ndouble surrogate_error(const int a[N], const int b[N]) {\n    double pi[N], new_pi[N];\n    for (int i = 0; i < N; ++i) pi[i] = 1.0 / N;\n    const int max_iter = 100;\n    for (int iter = 0; iter < max_iter; ++iter) {\n        for (int i = 0; i < N; ++i) new_pi[i] = 0.0;\n        for (int i = 0; i < N; ++i) {\n            if (a[i] == b[i]) {\n                new_pi[a[i]] += pi[i];\n            } else {\n                new_pi[a[i]] += pi[i] * 0.5;\n                new_pi[b[i]] += pi[i] * 0.5;\n            }\n        }\n        for (int i = 0; i < N; ++i) pi[i] = new_pi[i];\n    }\n    double err = 0.0;\n    for (int i = 0; i < N; ++i) err += fabs(pi[i] * L - T[i]);\n    return err;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    int N_in, L_in;\n    cin >> N_in >> L_in;\n    for (int i = 0; i < N; ++i) cin >> T[i];\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto rand_int = [&](int max) { return uniform_int_distribution<int>(0, max-1)(rng); };\n    auto rand_double = [&]() { return uniform_real_distribution<double>(0.0, 1.0)(rng); };\n\n    // ---------- greedy initial solution (approximate balance) ----------\n    vector<int> caps(N, 0);\n    for (int i = 0; i < N; ++i) caps[i] = 2 * T[i];\n    vector<pair<int,int>> items; // (weight, node_i)\n    for (int i = 0; i < N; ++i) {\n        items.emplace_back(T[i], i);\n        items.emplace_back(T[i], i);\n    }\n    sort(items.begin(), items.end(), greater<pair<int,int>>());\n\n    int init_a[N], init_b[N];\n    for (int i = 0; i < N; ++i) init_a[i] = init_b[i] = -1;\n\n    for (auto &p : items) {\n        int w = p.first;\n        int i = p.second;\n        int best_j = 0;\n        int best_cap = -1;\n        for (int j = 0; j < N; ++j) {\n            if (caps[j] > best_cap) {\n                best_cap = caps[j];\n                best_j = j;\n            }\n        }\n        if (init_a[i] == -1) init_a[i] = best_j;\n        else init_b[i] = best_j;\n        caps[best_j] -= w;\n    }\n    for (int i = 0; i < N; ++i) {\n        if (init_a[i] == -1) init_a[i] = i;\n        if (init_b[i] == -1) init_b[i] = i;\n    }\n\n    int best_a[N], best_b[N];\n    memcpy(best_a, init_a, sizeof(best_a));\n    memcpy(best_b, init_b, sizeof(best_b));\n    int best_err = real_error(best_a, best_b);\n\n    // fallback: if greedy yields huge error, start from a simple cycle\n    if (best_err > 1000000) {\n        for (int i = 0; i < N; ++i) {\n            best_a[i] = (i + 1) % N;\n            best_b[i] = (i + 1) % N;\n        }\n        best_err = real_error(best_a, best_b);\n    }\n\n    int cur_a[N], cur_b[N];\n    memcpy(cur_a, best_a, sizeof(cur_a));\n    memcpy(cur_b, best_b, sizeof(cur_b));\n    int cur_real_err = best_err;\n    double cur_surr_err = surrogate_error(cur_a, cur_b);\n    double best_surr_err = cur_surr_err;\n\n    auto start = chrono::steady_clock::now();\n    double elapsed = 0.0;\n    const double time_limit_surr = 1.3;\n    const double time_limit_total = 1.95;\n\n    // ---------- Stage 1: Surrogate SA ----------\n    double temp_surr = 200.0;\n    double temp_surr_end = 0.1;\n    int iter = 0;\n    while (true) {\n        if (iter % 100 == 0) {\n            auto now = chrono::steady_clock::now();\n            elapsed = chrono::duration<double>(now - start).count();\n            if (elapsed > time_limit_surr) break;\n            double progress = elapsed / time_limit_surr;\n            temp_surr = 200.0 * pow(temp_surr_end / 200.0, progress);\n        }\n        int type = rand_int(10);\n        int i = rand_int(N);\n        int old_a = cur_a[i], old_b = cur_b[i];\n        if (type < 4) {\n            cur_a[i] = rand_int(N);\n        } else if (type < 8) {\n            cur_b[i] = rand_int(N);\n        } else if (type == 8) {\n            swap(cur_a[i], cur_b[i]);\n        } else {\n            cur_a[i] = rand_int(N);\n            cur_b[i] = rand_int(N);\n        }\n        double new_surr_err = surrogate_error(cur_a, cur_b);\n        double delta = new_surr_err - cur_surr_err;\n        bool accepted = false;\n        if (delta <= 0) {\n            accepted = true;\n        } else if (rand_double() < exp(-delta / temp_surr)) {\n            accepted = true;\n        }\n        if (accepted) {\n            cur_surr_err = new_surr_err;\n            if (cur_surr_err < best_surr_err) {\n                best_surr_err = cur_surr_err;\n                int real_err = real_error(cur_a, cur_b);\n                if (real_err < best_err) {\n                    best_err = real_err;\n                    memcpy(best_a, cur_a, sizeof(cur_a));\n                    memcpy(best_b, cur_b, sizeof(cur_b));\n                }\n            }\n        } else {\n            cur_a[i] = old_a;\n            cur_b[i] = old_b;\n        }\n        ++iter;\n    }\n\n    // restore best found\n    memcpy(cur_a, best_a, sizeof(cur_a));\n    memcpy(cur_b, best_b, sizeof(cur_b));\n    cur_real_err = best_err;\n\n    // ---------- Stage 2: Real SA ----------\n    double temp_real = max(cur_real_err * 0.25, 10.0);\n    double temp_real_end = 0.1;\n    iter = 0;\n    while (true) {\n        if (iter % 10 == 0) {\n            auto now = chrono::steady_clock::now();\n            elapsed = chrono::duration<double>(now - start).count();\n            if (elapsed > time_limit_total) break;\n            double progress = max(0.0, min(1.0, (elapsed - time_limit_surr) / (time_limit_total - time_limit_surr)));\n            temp_real = max(cur_real_err * 0.25, 10.0) * pow(temp_real_end / max(cur_real_err * 0.25, 10.0), progress);\n        }\n        int type = rand_int(10);\n        int i = rand_int(N);\n        int old_a = cur_a[i], old_b = cur_b[i];\n        if (type < 4) {\n            cur_a[i] = rand_int(N);\n        } else if (type < 8) {\n            cur_b[i] = rand_int(N);\n        } else if (type == 8) {\n            swap(cur_a[i], cur_b[i]);\n        } else {\n            cur_a[i] = rand_int(N);\n            cur_b[i] = rand_int(N);\n        }\n        int new_err = real_error(cur_a, cur_b);\n        int delta = new_err - cur_real_err;\n        bool accepted = false;\n        if (delta <= 0) {\n            accepted = true;\n        } else if (rand_double() < exp(-delta / temp_real)) {\n            accepted = true;\n        }\n        if (accepted) {\n            cur_real_err = new_err;\n            if (new_err < best_err) {\n                best_err = new_err;\n                memcpy(best_a, cur_a, sizeof(cur_a));\n                memcpy(best_b, cur_b, sizeof(cur_b));\n            }\n        } else {\n            cur_a[i] = old_a;\n            cur_b[i] = old_b;\n        }\n        ++iter;\n        if (best_err == 0) break;\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << best_a[i] << \" \" << best_b[i] << \"\\n\";\n    }\n\n    return 0;\n}","ahc045":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n#include <cstdint>\n#include <limits>\n#include <chrono>\n#include <random>\n\nusing namespace std;\nusing namespace chrono;\n\n// ---------- DSU ----------\nstruct DSU {\n    vector<int> parent;\n    DSU(int n) { parent.assign(n, -1); }\n    int find(int x) { return parent[x] < 0 ? x : parent[x] = find(parent[x]); }\n    bool unite(int x, int y) {\n        x = find(x); y = find(y);\n        if (x == y) return false;\n        if (parent[x] > parent[y]) swap(x, y);\n        parent[x] += parent[y];\n        parent[y] = x;\n        return true;\n    }\n};\n\n// ---------- global state ----------\nint N, M, Q, L, W;\nint q_used = 0;\nvector<int> cx, cy;\nvector<vector<double>> gdist;   // global estimated Euclidean distances\n\n// ---------- query function ----------\nvector<pair<int, int>> query_subset(const vector<int>& C) {\n    if (q_used >= Q) return {};\n    ++q_used;\n    int l = (int)C.size();\n    cout << \"? \" << l;\n    for (int c : C) cout << \" \" << c;\n    cout << endl;\n    vector<pair<int, int>> res(l - 1);\n    for (int i = 0; i < l - 1; ++i) {\n        cin >> res[i].first >> res[i].second;\n    }\n    return res;\n}\n\n// ---------- local TSP (within one group) ----------\nvoid two_opt_local(vector<int>& order) {\n    int n = (int)order.size();\n    if (n <= 3) return;\n    auto d = [&](int a, int b) { return gdist[a][b]; };\n    int max_iter = 2000;\n    bool improved = true;\n    while (improved && max_iter-- > 0) {\n        improved = false;\n        for (int i = 0; i < n - 1; ++i) {\n            for (int j = i + 2; j < n - 1; ++j) {\n                int a = order[i], b = order[i + 1], c = order[j], d_ = order[j + 1];\n                double old_cost = d(a, b) + d(c, d_);\n                double new_cost = d(a, c) + d(b, d_);\n                if (new_cost + 1e-9 < old_cost) {\n                    reverse(order.begin() + i + 1, order.begin() + j + 1);\n                    improved = true;\n                }\n            }\n        }\n    }\n}\n\n// returns an ordering of the given city ids (TSP path)\nvector<int> group_tsp(const vector<int>& cities) {\n    int k = (int)cities.size();\n    if (k <= 2) return cities;\n    // start from city closest to the group's centroid\n    double sx = 0.0, sy = 0.0;\n    for (int c : cities) { sx += cx[c]; sy += cy[c]; }\n    sx /= k; sy /= k;\n    int start = 0;\n    double bestd = 1e18;\n    for (int i = 0; i < k; ++i) {\n        double dx = cx[cities[i]] - sx;\n        double dy = cy[cities[i]] - sy;\n        double d = dx * dx + dy * dy;\n        if (d < bestd) { bestd = d; start = i; }\n    }\n    // nearest neighbour\n    vector<int> idx_path(k);\n    idx_path[0] = start;\n    vector<bool> used(k, false);\n    used[start] = true;\n    for (int i = 1; i < k; ++i) {\n        int last = idx_path[i - 1];\n        int best = -1;\n        double best_d = 1e18;\n        for (int j = 0; j < k; ++j) {\n            if (used[j]) continue;\n            double d = gdist[cities[last]][cities[j]];\n            if (d < best_d) { best_d = d; best = j; }\n        }\n        idx_path[i] = best;\n        used[best] = true;\n    }\n    // convert to city ids\n    vector<int> order(k);\n    for (int i = 0; i < k; ++i) order[i] = cities[idx_path[i]];\n    two_opt_local(order);\n    return order;\n}\n\n// ---------- estimated MST cost ----------\ndouble mst_cost(const vector<int>& cities) {\n    int k = (int)cities.size();\n    if (k <= 1) return 0.0;\n    vector<double> minD(k, 1e18);\n    vector<bool> in(k, false);\n    minD[0] = 0.0;\n    double total = 0.0;\n    for (int i = 0; i < k; ++i) {\n        int u = -1;\n        double best = 1e18;\n        for (int j = 0; j < k; ++j) {\n            if (!in[j] && minD[j] < best) { best = minD[j]; u = j; }\n        }\n        if (u < 0) break;\n        in[u] = true;\n        total += minD[u];\n        for (int v = 0; v < k; ++v) {\n            if (!in[v]) {\n                double d = gdist[cities[u]][cities[v]];\n                if (d < minD[v]) minD[v] = d;\n            }\n        }\n    }\n    return total;\n}\n\n// ---------- build a tree for a group using allowed queries ----------\nvector<pair<int, int>> build_group_tree(const vector<int>& order, int allowed, DSU& dsu) {\n    int sz = (int)order.size();\n    vector<pair<int, int>> edges;\n    if (sz <= 1) return edges;\n\n    int pos = 0;\n    if (allowed > 0 && q_used < Q) {\n        int take = min(L, sz - pos);\n        vector<int> subset(order.begin(), order.begin() + take);\n        auto res = query_subset(subset);\n        for (auto& e : res) if (dsu.unite(e.first, e.second)) edges.push_back(e);\n        pos += take;\n        --allowed;\n    }\n    while (pos < sz && allowed > 0 && q_used < Q) {\n        int anchor = order[pos - 1];\n        int take = min(L - 1, sz - pos);\n        vector<int> subset = {anchor};\n        subset.insert(subset.end(), order.begin() + pos, order.begin() + pos + take);\n        auto res = query_subset(subset);\n        for (auto& e : res) if (dsu.unite(e.first, e.second)) edges.push_back(e);\n        pos += take;\n        --allowed;\n    }\n    // chain remaining (DSU guarantees no cycles)\n    for (int i = 1; i < sz; ++i) {\n        if (dsu.unite(order[i - 1], order[i])) {\n            edges.emplace_back(order[i - 1], order[i]);\n        }\n    }\n    return edges;\n}\n\n// ---------- main ----------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    cin >> N >> M >> Q >> L >> W;\n    vector<int> G(M);\n    for (int i = 0; i < M; ++i) cin >> G[i];\n\n    vector<int> lx(N), rx(N), ly(N), ry(N);\n    cx.resize(N);\n    cy.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n        cx[i] = (lx[i] + rx[i]) / 2;\n        cy[i] = (ly[i] + ry[i]) / 2;\n    }\n\n    // build global distance matrix (estimated Euclidean distances)\n    gdist.assign(N, vector<double>(N, 0.0));\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            double dx = cx[i] - cx[j];\n            double dy = cy[i] - cy[j];\n            double d = sqrt(dx * dx + dy * dy);\n            gdist[i][j] = gdist[j][i] = d;\n        }\n    }\n\n    auto start_time = steady_clock::now();\n    auto elapsed = [&]() { return duration<double>(steady_clock::now() - start_time).count(); };\n\n    // ---- global TSP order (multi\u2011start NN + 2\u2011opt) ----\n    vector<int> global_best;\n    double global_best_len = 1e18;\n    mt19937 rng(12345);\n    uniform_int_distribution<int> rnd_city(0, N - 1);\n\n    // centroid start for first trial\n    int start_city = 0;\n    {\n        double sx = 0, sy = 0;\n        for (int i = 0; i < N; ++i) { sx += cx[i]; sy += cy[i]; }\n        sx /= N; sy /= N;\n        double bd = 1e18;\n        for (int i = 0; i < N; ++i) {\n            double dx = cx[i] - sx, dy = cy[i] - sy;\n            double d = dx * dx + dy * dy;\n            if (d < bd) { bd = d; start_city = i; }\n        }\n    }\n\n    for (int rep = 0; rep < 6; ++rep) {\n        int start = (rep == 0) ? start_city : rnd_city(rng);\n        vector<int> path(N);\n        path[0] = start;\n        vector<bool> used(N, false);\n        used[start] = true;\n        for (int i = 1; i < N; ++i) {\n            int last = path[i - 1];\n            int best = -1;\n            double best_d = 1e18;\n            for (int j = 0; j < N; ++j) {\n                if (used[j]) continue;\n                double d = gdist[last][j];\n                if (d < best_d) { best_d = d; best = j; }\n            }\n            path[i] = best;\n            used[best] = true;\n        }\n        double len = 0.0;\n        for (int i = 1; i < N; ++i) len += gdist[path[i - 1]][path[i]];\n        if (len < global_best_len) {\n            global_best_len = len;\n            global_best = move(path);\n        }\n    }\n\n    // 2\u2011opt on the best global path (time\u2011limited)\n    {\n        auto d = [&](int a, int b) { return gdist[a][b]; };\n        int n = N;\n        bool improved = true;\n        while (improved && elapsed() < 1.0) {   // stop after 1 sec\n            improved = false;\n            for (int i = 0; i < n - 1; ++i) {\n                for (int j = i + 2; j < n - 1; ++j) {\n                    if (elapsed() >= 1.0) goto end_opt;\n                    int a = global_best[i], b = global_best[i + 1];\n                    int c = global_best[j], d_ = global_best[j + 1];\n                    double old_cost = d(a, b) + d(c, d_);\n                    double new_cost = d(a, c) + d(b, d_);\n                    if (new_cost + 1e-9 < old_cost) {\n                        reverse(global_best.begin() + i + 1, global_best.begin() + j + 1);\n                        improved = true;\n                    }\n                }\n            }\n        }\n        end_opt:;\n    }\n\n    // ---- partition into groups (contiguous blocks) ----\n    vector<vector<int>> groups(M);\n    int cur = 0;\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < G[i]; ++j) {\n            groups[i].push_back(global_best[cur++]);\n        }\n    }\n\n    // ---- per\u2011group TSP, benefit estimation, query allocation ----\n    struct GroupInfo {\n        int idx, size, need_queries;\n        double benefit_per_q;\n        vector<int> tsp_order;   // city ids\n    };\n    vector<GroupInfo> infos(M);\n    for (int i = 0; i < M; ++i) {\n        infos[i].idx = i;\n        infos[i].size = (int)groups[i].size();\n        if (infos[i].size <= 1) {\n            infos[i].tsp_order = groups[i];\n            infos[i].need_queries = 0;\n            infos[i].benefit_per_q = -1.0;\n        } else {\n            const auto& cities = groups[i];\n            vector<int> tsp = group_tsp(cities);\n            infos[i].tsp_order = tsp;\n\n            double chain = 0.0;\n            for (int j = 1; j < (int)tsp.size(); ++j)\n                chain += gdist[tsp[j - 1]][tsp[j]];\n            double mst = mst_cost(cities);\n            double benefit = max(0.0, chain - mst);\n\n            int sz = infos[i].size;\n            if (sz <= 2) infos[i].need_queries = 0;\n            else if (sz <= L) infos[i].need_queries = 1;\n            else infos[i].need_queries = 1 + (sz - 2) / (L - 1);\n\n            infos[i].benefit_per_q = (infos[i].need_queries > 0) ? benefit / infos[i].need_queries : -1.0;\n        }\n    }\n\n    int total_need = 0;\n    for (auto& info : infos) total_need += info.need_queries;\n\n    vector<int> alloc(M, 0);\n    if (total_need > Q) {\n        vector<pair<double, int>> ord;\n        for (int i = 0; i < M; ++i)\n            if (infos[i].need_queries > 0)\n                ord.emplace_back(infos[i].benefit_per_q, i);\n        sort(ord.begin(), ord.end(),\n             [](const auto& a, const auto& b) { return a.first > b.first; });\n        int remaining = Q;\n        for (auto& p : ord) {\n            int i = p.second;\n            int give = min(infos[i].need_queries, remaining);\n            alloc[i] = give;\n            remaining -= give;\n            if (remaining == 0) break;\n        }\n    } else {\n        for (int i = 0; i < M; ++i) alloc[i] = infos[i].need_queries;\n    }\n\n    // ---- query execution order (highest benefit first) ----\n    vector<int> query_order;\n    {\n        vector<pair<double, int>> tmp;\n        for (int i = 0; i < M; ++i)\n            if (alloc[i] > 0)\n                tmp.emplace_back(infos[i].benefit_per_q, i);\n        sort(tmp.begin(), tmp.end(),\n             [](const auto& a, const auto& b) { return a.first > b.first; });\n        for (auto& p : tmp) query_order.push_back(p.second);\n        for (int i = 0; i < M; ++i)\n            if (alloc[i] == 0) query_order.push_back(i);\n    }\n\n    // ---- build trees for all groups ----\n    vector<vector<pair<int, int>>> out_edges(M);\n    for (int idx : query_order) {\n        if (q_used >= Q) break;\n        const auto& cities = groups[idx];\n        if (cities.size() <= 1) continue;\n        DSU dsu(N);   // fresh DSU for this group\n        int allowed = alloc[idx];\n        if (allowed > 0) {\n            out_edges[idx] = build_group_tree(infos[idx].tsp_order, allowed, dsu);\n        } else {\n            // no queries \u2013 just chain\n            const auto& order = infos[idx].tsp_order;\n            for (int j = 1; j < (int)order.size(); ++j) {\n                if (dsu.unite(order[j - 1], order[j]))\n                    out_edges[idx].emplace_back(order[j - 1], order[j]);\n            }\n        }\n    }\n\n    // fallback for any group that still misses a tree (should not happen)\n    for (int i = 0; i < M; ++i) {\n        if (groups[i].size() <= 1) continue;\n        if (!out_edges[i].empty()) continue;\n        const auto& order = infos[i].tsp_order;\n        DSU dsu(N);\n        for (int j = 1; j < (int)order.size(); ++j) {\n            if (dsu.unite(order[j - 1], order[j]))\n                out_edges[i].emplace_back(order[j - 1], order[j]);\n        }\n    }\n\n    // ---- output answer ----\n    cout << \"!\" << endl;\n    for (int i = 0; i < M; ++i) {\n        const auto& cities = groups[i];\n        for (int j = 0; j < (int)cities.size(); ++j) {\n            if (j) cout << \" \";\n            cout << cities[j];\n        }\n        cout << endl;\n        for (const auto& e : out_edges[i]) {\n            cout << e.first << \" \" << e.second << endl;\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <string>\n\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int N, M;\n    cin >> N >> M;\n    vector<int> R(M), C(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> R[i] >> C[i];\n    }\n\n    int total = N * N;\n    int S = total;          // represents \"no block\"\n    int state_size = total + 1;\n    int MAX_STATE = total * state_size;\n\n    // precompute row and column for each cell\n    vector<int> pr(total), pc(total);\n    for (int i = 0; i < total; ++i) {\n        pr[i] = i / N;\n        pc[i] = i % N;\n    }\n\n    vector<int> vis(MAX_STATE, 0);\n    vector<int> ps(MAX_STATE);\n    vector<int> pa(MAX_STATE);\n    vector<int> q(MAX_STATE);\n    int tok = 0;\n\n    vector<int> total_actions;\n\n    // process each segment: start -> target1, target1 -> target2, ...\n    for (int seg = 0; seg < M - 1; ++seg) {\n        int start_pos = R[seg] * N + C[seg];\n        int target_pos = R[seg+1] * N + C[seg+1];\n\n        ++tok;\n        int head = 0, tail = 0;\n        int start_state = start_pos * state_size + S;\n        vis[start_state] = tok;\n        ps[start_state] = -1;\n        q[tail++] = start_state;\n        int goal_state = -1;\n\n        while (head < tail) {\n            int s = q[head++];\n            int pos = s / state_size;\n            int block = s % state_size;\n            if (pos == target_pos && block == S) {\n                goal_state = s;\n                break;\n            }\n            int r = pr[pos], c = pc[pos];\n\n            for (int d = 0; d < 4; ++d) {\n                // --- Move ---\n                int nr = r, nc = c;\n                if (d == 0) nr--;\n                else if (d == 1) nr++;\n                else if (d == 2) nc--;\n                else nc++;\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                    int npos = nr * N + nc;\n                    if (npos != block) {\n                        int nstate = npos * state_size + block;\n                        if (vis[nstate] != tok) {\n                            vis[nstate] = tok;\n                            ps[nstate] = s;\n                            pa[nstate] = 0 * 4 + d;  // Move\n                            q[tail++] = nstate;\n                        }\n                    }\n                }\n\n                // --- Slide ---\n                int slide_pos;\n                if (block == S) {\n                    if (d == 0) slide_pos = c;                     // (0, c)\n                    else if (d == 1) slide_pos = (N-1)*N + c;      // (N-1, c)\n                    else if (d == 2) slide_pos = r * N;            // (r, 0)\n                    else slide_pos = r * N + (N-1);                // (r, N-1)\n                } else {\n                    int br = block / N, bc = block % N;\n                    if (d == 0) {  // up\n                        if (bc == c && br < r) slide_pos = (br + 1) * N + c;\n                        else slide_pos = c;\n                    } else if (d == 1) {  // down\n                        if (bc == c && br > r) slide_pos = (br - 1) * N + c;\n                        else slide_pos = (N-1)*N + c;\n                    } else if (d == 2) {  // left\n                        if (br == r && bc < c) slide_pos = r * N + (bc + 1);\n                        else slide_pos = r * N;\n                    } else {  // right\n                        if (br == r && bc > c) slide_pos = r * N + (bc - 1);\n                        else slide_pos = r * N + (N-1);\n                    }\n                }\n                int nstate_s = slide_pos * state_size + block;\n                if (vis[nstate_s] != tok) {\n                    vis[nstate_s] = tok;\n                    ps[nstate_s] = s;\n                    pa[nstate_s] = 1 * 4 + d;  // Slide\n                    q[tail++] = nstate_s;\n                }\n\n                // --- Alter ---\n                int adj_r = r, adj_c = c;\n                if (d == 0) adj_r--;\n                else if (d == 1) adj_r++;\n                else if (d == 2) adj_c--;\n                else adj_c++;\n                if (adj_r >= 0 && adj_r < N && adj_c >= 0 && adj_c < N) {\n                    int adj_id = adj_r * N + adj_c;\n                    if (block == S) {\n                        // place block\n                        int nstate = pos * state_size + adj_id;\n                        if (vis[nstate] != tok) {\n                            vis[nstate] = tok;\n                            ps[nstate] = s;\n                            pa[nstate] = 2 * 4 + d;  // Alter (place)\n                            q[tail++] = nstate;\n                        }\n                    } else {\n                        if (adj_id == block) {\n                            // remove block\n                            int nstate = pos * state_size + S;\n                            if (vis[nstate] != tok) {\n                                vis[nstate] = tok;\n                                ps[nstate] = s;\n                                pa[nstate] = 2 * 4 + d;  // Alter (remove)\n                                q[tail++] = nstate;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        // reconstruct action sequence for this segment\n        vector<int> seg_actions;\n        for (int s = goal_state; s != start_state; s = ps[s]) {\n            seg_actions.push_back(pa[s]);\n        }\n        reverse(seg_actions.begin(), seg_actions.end());\n        total_actions.insert(total_actions.end(), seg_actions.begin(), seg_actions.end());\n    }\n\n    // cancel consecutive identical Alter actions (place/remove pairs that do nothing)\n    vector<int> opt_actions;\n    for (int aid : total_actions) {\n        if (!opt_actions.empty() && opt_actions.back() == aid && (aid / 4) == 2) {\n            opt_actions.pop_back();\n        } else {\n            opt_actions.push_back(aid);\n        }\n    }\n    total_actions = move(opt_actions);\n\n    const char act_chars[3] = {'M', 'S', 'A'};\n    const char dir_chars[4] = {'U', 'D', 'L', 'R'};\n    for (int aid : total_actions) {\n        cout << act_chars[aid / 4] << ' ' << dir_chars[aid % 4] << '\\n';\n    }\n\n    return 0;\n}"},"16":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\nusing namespace chrono;\n\nstruct XorShift {\n    uint32_t x, y, z, w;\n    XorShift(uint32_t seed = 123456789) : x(seed), y(362436069), z(521288629), w(88675123) {\n        for (int i = 0; i < 10; i++) next();\n    }\n    uint32_t next() {\n        uint32_t t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = w ^ (w >> 19) ^ t ^ (t >> 8);\n    }\n    int nextInt(int max) {\n        return next() % (max + 1);\n    }\n    double nextDouble() {\n        return (next() & 0xFFFFFF) / 16777216.0;\n    }\n};\n\nstruct Node {\n    int type;   // 0:leaf, 1:vertical, 2:horizontal\n    int leaf_id;\n    int k;\n    int left, right;\n    int parent;\n    int min_k, max_k;\n    int x1, y1, x2, y2;\n    double score;\n};\n\nint n;\nvector<int> x, y, r;\nvector<Node> nodes;\nint root;\nXorShift rng(system_clock::now().time_since_epoch().count());\n\ndouble leaf_score(long long area, int req) {\n    double rat = (area <= req) ? (double)area / req : (double)req / area;\n    return 2.0 * rat - rat * rat;\n}\n\ndouble eval_subtree(int idx) {\n    Node& node = nodes[idx];\n    if (node.type == 0) {\n        long long area = (long long)(node.x2 - node.x1) * (node.y2 - node.y1);\n        node.score = leaf_score(area, r[node.leaf_id]);\n        return node.score;\n    }\n    int k = node.k;\n    if (node.type == 1) {\n        nodes[node.left].x1 = node.x1; nodes[node.left].y1 = node.y1;\n        nodes[node.left].x2 = k;       nodes[node.left].y2 = node.y2;\n        nodes[node.right].x1 = k;      nodes[node.right].y1 = node.y1;\n        nodes[node.right].x2 = node.x2; nodes[node.right].y2 = node.y2;\n    } else {\n        nodes[node.left].x1 = node.x1; nodes[node.left].y1 = node.y1;\n        nodes[node.left].x2 = node.x2; nodes[node.left].y2 = k;\n        nodes[node.right].x1 = node.x1; nodes[node.right].y1 = k;\n        nodes[node.right].x2 = node.x2; nodes[node.right].y2 = node.y2;\n    }\n    double ls = eval_subtree(node.left);\n    double rs = eval_subtree(node.right);\n    node.score = ls + rs;\n    return node.score;\n}\n\nvoid full_eval() {\n    nodes[root].x1 = 0; nodes[root].y1 = 0;\n    nodes[root].x2 = 10000; nodes[root].y2 = 10000;\n    eval_subtree(root);\n}\n\nvoid get_points_minmax(int idx, int& min_x, int& max_x, int& min_y, int& max_y) {\n    Node& nd = nodes[idx];\n    if (nd.type == 0) {\n        min_x = max_x = x[nd.leaf_id];\n        min_y = max_y = y[nd.leaf_id];\n    } else {\n        int lx_min, lx_max, ly_min, ly_max;\n        get_points_minmax(nd.left, lx_min, lx_max, ly_min, ly_max);\n        int rx_min, rx_max, ry_min, ry_max;\n        get_points_minmax(nd.right, rx_min, rx_max, ry_min, ry_max);\n        min_x = min(lx_min, rx_min);\n        max_x = max(lx_max, rx_max);\n        min_y = min(ly_min, ry_min);\n        max_y = max(ly_max, ry_max);\n    }\n}\n\nbool try_reorient(int idx) {\n    Node& node = nodes[idx];\n    if (node.type == 0) return false;\n    int lx_min, lx_max, ly_min, ly_max;\n    int rx_min, rx_max, ry_min, ry_max;\n    get_points_minmax(node.left, lx_min, lx_max, ly_min, ly_max);\n    get_points_minmax(node.right, rx_min, rx_max, ry_min, ry_max);\n\n    if (node.type == 1) { // vertical -> horizontal\n        if (ly_max < ry_min) {\n            node.type = 2;\n            node.min_k = ly_max + 1;\n            node.max_k = ry_min;\n            node.k = node.min_k + rng.nextInt(node.max_k - node.min_k);\n            return true;\n        }\n        if (ry_max < ly_min) {\n            swap(node.left, node.right);\n            node.type = 2;\n            node.min_k = ry_max + 1;\n            node.max_k = ly_min;\n            node.k = node.min_k + rng.nextInt(node.max_k - node.min_k);\n            return true;\n        }\n    } else {\n        if (lx_max < rx_min) {\n            node.type = 1;\n            node.min_k = lx_max + 1;\n            node.max_k = rx_min;\n            node.k = node.min_k + rng.nextInt(node.max_k - node.min_k);\n            return true;\n        }\n        if (rx_max < lx_min) {\n            swap(node.left, node.right);\n            node.type = 1;\n            node.min_k = rx_max + 1;\n            node.max_k = lx_min;\n            node.k = node.min_k + rng.nextInt(node.max_k - node.min_k);\n            return true;\n        }\n    }\n    return false;\n}\n\nbool try_swap_children(int idx) {\n    Node& node = nodes[idx];\n    if (node.type == 0) return false;\n    int lx_min, lx_max, ly_min, ly_max;\n    int rx_min, rx_max, ry_min, ry_max;\n    get_points_minmax(node.left, lx_min, lx_max, ly_min, ly_max);\n    get_points_minmax(node.right, rx_min, rx_max, ry_min, ry_max);\n    int new_min_k, new_max_k;\n    if (node.type == 1) {\n        new_min_k = rx_max + 1;\n        new_max_k = lx_min;\n    } else {\n        new_min_k = ry_max + 1;\n        new_max_k = ly_min;\n    }\n    if (new_min_k > new_max_k) return false;\n    swap(node.left, node.right);\n    node.min_k = new_min_k;\n    node.max_k = new_max_k;\n    node.k = new_min_k + rng.nextInt(new_max_k - new_min_k);\n    return true;\n}\n\nvoid collect_leaves(int idx, vector<int>& out) {\n    Node& nd = nodes[idx];\n    if (nd.type == 0) out.push_back(nd.leaf_id);\n    else {\n        collect_leaves(nd.left, out);\n        collect_leaves(nd.right, out);\n    }\n}\n\nint build_greedy_tree(const vector<int>& pts, int x1, int y1, int x2, int y2, int parent);\nint build_random_tree(const vector<int>& pts, int x1, int y1, int x2, int y2, int parent);\n\nint build_greedy_tree(const vector<int>& pts, int x1, int y1, int x2, int y2, int parent) {\n    if (pts.size() == 1) {\n        int id = pts[0];\n        nodes.push_back({0, id, 0, -1, -1, parent, 0, 0, 0, 0, 0, 0, 0.0});\n        return (int)nodes.size() - 1;\n    }\n    long long sumR = 0;\n    for (int id : pts) sumR += r[id];\n\n    struct Candidate { int orient; int k; vector<int> left, right; double err; };\n    vector<Candidate> cands;\n\n    vector<int> sorted = pts;\n    sort(sorted.begin(), sorted.end(), [&](int a, int b) { return x[a] < x[b]; });\n    long long left_sum = 0;\n    for (size_t i = 0; i + 1 < sorted.size(); i++) {\n        left_sum += r[sorted[i]];\n        double ideal = (double)left_sum / sumR;\n        int min_k = x[sorted[i]] + 1;\n        int max_k = x[sorted[i+1]];\n        if (min_k > max_k) continue;\n        int k = clamp((int)round(x1 + ideal * (x2 - x1)), min_k, max_k);\n        double actual = (double)(k - x1) / (x2 - x1);\n        double err = fabs(actual - ideal);\n        cands.push_back({1, k, \n            vector<int>(sorted.begin(), sorted.begin()+i+1),\n            vector<int>(sorted.begin()+i+1, sorted.end()), err});\n    }\n\n    sort(sorted.begin(), sorted.end(), [&](int a, int b) { return y[a] < y[b]; });\n    left_sum = 0;\n    for (size_t i = 0; i + 1 < sorted.size(); i++) {\n        left_sum += r[sorted[i]];\n        double ideal = (double)left_sum / sumR;\n        int min_k = y[sorted[i]] + 1;\n        int max_k = y[sorted[i+1]];\n        if (min_k > max_k) continue;\n        int k = clamp((int)round(y1 + ideal * (y2 - y1)), min_k, max_k);\n        double actual = (double)(k - y1) / (y2 - y1);\n        double err = fabs(actual - ideal);\n        cands.push_back({2, k, \n            vector<int>(sorted.begin(), sorted.begin()+i+1),\n            vector<int>(sorted.begin()+i+1, sorted.end()), err});\n    }\n\n    double min_err = 1e9;\n    for (auto& c : cands) if (c.err < min_err) min_err = c.err;\n    vector<double> w(cands.size());\n    double sum_w = 0;\n    for (size_t i = 0; i < cands.size(); i++) {\n        w[i] = exp(-(cands[i].err - min_err) * 100.0);\n        sum_w += w[i];\n    }\n    double rv = rng.nextDouble() * sum_w;\n    size_t chosen = 0;\n    double cum = 0;\n    for (size_t i = 0; i < cands.size(); i++) {\n        cum += w[i];\n        if (cum >= rv) { chosen = i; break; }\n    }\n    Candidate& best = cands[chosen];\n\n    nodes.push_back({best.orient, -1, best.k, -1, -1, parent, 0, 0, 0, 0, 0, 0, 0.0});\n    int idx = (int)nodes.size() - 1;\n    int lchild, rchild;\n    if (best.orient == 1) {\n        lchild = build_greedy_tree(best.left, x1, y1, best.k, y2, idx);\n        rchild = build_greedy_tree(best.right, best.k, y1, x2, y2, idx);\n        int max_x_left = 0, min_x_right = 10000;\n        for (int id : best.left) max_x_left = max(max_x_left, x[id]);\n        for (int id : best.right) min_x_right = min(min_x_right, x[id]);\n        nodes[idx].min_k = max_x_left + 1;\n        nodes[idx].max_k = min_x_right;\n    } else {\n        lchild = build_greedy_tree(best.left, x1, y1, x2, best.k, idx);\n        rchild = build_greedy_tree(best.right, x1, best.k, x2, y2, idx);\n        int max_y_bottom = 0, min_y_top = 10000;\n        for (int id : best.left) max_y_bottom = max(max_y_bottom, y[id]);\n        for (int id : best.right) min_y_top = min(min_y_top, y[id]);\n        nodes[idx].min_k = max_y_bottom + 1;\n        nodes[idx].max_k = min_y_top;\n    }\n    nodes[idx].left = lchild;\n    nodes[idx].right = rchild;\n    return idx;\n}\n\nint build_random_tree(const vector<int>& pts, int x1, int y1, int x2, int y2, int parent) {\n    if (pts.size() == 1) {\n        int id = pts[0];\n        nodes.push_back({0, id, 0, -1, -1, parent, 0, 0, 0, 0, 0, 0, 0.0});\n        return (int)nodes.size() - 1;\n    }\n    vector<int> xsorted = pts, ysorted = pts;\n    sort(xsorted.begin(), xsorted.end(), [&](int a, int b) { return x[a] < x[b]; });\n    sort(ysorted.begin(), ysorted.end(), [&](int a, int b) { return y[a] < y[b]; });\n\n    vector<int> v_splits;\n    for (size_t i = 0; i + 1 < xsorted.size(); i++) {\n        if (x[xsorted[i]] + 1 <= x[xsorted[i+1]]) v_splits.push_back(i);\n    }\n    vector<int> h_splits;\n    for (size_t i = 0; i + 1 < ysorted.size(); i++) {\n        if (y[ysorted[i]] + 1 <= y[ysorted[i+1]]) h_splits.push_back(i);\n    }\n    if (v_splits.empty() && h_splits.empty()) {\n        return build_greedy_tree(pts, x1, y1, x2, y2, parent);\n    }\n    int orient, split_idx;\n    if (v_splits.empty()) {\n        orient = 2;\n        split_idx = h_splits[rng.nextInt((int)h_splits.size() - 1)];\n    } else if (h_splits.empty()) {\n        orient = 1;\n        split_idx = v_splits[rng.nextInt((int)v_splits.size() - 1)];\n    } else {\n        if (rng.nextDouble() < 0.5) {\n            orient = 1;\n            split_idx = v_splits[rng.nextInt((int)v_splits.size() - 1)];\n        } else {\n            orient = 2;\n            split_idx = h_splits[rng.nextInt((int)h_splits.size() - 1)];\n        }\n    }\n    vector<int> left_pts, right_pts;\n    int min_k, max_k;\n    if (orient == 1) {\n        left_pts.assign(xsorted.begin(), xsorted.begin() + split_idx + 1);\n        right_pts.assign(xsorted.begin() + split_idx + 1, xsorted.end());\n        min_k = x[xsorted[split_idx]] + 1;\n        max_k = x[xsorted[split_idx+1]];\n    } else {\n        left_pts.assign(ysorted.begin(), ysorted.begin() + split_idx + 1);\n        right_pts.assign(ysorted.begin() + split_idx + 1, ysorted.end());\n        min_k = y[ysorted[split_idx]] + 1;\n        max_k = y[ysorted[split_idx+1]];\n    }\n    int k = min_k + rng.nextInt(max_k - min_k);\n    nodes.push_back({orient, -1, k, -1, -1, parent, min_k, max_k, 0, 0, 0, 0, 0.0});\n    int idx = (int)nodes.size() - 1;\n    int lchild, rchild;\n    if (orient == 1) {\n        lchild = build_random_tree(left_pts, x1, y1, k, y2, idx);\n        rchild = build_random_tree(right_pts, k, y1, x2, y2, idx);\n    } else {\n        lchild = build_random_tree(left_pts, x1, y1, x2, k, idx);\n        rchild = build_random_tree(right_pts, x1, k, x2, y2, idx);\n    }\n    nodes[idx].left = lchild;\n    nodes[idx].right = rchild;\n    return idx;\n}\n\nvector<int> get_internal_nodes() {\n    vector<int> res;\n    function<void(int)> dfs = [&](int u) {\n        if (nodes[u].type != 0) res.push_back(u);\n        if (nodes[u].type != 0) {\n            dfs(nodes[u].left);\n            dfs(nodes[u].right);\n        }\n    };\n    dfs(root);\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n;\n    x.resize(n); y.resize(n); r.resize(n);\n    for (int i = 0; i < n; i++) cin >> x[i] >> y[i] >> r[i];\n\n    double global_best_score = -1e9;\n    vector<Node> best_nodes;\n    int best_root = -1;\n    auto start_time = steady_clock::now();\n    auto time_left = [&]() { return duration<double>(steady_clock::now() - start_time).count() > 4.7; };\n\n    while (!time_left()) {\n        nodes.clear();\n        vector<int> all(n);\n        iota(all.begin(), all.end(), 0);\n        root = build_greedy_tree(all, 0, 0, 10000, 10000, -1);\n        full_eval();\n        double current_score = nodes[root].score;\n\n        double best_restart_score = current_score;\n        vector<Node> best_restart_nodes = nodes;\n        int best_restart_root = root;\n\n        const int max_iter = 200000;\n        const double T_start = 1.0;\n        const double T_end = 1e-6;\n\n        for (int iter = 0; iter < max_iter; iter++) {\n            if (iter % 100 == 0 && time_left()) break;\n\n            double progress = (double)iter / max_iter;\n            double T = T_start * pow(T_end / T_start, progress);\n\n            vector<int> internals = get_internal_nodes();\n            if (internals.empty()) continue;\n\n            int move_type = rng.nextInt(99);\n            if (move_type < 60) {\n                // change cut coordinate\n                int idx = internals[rng.nextInt((int)internals.size() - 1)];\n                if (nodes[idx].min_k == nodes[idx].max_k) continue;\n                int old_k = nodes[idx].k;\n                double old_sub_score = nodes[idx].score;\n                int new_k = nodes[idx].min_k + rng.nextInt(nodes[idx].max_k - nodes[idx].min_k);\n                if (new_k == old_k) continue;\n                nodes[idx].k = new_k;\n                double new_sub_score = eval_subtree(idx);\n                double diff = new_sub_score - old_sub_score;\n                if (diff > 0 || rng.nextDouble() < exp(diff / T)) {\n                    if (abs(diff) > 1e-12) {\n                        int p = nodes[idx].parent;\n                        while (p != -1) { nodes[p].score += diff; p = nodes[p].parent; }\n                    }\n                    current_score += diff;\n                    if (current_score > best_restart_score) {\n                        best_restart_score = current_score;\n                        best_restart_nodes = nodes;\n                        best_restart_root = root;\n                    }\n                } else {\n                    nodes[idx].k = old_k;\n                    eval_subtree(idx);\n                }\n            } else if (move_type < 80) {\n                // reorient (20%)\n                bool accepted = false;\n                for (int attempt = 0; attempt < 5; attempt++) {\n                    int idx = internals[rng.nextInt((int)internals.size() - 1)];\n                    Node saved = nodes[idx];\n                    int sl = nodes[idx].left, sr = nodes[idx].right;\n                    if (!try_reorient(idx)) continue;\n                    double old_sub_score = nodes[idx].score;\n                    double new_sub_score = eval_subtree(idx);\n                    double diff = new_sub_score - old_sub_score;\n                    if (diff > 0 || rng.nextDouble() < exp(diff / T)) {\n                        if (abs(diff) > 1e-12) {\n                            int p = nodes[idx].parent;\n                            while (p != -1) { nodes[p].score += diff; p = nodes[p].parent; }\n                        }\n                        current_score += diff;\n                        if (current_score > best_restart_score) {\n                            best_restart_score = current_score;\n                            best_restart_nodes = nodes;\n                            best_restart_root = root;\n                        }\n                        accepted = true;\n                        break;\n                    } else {\n                        nodes[idx] = saved;\n                        nodes[idx].left = sl; nodes[idx].right = sr;\n                        eval_subtree(idx);\n                    }\n                }\n            } else if (move_type < 85) {\n                // swap children (5%)\n                bool accepted = false;\n                for (int attempt = 0; attempt < 5; attempt++) {\n                    int idx = internals[rng.nextInt((int)internals.size() - 1)];\n                    Node saved = nodes[idx];\n                    int sl = nodes[idx].left, sr = nodes[idx].right;\n                    if (!try_swap_children(idx)) continue;\n                    double old_sub_score = nodes[idx].score;\n                    double new_sub_score = eval_subtree(idx);\n                    double diff = new_sub_score - old_sub_score;\n                    if (diff > 0 || rng.nextDouble() < exp(diff / T)) {\n                        if (abs(diff) > 1e-12) {\n                            int p = nodes[idx].parent;\n                            while (p != -1) { nodes[p].score += diff; p = nodes[p].parent; }\n                        }\n                        current_score += diff;\n                        if (current_score > best_restart_score) {\n                            best_restart_score = current_score;\n                            best_restart_nodes = nodes;\n                            best_restart_root = root;\n                        }\n                        accepted = true;\n                        break;\n                    } else {\n                        nodes[idx] = saved;\n                        nodes[idx].left = sl; nodes[idx].right = sr;\n                        eval_subtree(idx);\n                    }\n                }\n            } else {\n                // local rebuild (15%)\n                int idx = internals[rng.nextInt((int)internals.size() - 1)];\n                Node& nd = nodes[idx];\n                vector<int> leaves;\n                collect_leaves(idx, leaves);\n                int px1 = nd.x1, py1 = nd.y1, px2 = nd.x2, py2 = nd.y2;\n                double old_sub_score = nd.score;\n                int p = nd.parent;\n                bool is_left = (p != -1 && nodes[p].left == idx);\n\n                vector<Node> backup_nodes = nodes;\n                int backup_root = root;\n                double backup_score = current_score;\n\n                int new_subroot;\n                if (rng.nextDouble() < 0.5)\n                    new_subroot = build_greedy_tree(leaves, px1, py1, px2, py2, p);\n                else\n                    new_subroot = build_random_tree(leaves, px1, py1, px2, py2, p);\n                nodes[new_subroot].x1 = px1; nodes[new_subroot].y1 = py1;\n                nodes[new_subroot].x2 = px2; nodes[new_subroot].y2 = py2;\n                if (p != -1) {\n                    if (is_left) nodes[p].left = new_subroot;\n                    else nodes[p].right = new_subroot;\n                } else {\n                    root = new_subroot;\n                }\n                double new_sub_score = eval_subtree(new_subroot);\n                double diff = new_sub_score - old_sub_score;\n                if (abs(diff) > 1e-12) {\n                    int par = p;\n                    while (par != -1) { nodes[par].score += diff; par = nodes[par].parent; }\n                }\n                current_score += diff;\n                if (diff > 0 || rng.nextDouble() < exp(diff / T)) {\n                    if (current_score > best_restart_score) {\n                        best_restart_score = current_score;\n                        best_restart_nodes = nodes;\n                        best_restart_root = root;\n                    }\n                } else {\n                    nodes = move(backup_nodes);\n                    root = backup_root;\n                    current_score = backup_score;\n                }\n            }\n        }\n\n        if (best_restart_score > global_best_score) {\n            global_best_score = best_restart_score;\n            best_nodes = best_restart_nodes;\n            best_root = best_restart_root;\n        }\n    }\n\n    // Final polishing\n    nodes = move(best_nodes);\n    root = best_root;\n    full_eval();\n    vector<int> internals = get_internal_nodes();\n    for (int idx : internals) {\n        if (nodes[idx].min_k >= nodes[idx].max_k) continue;\n        int old_k = nodes[idx].k;\n        double best_local = nodes[root].score;\n        int best_k = old_k;\n        for (int k = nodes[idx].min_k; k <= nodes[idx].max_k; k++) {\n            if (k == old_k) continue;\n            nodes[idx].k = k;\n            full_eval();\n            double sc = nodes[root].score;\n            if (sc > best_local) {\n                best_local = sc;\n                best_k = k;\n            }\n        }\n        if (best_k != old_k) {\n            nodes[idx].k = best_k;\n            full_eval();\n        } else {\n            nodes[idx].k = old_k;\n            full_eval();\n        }\n    }\n\n    // Output\n    full_eval();\n    vector<array<int,4>> ans(n);\n    function<void(int)> collect = [&](int u) {\n        Node& nd = nodes[u];\n        if (nd.type == 0) {\n            ans[nd.leaf_id] = {nd.x1, nd.y1, nd.x2, nd.y2};\n        } else {\n            collect(nd.left);\n            collect(nd.right);\n        }\n    };\n    collect(root);\n    for (auto [a,b,c,d] : ans) cout << a << \" \" << b << \" \" << c << \" \" << d << \"\\n\";\n\n    return 0;\n}","ahc002":"#include <iostream>\n#include <vector>\n#include <bitset>\n#include <algorithm>\n#include <chrono>\n#include <numeric>\n#include <string>\nusing namespace std;\n\nconstexpr int N = 50;\nconstexpr int MAX_TILES = 2500;\n\nstruct State {\n    int parent_id;\n    unsigned char move;   // 0: none, 1:U,2:D,3:L,4:R\n    unsigned short x, y;\n    unsigned short tile;\n    int score;\n    int potential;        // sum of max_p of remaining unvisited tiles\n    bitset<MAX_TILES> visited;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj;\n    cin >> si >> sj;\n\n    vector tile(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> tile[i][j];\n\n    vector p(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> p[i][j];\n\n    int M = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (tile[i][j] > M) M = tile[i][j];\n    M += 1;\n\n    vector<int> max_p(M, 0);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (p[i][j] > max_p[tile[i][j]])\n                max_p[tile[i][j]] = p[i][j];\n\n    long long total_max = 0;\n    for (int v : max_p) total_max += v;\n\n    const int dirs[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};\n    const char move_chars[4] = {'U', 'D', 'L', 'R'};\n\n    int start_tile = tile[si][sj];\n    int start_potential = (int)(total_max - max_p[start_tile]);\n\n    vector<State> states;\n    states.reserve(2000000);\n    State init;\n    init.parent_id = -1;\n    init.move = 0;\n    init.x = (unsigned short)si;\n    init.y = (unsigned short)sj;\n    init.tile = (unsigned short)start_tile;\n    init.score = p[si][sj];\n    init.potential = start_potential;\n    init.visited.reset();\n    init.visited.set(start_tile);\n    states.push_back(init);\n\n    vector<int> cur = {0};\n    int best_id = 0;\n\n    const int BEAM_WIDTH = 300;\n    auto start_time = chrono::steady_clock::now();\n\n    while (!cur.empty()) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - start_time).count() > 1950) break;\n        if (states.size() > 2000000) break;\n\n        vector<int> nxt;\n        nxt.reserve(cur.size() * 4);\n        for (int id : cur) {\n            const State& st = states[id];\n            int x = st.x, y = st.y;\n            for (int d = 0; d < 4; ++d) {\n                int nx = x + dirs[d][0], ny = y + dirs[d][1];\n                if (nx < 0 || nx >= N || ny < 0 || ny >= N) continue;\n                int nxt_tile = tile[nx][ny];\n                if (st.visited[nxt_tile]) continue;   // cannot step on same tile\n                State ns = st;\n                ns.x = (unsigned short)nx;\n                ns.y = (unsigned short)ny;\n                ns.tile = (unsigned short)nxt_tile;\n                ns.score = st.score + p[nx][ny];\n                ns.potential = st.potential - max_p[nxt_tile];\n                ns.visited.set(nxt_tile);\n                ns.parent_id = id;\n                ns.move = (unsigned char)(d + 1);\n                nxt.push_back((int)states.size());\n                states.push_back(move(ns));\n                if (states.back().score > states[best_id].score) {\n                    best_id = (int)states.size() - 1;\n                }\n            }\n        }\n        if (nxt.empty()) break;\n\n        if ((int)nxt.size() > BEAM_WIDTH) {\n            vector<long long> h(nxt.size());\n            for (size_t i = 0; i < nxt.size(); ++i) {\n                const State& s = states[nxt[i]];\n                h[i] = (long long)s.score + s.potential;\n            }\n            vector<int> idx(nxt.size());\n            iota(idx.begin(), idx.end(), 0);\n            sort(idx.begin(), idx.end(), [&](int i, int j) { return h[i] > h[j]; });\n            cur.clear();\n            cur.reserve(BEAM_WIDTH);\n            for (int i = 0; i < BEAM_WIDTH; ++i) {\n                cur.push_back(nxt[idx[i]]);\n            }\n        } else {\n            cur = move(nxt);\n        }\n    }\n\n    // reconstruct path\n    string ans;\n    for (int id = best_id; id > 0; id = states[id].parent_id) {\n        int m = states[id].move - 1;\n        ans.push_back(move_chars[m]);\n    }\n    reverse(ans.begin(), ans.end());\n\n    // verify\n    vector<int> tile_vis(M, 0);\n    int cx = si, cy = sj;\n    int ct = start_tile;\n    tile_vis[ct] = 1;\n    bool ok = true;\n    for (char c : ans) {\n        if (c == 'U') cx--;\n        else if (c == 'D') cx++;\n        else if (c == 'L') cy--;\n        else if (c == 'R') cy++;\n        else { ok = false; break; }\n        if (cx < 0 || cx >= N || cy < 0 || cy >= N) { ok = false; break; }\n        int nt = tile[cx][cy];\n        if (nt == ct) {\n            // step on same tile twice in a row (intra-tile move) -> invalid\n            ok = false; break;\n        }\n        if (tile_vis[nt]) { ok = false; break; }\n        tile_vis[nt] = 1;\n        ct = nt;\n    }\n    if (!ok) {\n        // fallback: empty path (stay at start)\n        ans.clear();\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int N = 30;\nconstexpr int H_EDGES = N * (N - 1);\nconstexpr int V_EDGES = (N - 1) * N;\nconstexpr int E = H_EDGES + V_EDGES;\n\ninline int edge_idx_horiz(int i, int j) { return i * (N - 1) + j; }\ninline int edge_idx_vert(int i, int j) { return H_EDGES + i * N + j; }\n\n// Dijkstra with exploration bonus and tiny noise\nstring dijkstra(int si, int sj, int ti, int tj,\n                const vector<double>& w_plan,\n                const vector<int>& cnt,\n                double alpha_explore,\n                mt19937& rng,\n                vector<int>& path_edges) {\n    int start = si * N + sj;\n    int goal = ti * N + tj;\n\n    vector<double> dist(N * N, 1e18);\n    vector<int> parent(N * N, -1), parent_edge(N * N, -1);\n    dist[start] = 0;\n\n    using P = pair<double, int>;\n    priority_queue<P, vector<P>, greater<P>> pq;\n    pq.push({0, start});\n\n    uniform_real_distribution<double> noise(-0.5, 0.5);\n\n    static vector<vector<pair<int, int>>> adj;\n    if (adj.empty()) {\n        adj.resize(N * N);\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (j < N - 1) {\n                    int u = i * N + j, v = i * N + j + 1;\n                    int e = edge_idx_horiz(i, j);\n                    adj[u].push_back({v, e});\n                    adj[v].push_back({u, e});\n                }\n                if (i < N - 1) {\n                    int u = i * N + j, v = (i + 1) * N + j;\n                    int e = edge_idx_vert(i, j);\n                    adj[u].push_back({v, e});\n                    adj[v].push_back({u, e});\n                }\n            }\n        }\n    }\n\n    while (!pq.empty()) {\n        auto [d, u] = pq.top(); pq.pop();\n        if (d != dist[u]) continue;\n        if (u == goal) break;\n        for (auto [v, e] : adj[u]) {\n            double w_used = w_plan[e] - alpha_explore / sqrt(cnt[e] + 1.0);\n            if (w_used < 1.0) w_used = 1.0;\n            double nd = d + w_used + noise(rng) * 0.1;\n            if (nd < dist[v]) {\n                dist[v] = nd;\n                parent[v] = u;\n                parent_edge[v] = e;\n                pq.push({nd, v});\n            }\n        }\n    }\n\n    path_edges.clear();\n    vector<int> nodes;\n    for (int cur = goal; cur != start; cur = parent[cur]) {\n        nodes.push_back(cur);\n        path_edges.push_back(parent_edge[cur]);\n    }\n    nodes.push_back(start);\n    reverse(nodes.begin(), nodes.end());\n    reverse(path_edges.begin(), path_edges.end());\n\n    string moves;\n    for (size_t i = 0; i + 1 < nodes.size(); ++i) {\n        int u = nodes[i], v = nodes[i + 1];\n        int ui = u / N, uj = u % N;\n        int vi = v / N, vj = v % N;\n        if (vi == ui - 1) moves += 'U';\n        else if (vi == ui + 1) moves += 'D';\n        else if (vj == uj - 1) moves += 'L';\n        else moves += 'R';\n    }\n    return moves;\n}\n\n// Soft segmentation: gently pull edges toward the best piecewise constant model\nvoid soft_segment_rows(vector<double>& w, const vector<int>& cnt, double lr_soft) {\n    for (int i = 0; i < N; ++i) {\n        int total_cnt = 0;\n        for (int j = 0; j < N - 1; ++j) total_cnt += cnt[edge_idx_horiz(i, j)];\n        if (total_cnt < 5) continue;\n\n        vector<double> vals(N - 1);\n        vector<double> weight(N - 1);\n        double total_weight = 0.0, total_wsum = 0.0, total_wsum2 = 0.0;\n        for (int j = 0; j < N - 1; ++j) {\n            int e = edge_idx_horiz(i, j);\n            vals[j] = w[e];\n            double wgt = cnt[e] + 1.0;\n            weight[j] = wgt;\n            total_weight += wgt;\n            total_wsum += wgt * vals[j];\n            total_wsum2 += wgt * vals[j] * vals[j];\n        }\n\n        double mean_all = total_wsum / total_weight;\n        double base_sse = total_wsum2 - 2.0 * mean_all * total_wsum + mean_all * mean_all * total_weight;\n        double best_sse = base_sse;\n        int best_x = -1;\n        double best_meanL = mean_all, best_meanR = mean_all;\n\n        double wsum_left = 0.0, wsum2_left = 0.0, wgt_left = 0.0;\n        for (int x = 1; x < N - 1; ++x) {\n            int j = x - 1;\n            double wgt = weight[j];\n            double v = vals[j];\n            wsum_left += wgt * v;\n            wsum2_left += wgt * v * v;\n            wgt_left += wgt;\n\n            double meanL = wsum_left / wgt_left;\n            double wgt_right = total_weight - wgt_left;\n            double wsum_right = total_wsum - wsum_left;\n            double meanR = wsum_right / wgt_right;\n            double wsum2_right = total_wsum2 - wsum2_left;\n\n            double sseL = wsum2_left - 2.0 * meanL * wsum_left + meanL * meanL * wgt_left;\n            double sseR = wsum2_right - 2.0 * meanR * wsum_right + meanR * meanR * wgt_right;\n            double sse = sseL + sseR;\n\n            if (sse < best_sse) {\n                best_sse = sse;\n                best_x = x;\n                best_meanL = meanL;\n                best_meanR = meanR;\n            }\n        }\n\n        double split_meanL = (best_x == -1) ? mean_all : best_meanL;\n        double split_meanR = (best_x == -1) ? mean_all : best_meanR;\n        int x_split = (best_x == -1) ? N - 1 : best_x;\n\n        for (int j = 0; j < N - 1; ++j) {\n            int e = edge_idx_horiz(i, j);\n            double target = (j < x_split) ? split_meanL : split_meanR;\n            double conf = cnt[e] / (cnt[e] + 5.0);\n            w[e] += lr_soft * conf * (target - w[e]);\n        }\n    }\n}\n\nvoid soft_segment_cols(vector<double>& w, const vector<int>& cnt, double lr_soft) {\n    for (int j = 0; j < N; ++j) {\n        int total_cnt = 0;\n        for (int i = 0; i < N - 1; ++i) total_cnt += cnt[edge_idx_vert(i, j)];\n        if (total_cnt < 5) continue;\n\n        vector<double> vals(N - 1);\n        vector<double> weight(N - 1);\n        double total_weight = 0.0, total_wsum = 0.0, total_wsum2 = 0.0;\n        for (int i = 0; i < N - 1; ++i) {\n            int e = edge_idx_vert(i, j);\n            vals[i] = w[e];\n            double wgt = cnt[e] + 1.0;\n            weight[i] = wgt;\n            total_weight += wgt;\n            total_wsum += wgt * vals[i];\n            total_wsum2 += wgt * vals[i] * vals[i];\n        }\n\n        double mean_all = total_wsum / total_weight;\n        double base_sse = total_wsum2 - 2.0 * mean_all * total_wsum + mean_all * mean_all * total_weight;\n        double best_sse = base_sse;\n        int best_x = -1;\n        double best_meanL = mean_all, best_meanR = mean_all;\n\n        double wsum_left = 0.0, wsum2_left = 0.0, wgt_left = 0.0;\n        for (int x = 1; x < N - 1; ++x) {\n            int i = x - 1;\n            double wgt = weight[i];\n            double v = vals[i];\n            wsum_left += wgt * v;\n            wsum2_left += wgt * v * v;\n            wgt_left += wgt;\n\n            double meanL = wsum_left / wgt_left;\n            double wgt_right = total_weight - wgt_left;\n            double wsum_right = total_wsum - wsum_left;\n            double meanR = wsum_right / wgt_right;\n            double wsum2_right = total_wsum2 - wsum2_left;\n\n            double sseL = wsum2_left - 2.0 * meanL * wsum_left + meanL * meanL * wgt_left;\n            double sseR = wsum2_right - 2.0 * meanR * wsum_right + meanR * meanR * wgt_right;\n            double sse = sseL + sseR;\n\n            if (sse < best_sse) {\n                best_sse = sse;\n                best_x = x;\n                best_meanL = meanL;\n                best_meanR = meanR;\n            }\n        }\n\n        double split_meanL = (best_x == -1) ? mean_all : best_meanL;\n        double split_meanR = (best_x == -1) ? mean_all : best_meanR;\n        int y_split = (best_x == -1) ? N - 1 : best_x;\n\n        for (int i = 0; i < N - 1; ++i) {\n            int e = edge_idx_vert(i, j);\n            double target = (i < y_split) ? split_meanL : split_meanR;\n            double conf = cnt[e] / (cnt[e] + 5.0);\n            w[e] += lr_soft * conf * (target - w[e]);\n        }\n    }\n}\n\n// Hard segmentation: replace w with two\u2011constant model if SSE improves significantly\nvoid hard_segment_rows(vector<double>& w, const vector<int>& cnt) {\n    for (int i = 0; i < N; ++i) {\n        vector<double> vals(N - 1);\n        vector<double> weight(N - 1);\n        double total_weight = 0.0, total_wsum = 0.0, total_wsum2 = 0.0;\n        for (int j = 0; j < N - 1; ++j) {\n            int e = edge_idx_horiz(i, j);\n            vals[j] = w[e];\n            double wgt = cnt[e] + 1.0;\n            weight[j] = wgt;\n            total_weight += wgt;\n            total_wsum += wgt * vals[j];\n            total_wsum2 += wgt * vals[j] * vals[j];\n        }\n        double mean_all = total_wsum / total_weight;\n        double base_sse = total_wsum2 - 2.0 * mean_all * total_wsum + mean_all * mean_all * total_weight;\n        double best_sse = base_sse;\n        int best_x = -1;\n        double best_meanL = mean_all, best_meanR = mean_all;\n        double wsum_left = 0.0, wsum2_left = 0.0, wgt_left = 0.0;\n        for (int x = 1; x < N - 1; ++x) {\n            int j = x - 1;\n            double wgt = weight[j];\n            double v = vals[j];\n            wsum_left += wgt * v;\n            wsum2_left += wgt * v * v;\n            wgt_left += wgt;\n            double meanL = wsum_left / wgt_left;\n            double wgt_right = total_weight - wgt_left;\n            double wsum_right = total_wsum - wsum_left;\n            double meanR = wsum_right / wgt_right;\n            double wsum2_right = total_wsum2 - wsum2_left;\n            double sseL = wsum2_left - 2.0 * meanL * wsum_left + meanL * meanL * wgt_left;\n            double sseR = wsum2_right - 2.0 * meanR * wsum_right + meanR * meanR * wgt_right;\n            double sse = sseL + sseR;\n            if (sse < best_sse) {\n                best_sse = sse;\n                best_x = x;\n                best_meanL = meanL;\n                best_meanR = meanR;\n            }\n        }\n        if (best_sse < base_sse * 0.95) {\n            for (int j = 0; j < N - 1; ++j) {\n                int e = edge_idx_horiz(i, j);\n                w[e] = (j < best_x) ? best_meanL : best_meanR;\n            }\n        } else {\n            for (int j = 0; j < N - 1; ++j) {\n                int e = edge_idx_horiz(i, j);\n                w[e] = mean_all;\n            }\n        }\n    }\n}\n\nvoid hard_segment_cols(vector<double>& w, const vector<int>& cnt) {\n    for (int j = 0; j < N; ++j) {\n        vector<double> vals(N - 1);\n        vector<double> weight(N - 1);\n        double total_weight = 0.0, total_wsum = 0.0, total_wsum2 = 0.0;\n        for (int i = 0; i < N - 1; ++i) {\n            int e = edge_idx_vert(i, j);\n            vals[i] = w[e];\n            double wgt = cnt[e] + 1.0;\n            weight[i] = wgt;\n            total_weight += wgt;\n            total_wsum += wgt * vals[i];\n            total_wsum2 += wgt * vals[i] * vals[i];\n        }\n        double mean_all = total_wsum / total_weight;\n        double base_sse = total_wsum2 - 2.0 * mean_all * total_wsum + mean_all * mean_all * total_weight;\n        double best_sse = base_sse;\n        int best_x = -1;\n        double best_meanL = mean_all, best_meanR = mean_all;\n        double wsum_left = 0.0, wsum2_left = 0.0, wgt_left = 0.0;\n        for (int x = 1; x < N - 1; ++x) {\n            int i = x - 1;\n            double wgt = weight[i];\n            double v = vals[i];\n            wsum_left += wgt * v;\n            wsum2_left += wgt * v * v;\n            wgt_left += wgt;\n            double meanL = wsum_left / wgt_left;\n            double wgt_right = total_weight - wgt_left;\n            double wsum_right = total_wsum - wsum_left;\n            double meanR = wsum_right / wgt_right;\n            double wsum2_right = total_wsum2 - wsum2_left;\n            double sseL = wsum2_left - 2.0 * meanL * wsum_left + meanL * meanL * wgt_left;\n            double sseR = wsum2_right - 2.0 * meanR * wsum_right + meanR * meanR * wgt_right;\n            double sse = sseL + sseR;\n            if (sse < best_sse) {\n                best_sse = sse;\n                best_x = x;\n                best_meanL = meanL;\n                best_meanR = meanR;\n            }\n        }\n        if (best_sse < base_sse * 0.95) {\n            for (int i = 0; i < N - 1; ++i) {\n                int e = edge_idx_vert(i, j);\n                w[e] = (i < best_x) ? best_meanL : best_meanR;\n            }\n        } else {\n            for (int i = 0; i < N - 1; ++i) {\n                int e = edge_idx_vert(i, j);\n                w[e] = mean_all;\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    vector<double> w(E, 5000.0);\n    vector<double> w_plan = w;\n    vector<int> cnt(E, 0);\n\n    mt19937 rng(12345);\n\n    // Exploration schedule \u2013 encourage diverse paths early\n    const double alpha_start   = 4500.0;\n    const double alpha_decay   = 4.5;\n\n    // Learning rate for additive gradient updates\n    const double base_lr       = 1600.0;\n    const double lr_decay_factor = 0.005;\n\n    auto clamp_w = [](double v) { return max(1000.0, min(9000.0, v)); };\n\n    for (int k = 0; k < 1000; ++k) {\n        double alpha_explore = max(0.0, alpha_start - k * alpha_decay);\n\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n\n        vector<int> path_edges;\n        string moves = dijkstra(si, sj, ti, tj, w_plan, cnt, alpha_explore, rng, path_edges);\n        cout << moves << endl;   // flush\n\n        int obs;\n        cin >> obs;\n\n        double pred = 0;\n        for (int e : path_edges) pred += w[e];\n\n        double grad = pred - obs;\n        double lr_decay = 1.0 / (1.0 + k * lr_decay_factor);\n        double lr_abs = base_lr / (pred + 1.0) * lr_decay;\n\n        for (int e : path_edges) {\n            w[e] -= lr_abs * grad;\n            w[e] = clamp_w(w[e]);\n            cnt[e]++;\n        }\n\n        // Soft segmentation (piecewise constant prior)\n        if (k >= 3) {\n            double lr_soft = min(0.30, 0.0025 * (k - 3));\n            soft_segment_rows(w, cnt, lr_soft);\n            soft_segment_cols(w, cnt, lr_soft);\n            for (int e = 0; e < E; ++e) w[e] = clamp_w(w[e]);\n        }\n\n        // Smooth planning weights \u2013 more aggressive later\n        double rho = min(0.40, 0.04 + k / 2000.0);\n        for (int e = 0; e < E; ++e)\n            w_plan[e] = (1 - rho) * w_plan[e] + rho * w[e];\n\n        // Hard segment to enforce the discovered block structure\n        if ((k + 1) % 50 == 0 && k >= 49) {\n            hard_segment_rows(w, cnt);\n            hard_segment_cols(w, cnt);\n            for (int e = 0; e < E; ++e) {\n                w[e] = clamp_w(w[e]);\n                w_plan[e] = w[e];   // adopt cleaned model completely\n            }\n        }\n    }\n\n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n#include <cstring>\n#include <chrono>\n#include <cstdint>\n\nusing namespace std;\nusing namespace std::chrono;\n\nconstexpr int N = 20;\nconstexpr int LETTERS = 8;\nconst char letters[LETTERS] = {'A','B','C','D','E','F','G','H'};\n\n// ---- fast random generator ----\nstruct XorShift {\n    uint32_t x;\n    XorShift(uint32_t seed) : x(seed) {}\n    uint32_t next() {\n        x ^= x << 13;\n        x ^= x >> 17;\n        x ^= x << 5;\n        return x;\n    }\n    int nextInt(int max) { return next() % max; }\n    double nextDouble() { return (next() >> 8) * 0x1p-24; }\n};\n\n// ---- problem data ----\nint M;\nvector<string> strs;\nvector<int> len;\n\n// ---- incremental match tracking ----\nvector<int> h_match;   // [i*N*N + r*N + start]\nvector<int> v_match;   // [i*N*N + c*N + start]\nvector<int> h_count;   // [i*N + r]\nvector<int> v_count;   // [i*N + c]\nvector<int> s_count;   // [i]\nint c_total = 0;\nint d_total = 0;\nchar grid[N][N];\n\n// unmatched list\nvector<bool> matched;\nvector<int> um;\nvector<int> um_pos;\n\nvoid add_unmatched(int i) {\n    if (!matched[i]) return;\n    matched[i] = false;\n    um_pos[i] = (int)um.size();\n    um.push_back(i);\n}\nvoid remove_unmatched(int i) {\n    if (matched[i]) return;\n    matched[i] = true;\n    int pos = um_pos[i];\n    int last = um.back();\n    um[pos] = last;\n    um_pos[last] = pos;\n    um.pop_back();\n}\n\nvoid rebuild_all() {\n    h_match.assign(M * N * N, 0);\n    v_match.assign(M * N * N, 0);\n    h_count.assign(M * N, 0);\n    v_count.assign(M * N, 0);\n    s_count.assign(M, 0);\n    c_total = d_total = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (grid[i][j] == '.') ++d_total;\n\n    for (int i = 0; i < M; ++i) {\n        int L = len[i];\n        const string& s = strs[i];\n        // horizontal\n        for (int r = 0; r < N; ++r)\n            for (int st = 0; st < N; ++st) {\n                int cnt = 0;\n                for (int k = 0; k < L; ++k)\n                    if (grid[r][(st+k)%N] == s[k]) ++cnt;\n                h_match[i*N*N + r*N + st] = cnt;\n                if (cnt == L) { ++h_count[i*N + r]; ++s_count[i]; }\n            }\n        // vertical\n        for (int c = 0; c < N; ++c)\n            for (int st = 0; st < N; ++st) {\n                int cnt = 0;\n                for (int k = 0; k < L; ++k)\n                    if (grid[(st+k)%N][c] == s[k]) ++cnt;\n                v_match[i*N*N + c*N + st] = cnt;\n                if (cnt == L) { ++v_count[i*N + c]; ++s_count[i]; }\n            }\n        if (s_count[i] > 0) ++c_total;\n    }\n    matched.assign(M, false);\n    um.clear();\n    um_pos.assign(M, -1);\n    for (int i = 0; i < M; ++i) {\n        if (s_count[i] > 0) { matched[i] = true; }\n        else { um_pos[i] = (int)um.size(); um.push_back(i); }\n    }\n}\n\nvoid set_cell(int r, int c, char nc) {\n    char oc = grid[r][c];\n    if (oc == nc) return;\n    if (oc == '.') --d_total;\n    if (nc == '.') ++d_total;\n\n    for (int i = 0; i < M; ++i) {\n        int L = len[i];\n        const string& s = strs[i];\n        // horizontal\n        int h_base = i*N*N + r*N;\n        for (int off = 0; off < L; ++off) {\n            int st = (c - off + N) % N;\n            int idx = h_base + st;\n            if (oc == s[off] && nc != s[off]) {\n                if (--h_match[idx] == L-1) {\n                    --h_count[i*N + r];\n                    if (--s_count[i] == 0) { --c_total; add_unmatched(i); }\n                }\n            } else if (oc != s[off] && nc == s[off]) {\n                if (++h_match[idx] == L) {\n                    ++h_count[i*N + r];\n                    if (++s_count[i] == 1) { ++c_total; remove_unmatched(i); }\n                }\n            }\n        }\n        // vertical\n        int v_base = i*N*N + c*N;\n        for (int off = 0; off < L; ++off) {\n            int st = (r - off + N) % N;\n            int idx = v_base + st;\n            if (oc == s[off] && nc != s[off]) {\n                if (--v_match[idx] == L-1) {\n                    --v_count[i*N + c];\n                    if (--s_count[i] == 0) { --c_total; add_unmatched(i); }\n                }\n            } else if (oc != s[off] && nc == s[off]) {\n                if (++v_match[idx] == L) {\n                    ++v_count[i*N + c];\n                    if (++s_count[i] == 1) { ++c_total; remove_unmatched(i); }\n                }\n            }\n        }\n    }\n    grid[r][c] = nc;\n}\n\nint count_matched(const char g[N][N]) {\n    int cnt = 0;\n    for (int i = 0; i < M; ++i) {\n        const string& s = strs[i];\n        int L = len[i];\n        bool found = false;\n        for (int r = 0; r < N && !found; ++r)\n            for (int st = 0; st < N && !found; ++st) {\n                bool ok = true;\n                for (int k = 0; k < L; ++k)\n                    if (g[r][(st+k)%N] != s[k]) { ok = false; break; }\n                if (ok) found = true;\n            }\n        for (int c = 0; c < N && !found; ++c)\n            for (int st = 0; st < N && !found; ++st) {\n                bool ok = true;\n                for (int k = 0; k < L; ++k)\n                    if (g[(st+k)%N][c] != s[k]) { ok = false; break; }\n                if (ok) found = true;\n            }\n        if (found) ++cnt;\n    }\n    return cnt;\n}\n\n// ---- greedy construction ----\nvoid greedy_construction(char best_grid[N][N], int& best_c, XorShift& rng,\n                         double time_limit, steady_clock::time_point start_time) {\n    auto get_time = [&]() {\n        return duration<double>(steady_clock::now() - start_time).count();\n    };\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n\n    char cur[N][N];\n    best_c = -1;\n    int best_d = 0;\n\n    struct Placement{ int ori, rc, start, overlap; };\n    vector<Placement> valid; valid.reserve(800);\n\n    while (get_time() < time_limit) {\n        memset(cur, '.', sizeof(cur));\n        for (int i = M-1; i > 0; --i) swap(order[i], order[rng.nextInt(i+1)]);\n\n        for (int idx : order) {\n            const string& s = strs[idx];\n            int L = len[idx];\n            valid.clear();\n            for (int r = 0; r < N; ++r)\n                for (int st = 0; st < N; ++st) {\n                    int overlap = 0; bool ok = true;\n                    for (int k = 0; k < L; ++k) {\n                        char cell = cur[r][(st+k)%N];\n                        if (cell != '.' && cell != s[k]) { ok = false; break; }\n                        if (cell != '.') ++overlap;\n                    }\n                    if (ok) valid.push_back({0, r, st, overlap});\n                }\n            for (int c = 0; c < N; ++c)\n                for (int st = 0; st < N; ++st) {\n                    int overlap = 0; bool ok = true;\n                    for (int k = 0; k < L; ++k) {\n                        char cell = cur[(st+k)%N][c];\n                        if (cell != '.' && cell != s[k]) { ok = false; break; }\n                        if (cell != '.') ++overlap;\n                    }\n                    if (ok) valid.push_back({1, c, st, overlap});\n                }\n            if (valid.empty()) continue;\n            int maxo = -1;\n            for (auto& p : valid) if (p.overlap > maxo) maxo = p.overlap;\n            vector<Placement*> cand;\n            for (auto& p : valid) if (p.overlap == maxo) cand.push_back(&p);\n            Placement& ch = *cand[rng.nextInt(cand.size())];\n            if (ch.ori == 0) for (int k = 0; k < L; ++k) cur[ch.rc][(ch.start+k)%N] = s[k];\n            else for (int k = 0; k < L; ++k) cur[(ch.start+k)%N][ch.rc] = s[k];\n        }\n        int actual_c = count_matched(cur);\n        int actual_d = 0;\n        for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) if (cur[i][j] == '.') ++actual_d;\n        if (actual_c > best_c || (actual_c == best_c && actual_d > best_d)) {\n            best_c = actual_c; best_d = actual_d;\n            memcpy(best_grid, cur, sizeof(cur));\n            if (best_c == M) break;\n        }\n    }\n}\n\n// small struct for SA change records\nstruct Change { int r, c; char old; };\n\nint main() {\n    ios::sync_with_stdio(false); cin.tie(0);\n    auto start = steady_clock::now();\n    auto get_time = [&]() { return duration<double>(steady_clock::now() - start).count(); };\n\n    // input\n    int dummy; cin >> dummy >> M;\n    strs.resize(M); len.resize(M);\n    for (int i = 0; i < M; ++i) { cin >> strs[i]; len[i] = strs[i].size(); }\n\n    XorShift rng((uint32_t)(steady_clock::now().time_since_epoch().count() & 0xFFFFFFFF));\n\n    // ---- greedy ----\n    double greedy_time = 0.5;\n    char best_greedy[N][N];\n    int greedy_c;\n    greedy_construction(best_greedy, greedy_c, rng, greedy_time, start);\n\n    memcpy(grid, best_greedy, sizeof(grid));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (grid[i][j] == '.') grid[i][j] = letters[rng.nextInt(LETTERS)];\n\n    rebuild_all();\n\n    char best_grid[N][N];\n    memcpy(best_grid, grid, sizeof(grid));\n    int best_c = c_total, best_d = d_total;\n\n    auto energy = [&](int c, int d) {\n        if (c < M) return (double)c;\n        return (double)M + (double)(N*N - d) / (N*N);\n    };\n    double cur_energy = energy(c_total, d_total);\n    double best_energy = cur_energy;\n\n    // ---- SA ----\n    double total_budget = 2.95;\n    double sa_start = get_time();\n    double sa_end = total_budget - 0.05; // leave room for dot optimisation\n\n    double T_start = 0.4, T_end = 0.0001;\n\n    while (get_time() < sa_end) {\n        double elapsed = get_time() - sa_start;\n        double progress = min(elapsed / (sa_end - sa_start), 1.0);\n        double T = T_start * pow(T_end / T_start, progress);\n\n        double rnd = rng.nextDouble();\n        if (!um.empty() && rnd < 0.15) {\n            // whole string placement\n            int i = um[rng.nextInt((int)um.size())];\n            int L = len[i];\n            const string& s = strs[i];\n            bool horiz = rng.nextInt(2);\n            int rc = rng.nextInt(N), st = rng.nextInt(N);\n            vector<Change> changes;\n            for (int k = 0; k < L; ++k) {\n                int r, c;\n                if (horiz) { r = rc; c = (st + k) % N; }\n                else { r = (st + k) % N; c = rc; }\n                if (grid[r][c] != s[k]) {\n                    changes.push_back({r, c, grid[r][c]});\n                    set_cell(r, c, s[k]);\n                }\n            }\n            if (changes.empty()) continue;\n            double new_energy = energy(c_total, d_total);\n            double delta = new_energy - cur_energy;\n            if (delta >= 0 || rng.nextDouble() < exp(delta / T)) {\n                cur_energy = new_energy;\n                if (new_energy > best_energy) {\n                    best_energy = new_energy;\n                    best_c = c_total; best_d = d_total;\n                    memcpy(best_grid, grid, sizeof(grid));\n                }\n            } else {\n                for (int j = (int)changes.size()-1; j >= 0; --j)\n                    set_cell(changes[j].r, changes[j].c, changes[j].old);\n            }\n        } else if (!um.empty() && rnd < 0.40) {\n            // targeted single cell\n            int i = um[rng.nextInt((int)um.size())];\n            int L = len[i];\n            const string& s = strs[i];\n            bool horiz = rng.nextInt(2);\n            int rc = rng.nextInt(N), st = rng.nextInt(N), off = rng.nextInt(L);\n            int r, c;\n            if (horiz) { r = rc; c = (st + off) % N; }\n            else { r = (st + off) % N; c = rc; }\n            char desired = s[off];\n            if (grid[r][c] == desired) continue;\n            char old = grid[r][c];\n            double old_energy = cur_energy;\n            set_cell(r, c, desired);\n            double new_energy = energy(c_total, d_total);\n            double delta = new_energy - old_energy;\n            if (delta >= 0 || rng.nextDouble() < exp(delta / T)) {\n                cur_energy = new_energy;\n                if (new_energy > best_energy) {\n                    best_energy = new_energy;\n                    best_c = c_total; best_d = d_total;\n                    memcpy(best_grid, grid, sizeof(grid));\n                }\n            } else set_cell(r, c, old);\n        } else {\n            // random cell flip\n            int r = rng.nextInt(N), c = rng.nextInt(N);\n            char cur_char = grid[r][c];\n            char nxt = rng.nextInt(9) == 0 ? '.' : letters[rng.nextInt(LETTERS)];\n            if (nxt == cur_char) continue;\n            double old_energy = cur_energy;\n            set_cell(r, c, nxt);\n            double new_energy = energy(c_total, d_total);\n            double delta = new_energy - old_energy;\n            if (delta >= 0 || rng.nextDouble() < exp(delta / T)) {\n                cur_energy = new_energy;\n                if (new_energy > best_energy) {\n                    best_energy = new_energy;\n                    best_c = c_total; best_d = d_total;\n                    memcpy(best_grid, grid, sizeof(grid));\n                }\n            } else set_cell(r, c, cur_char);\n        }\n        if (c_total == M) break;\n    }\n\n    // restore best\n    memcpy(grid, best_grid, sizeof(grid));\n    rebuild_all();\n\n    // ---- dot maximisation if all strings matched ----\n    if (c_total == M && get_time() < total_budget) {\n        bool changed = true;\n        for (int pass = 0; pass < 10 && changed && get_time() < total_budget; ++pass) {\n            changed = false;\n            vector<int> order(N*N);\n            iota(order.begin(), order.end(), 0);\n            for (int i = N*N-1; i > 0; --i) swap(order[i], order[rng.nextInt(i+1)]);\n            for (int idx : order) {\n                if (get_time() >= total_budget) break;\n                int r = idx / N, c = idx % N;\n                if (grid[r][c] == '.') continue;\n                char old = grid[r][c];\n                set_cell(r, c, '.');\n                if (c_total == M) changed = true;\n                else set_cell(r, c, old);\n            }\n        }\n        memcpy(best_grid, grid, sizeof(grid));\n    }\n\n    // output\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    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int INF = 1e9;\n\n// Dial's algorithm (weights 5..9)\nvoid dial(const vector<vector<pair<int, int>>> &adj, int src,\n          vector<int> &dist, vector<int> &prev) {\n    int n = (int)adj.size();\n    dist.assign(n, INF);\n    prev.assign(n, -1);\n    dist[src] = 0;\n    vector<queue<int>> buckets(10);\n    buckets[0].push(src);\n    int cur = 0, mx = 0;\n    while (cur <= mx) {\n        int idx = cur % 10;\n        if (!buckets[idx].empty()) {\n            int u = buckets[idx].front();\n            buckets[idx].pop();\n            if (dist[u] < cur) continue;\n            for (auto &p : adj[u]) {\n                int v = p.first, w = p.second;\n                int nd = cur + w;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    prev[v] = u;\n                    buckets[nd % 10].push(v);\n                    if (nd > mx) mx = nd;\n                }\n            }\n        } else {\n            ++cur;\n        }\n    }\n}\n\nint main() {\n    auto start = chrono::steady_clock::now();\n    auto time_ok = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count() < 2.9;\n    };\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int N, si, sj;\n    cin >> N >> si >> sj;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n\n    // --- map cells to IDs ---\n    vector<vector<int>> id(N, vector<int>(N, -1));\n    vector<pair<int, int>> cells;\n    vector<int> cost_cell;\n    int road_cnt = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (grid[i][j] != '#') {\n                id[i][j] = road_cnt++;\n                cells.push_back({i, j});\n                cost_cell.push_back(grid[i][j] - '0');\n            }\n\n    // --- adjacency ---\n    vector<vector<pair<int, int>>> adj(road_cnt);\n    const int di[4] = {-1, 1, 0, 0};\n    const int dj[4] = {0, 0, -1, 1};\n    for (int u = 0; u < road_cnt; ++u) {\n        int i = cells[u].first, j = cells[u].second;\n        for (int d = 0; d < 4; ++d) {\n            int ni = i + di[d], nj = j + dj[d];\n            if (ni >= 0 && ni < N && nj >= 0 && nj < N && id[ni][nj] != -1) {\n                int v = id[ni][nj];\n                adj[u].push_back({v, cost_cell[v]});\n            }\n        }\n    }\n\n    // --- horizontal segments ---\n    vector<int> h_id(road_cnt, -1);\n    vector<vector<int>> h_segs;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N;) {\n            if (id[i][j] != -1) {\n                int st = j;\n                while (j < N && id[i][j] != -1) ++j;\n                vector<int> seg;\n                for (int jj = st; jj < j; ++jj) seg.push_back(id[i][jj]);\n                for (int u : seg) h_id[u] = (int)h_segs.size();\n                h_segs.push_back(seg);\n            } else ++j;\n        }\n    }\n    int H = (int)h_segs.size();\n\n    // --- vertical segments ---\n    vector<int> v_id(road_cnt, -1);\n    vector<vector<int>> v_segs;\n    for (int j = 0; j < N; ++j) {\n        for (int i = 0; i < N;) {\n            if (id[i][j] != -1) {\n                int st = i;\n                while (i < N && id[i][j] != -1) ++i;\n                vector<int> seg;\n                for (int ii = st; ii < i; ++ii) seg.push_back(id[ii][j]);\n                for (int u : seg) v_id[u] = (int)v_segs.size();\n                v_segs.push_back(seg);\n            } else ++i;\n        }\n    }\n    int V = (int)v_segs.size();\n    int S = H + V;   // total segments\n\n    // segment indices of a road cell\n    auto seg_of = [&](int u) -> array<int, 2> {\n        return {h_id[u], (v_id[u] == -1 ? -1 : H + v_id[u])};\n    };\n\n    // --- candidate waypoints ---\n    int start_cell = id[si][sj];\n    vector<int> cand;\n    cand.push_back(start_cell);\n    set<int> used;\n    used.insert(start_cell);\n    for (auto &seg : h_segs) {\n        for (int u : {seg.front(), seg.back(), seg[seg.size() / 2]}) {\n            if (used.insert(u).second) cand.push_back(u);\n        }\n    }\n    for (auto &seg : v_segs) {\n        for (int u : {seg.front(), seg.back(), seg[seg.size() / 2]}) {\n            if (used.insert(u).second) cand.push_back(u);\n        }\n    }\n    int Psz = (int)cand.size();\n    vector<array<int, 2>> cand_segs(Psz);\n    for (int i = 0; i < Psz; ++i) cand_segs[i] = seg_of(cand[i]);\n\n    // distance from start (tiebreaker)\n    vector<int> dist_start, dummy_prev;\n    dial(adj, start_cell, dist_start, dummy_prev);\n\n    int start_idx = find(cand.begin(), cand.end(), start_cell) - cand.begin();\n\n    // --- greedy set cover ---\n    vector<bool> cov_seg(S, false);\n    if (h_id[start_cell] != -1) cov_seg[h_id[start_cell]] = true;\n    if (v_id[start_cell] != -1) cov_seg[H + v_id[start_cell]] = true;\n    int uncovered = 0;\n    for (bool b : cov_seg) if (!b) ++uncovered;\n\n    vector<int> chosen;\n    vector<bool> in_chosen(Psz, false);\n    chosen.push_back(start_idx);\n    in_chosen[start_idx] = true;\n\n    while (uncovered > 0) {\n        int best_gain = 0, best_i = -1, best_d = INF;\n        for (int i = 0; i < Psz; ++i) {\n            if (in_chosen[i]) continue;\n            int gain = 0;\n            for (int seg : cand_segs[i])\n                if (seg != -1 && !cov_seg[seg]) ++gain;\n            if (gain == 0) continue;\n            int d = dist_start[cand[i]];\n            if (gain > best_gain || (gain == best_gain && d < best_d)) {\n                best_gain = gain;\n                best_d = d;\n                best_i = i;\n            }\n        }\n        if (best_i == -1) break;\n        chosen.push_back(best_i);\n        in_chosen[best_i] = true;\n        for (int seg : cand_segs[best_i]) {\n            if (seg != -1 && !cov_seg[seg]) {\n                cov_seg[seg] = true;\n                --uncovered;\n            }\n        }\n    }\n\n    // --- remove redundant waypoints (purely by segment coverage) ---\n    bool altered = true;\n    while (altered) {\n        altered = false;\n        for (size_t i = 0; i < chosen.size(); ++i) {\n            if (chosen[i] == start_idx) continue;\n            vector<bool> cov(S, false);\n            for (size_t j = 0; j < chosen.size(); ++j)\n                if (i != j)\n                    for (int seg : cand_segs[chosen[j]])\n                        if (seg != -1) cov[seg] = true;\n            bool needed = false;\n            for (int seg : cand_segs[chosen[i]])\n                if (seg != -1 && !cov[seg]) { needed = true; break; }\n            if (!needed) {\n                chosen.erase(chosen.begin() + i);\n                altered = true;\n                break;\n            }\n        }\n    }\n\n    vector<int> W;\n    for (int idx : chosen) W.push_back(cand[idx]);\n    int K = (int)W.size();\n    auto it = find(W.begin(), W.end(), start_cell);\n    if (it != W.end()) swap(W[0], *it);\n    if (K == 1) { cout << \"\" << \"\\n\"; return 0; }\n\n    // --- all-pairs distances ---\n    vector<vector<int>> D(K, vector<int>(K, 0));\n    for (int i = 0; i < K; ++i) {\n        vector<int> dist, prv;\n        dial(adj, W[i], dist, prv);\n        for (int j = 0; j < K; ++j) D[i][j] = dist[W[j]];\n    }\n\n    // --- initial tour: cheapest insertion ---\n    vector<int> tour(K);\n    vector<bool> in_tour(K, false);\n    tour[0] = 0;\n    in_tour[0] = true;\n    for (int t = 1; t < K; ++t) {\n        int best_v = -1, best_pos = -1, best_inc = INF;\n        for (int v = 1; v < K; ++v) {\n            if (in_tour[v]) continue;\n            for (int i = 0; i < t; ++i) {\n                int u = tour[i];\n                int w = tour[(i + 1) % t];\n                int inc = D[u][v] + D[v][w] - D[u][w];\n                if (inc < best_inc) {\n                    best_inc = inc;\n                    best_v = v;\n                    best_pos = i + 1;\n                }\n            }\n        }\n        for (int i = t; i > best_pos; --i) tour[i] = tour[i - 1];\n        tour[best_pos] = best_v;\n        in_tour[best_v] = true;\n    }\n\n    // --- local search: Or-opt + 2-opt ---\n    auto apply_or = [&]() -> bool {\n        int best_delta = 0, best_i = -1, best_j = -1;\n        for (int i = 1; i < K; ++i) {\n            int prev = (i - 1 + K) % K;\n            int next = (i + 1) % K;\n            int node = tour[i];\n            for (int j = 0; j < K; ++j) {\n                if (j == i || j == i - 1) continue;\n                int nextj = (j + 1) % K;\n                int delta = -D[tour[prev]][node] - D[node][tour[next]] - D[tour[j]][tour[nextj]]\n                            + D[tour[prev]][tour[next]] + D[tour[j]][node] + D[node][tour[nextj]];\n                if (delta < best_delta) {\n                    best_delta = delta;\n                    best_i = i;\n                    best_j = j;\n                }\n            }\n        }\n        if (best_delta >= 0) return false;\n        int node = tour[best_i];\n        if (best_j > best_i) {\n            tour.erase(tour.begin() + best_i);\n            tour.insert(tour.begin() + best_j, node);\n        } else {\n            tour.erase(tour.begin() + best_i);\n            tour.insert(tour.begin() + best_j + 1, node);\n        }\n        return true;\n    };\n\n    auto apply_2opt = [&]() -> bool {\n        // prefix sums for fast delta computation\n        vector<int> pref_fwd(K + 1), pref_rev(K + 1);\n        for (int i = 0; i < K; ++i) {\n            int nxt = (i + 1) % K;\n            pref_fwd[i + 1] = pref_fwd[i] + D[tour[i]][tour[nxt]];\n            pref_rev[i + 1] = pref_rev[i] + D[tour[nxt]][tour[i]];\n        }\n        int best_delta = 0, best_i = -1, best_j = -1;\n        for (int i = 0; i < K; ++i) {\n            for (int j = i + 2; j < K; ++j) {\n                if (i == 0 && j == K - 1) continue; // full reversal\n                int nxt_i = (i + 1) % K; // == i+1 as i < K-1, but safe\n                int nxt_j = (j + 1) % K;\n                int orig_seg = pref_fwd[j] - pref_fwd[nxt_i]; // edges i+1 -> ... -> j\n                int rev_seg = pref_rev[j] - pref_rev[nxt_i]; // reversed\n                int removed1 = D[tour[i]][tour[nxt_i]];\n                int removed2 = D[tour[j]][tour[nxt_j]];\n                int added1 = D[tour[i]][tour[j]];\n                int added2 = D[tour[nxt_i]][tour[nxt_j]];\n                int delta = added1 + rev_seg + added2 - orig_seg - removed1 - removed2;\n                if (delta < best_delta) {\n                    best_delta = delta;\n                    best_i = i;\n                    best_j = j;\n                }\n            }\n        }\n        if (best_delta >= 0) return false;\n        reverse(tour.begin() + best_i + 1, tour.begin() + best_j + 1);\n        return true;\n    };\n\n    while (time_ok()) {\n        bool improved = false;\n        improved |= apply_or();\n        improved |= apply_2opt();\n        if (!improved) break;\n    }\n\n    // --- output ---\n    string ans;\n    ans.reserve(1'000'000);\n    for (int step = 0; step < K; ++step) {\n        int u = W[tour[step]];\n        int v = W[tour[(step + 1) % K]];\n        vector<int> dist, prv;\n        dial(adj, u, dist, prv);\n        vector<int> path;\n        for (int cur = v; cur != u; cur = prv[cur]) path.push_back(cur);\n        path.push_back(u);\n        reverse(path.begin(), path.end());\n        for (size_t k = 0; k + 1 < path.size(); ++k) {\n            int ci = cells[path[k]].first, cj = cells[path[k]].second;\n            int ni = cells[path[k + 1]].first, nj = cells[path[k + 1]].second;\n            if (ni < ci) ans.push_back('U');\n            else if (ni > ci) ans.push_back('D');\n            else if (nj < cj) ans.push_back('L');\n            else ans.push_back('R');\n        }\n    }\n    cout << ans << \"\\n\";\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <climits>\n#include <cmath>\n#include <cstring>\nusing namespace std;\n\nstruct Obs {\n    int task;\n    int L;   // lower bound on w\n    int U;   // upper bound on w\n};\n\nint N, M, K, R;\nvector<vector<int>> d;           // task difficulties\nvector<vector<int>> out_edges;   // dependents of each task\nvector<int> height;              // longest path to sink (inclusive)\nint max_height;\n\nvector<int> task_status;         // 0: not started, 1: in progress, 2: completed\nvector<int> req_remaining;       // number of unfinished prerequisites\nvector<int> worker_task;         // current task of worker, -1 if free\nvector<int> worker_start;        // day the worker started the current task\n\nvector<vector<Obs>> obs;         // observations per worker\nvector<vector<int>> LB, UB;      // current skill bounds per worker\n\n// Tighten skill bounds for a single worker using all its observations.\nvoid update_bounds(int w) {\n    vector<int> &lb = LB[w];\n    vector<int> &ub = UB[w];\n    bool changed = true;\n    int iter = 0;\n    while (changed && iter < 20) {\n        changed = false;\n        ++iter;\n        for (const auto &ob : obs[w]) {\n            int ti = ob.task;\n            int L = ob.L;\n            int U = ob.U;\n            // Lower bounds from upper bound on w\n            for (int k = 0; k < K; ++k) {\n                int cand = d[ti][k] - U;\n                if (cand > lb[k]) {\n                    lb[k] = min(cand, ub[k]);\n                    changed = true;\n                }\n            }\n            // Upper bounds from lower bound on w\n            vector<int> sum_others_max(K, 0);\n            for (int k = 0; k < K; ++k) {\n                int s = 0;\n                for (int j = 0; j < K; ++j) {\n                    if (j == k) continue;\n                    s += max(0, d[ti][j] - lb[j]);\n                }\n                sum_others_max[k] = s;\n            }\n            for (int k = 0; k < K; ++k) {\n                if (L > sum_others_max[k]) {\n                    int cand = d[ti][k] - (L - sum_others_max[k]);\n                    if (cand < ub[k]) {\n                        ub[k] = max(cand, lb[k]);\n                        changed = true;\n                    }\n                }\n            }\n        }\n    }\n}\n\n// Estimate the deterministic part w = sum max(0, d - s) for worker w on task idx.\nint w_estimate(int w, int idx) {\n    const vector<int> &lb = LB[w];\n    const vector<int> &ub = UB[w];\n    double r = 0.0;\n    if (max_height > 1) {\n        r = (double)(height[idx] - 1) / (max_height - 1);\n    }\n    int w_val = 0;\n    for (int k = 0; k < K; ++k) {\n        double s_blend = lb[k] + (ub[k] - lb[k]) * (1.0 - r);\n        int s_est = (int)round(s_blend);\n        int def = d[idx][k] - s_est;\n        if (def > 0) w_val += def;\n    }\n    return w_val;\n}\n\n// Expected duration (same as w_val if >0, else 1)\nint estimate_duration(int w, int idx) {\n    int wv = w_estimate(w, idx);\n    return (wv == 0) ? 1 : wv;\n}\n\n// Hungarian algorithm for minimum cost assignment (square matrix).\n// Returns vector assign such that assign[row] = column.\nvector<int> hungarian(const vector<vector<int>> &cost) {\n    int n = (int)cost.size();\n    vector<int> u(n + 1), v(n + 1), p(n + 1), way(n + 1);\n    for (int i = 1; i <= n; ++i) {\n        p[0] = i;\n        int j0 = 0;\n        vector<int> minv(n + 1, INT_MAX);\n        vector<char> used(n + 1, 0);\n        do {\n            used[j0] = 1;\n            int i0 = p[j0], delta = INT_MAX, j1 = 0;\n            for (int j = 1; j <= n; ++j) {\n                if (!used[j]) {\n                    int cur = cost[i0 - 1][j - 1] - u[i0] - v[j];\n                    if (cur < minv[j]) {\n                        minv[j] = cur;\n                        way[j] = j0;\n                    }\n                    if (minv[j] < delta) {\n                        delta = minv[j];\n                        j1 = j;\n                    }\n                }\n            }\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    vector<int> assign(n);\n    for (int j = 1; j <= n; ++j) {\n        assign[p[j] - 1] = j - 1;\n    }\n    return assign;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> M >> K >> R;\n    d.resize(N, vector<int>(K));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < K; ++j)\n            cin >> d[i][j];\n    \n    out_edges.resize(N);\n    vector<int> indegree(N, 0);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        out_edges[u].push_back(v);\n        indegree[v]++;\n    }\n    \n    // Static height = longest path to a sink (inclusive)\n    height.resize(N);\n    max_height = 0;\n    for (int i = N - 1; i >= 0; --i) {\n        int best = 0;\n        for (int v : out_edges[i]) best = max(best, height[v]);\n        height[i] = best + 1;\n        max_height = max(max_height, height[i]);\n    }\n    \n    task_status.assign(N, 0);\n    req_remaining = indegree;\n    worker_task.assign(M, -1);\n    worker_start.assign(M, -1);\n    obs.resize(M);\n    LB.assign(M, vector<int>(K, 0));\n    UB.assign(M, vector<int>(K, 200));   // tighter upper bound\n    \n    int day = 1;\n    \n    while (true) {\n        // Collect free workers\n        vector<int> free;\n        for (int w = 0; w < M; ++w)\n            if (worker_task[w] == -1) free.push_back(w);\n        \n        // Collect ready tasks\n        vector<int> ready;\n        for (int i = 0; i < N; ++i)\n            if (task_status[i] == 0 && req_remaining[i] == 0)\n                ready.push_back(i);\n        \n        // Sort by descending height, then by index\n        sort(ready.begin(), ready.end(), [&](int a, int b) {\n            if (height[a] != height[b]) return height[a] > height[b];\n            return a < b;\n        });\n        \n        int W = (int)free.size();\n        int T = (int)ready.size();\n        vector<pair<int,int>> today;   // (worker, task)\n        \n        if (W > 0 && T > 0) {\n            if (T <= W) {\n                // Fewer ready tasks than free workers: assign each task to its best worker\n                vector<char> used(M, 0);\n                for (int t : ready) {\n                    int best_w = -1, best_val = INT_MAX;\n                    for (int w : free) {\n                        if (used[w]) continue;\n                        int val = estimate_duration(w, t);\n                        if (val < best_val) {\n                            best_val = val;\n                            best_w = w;\n                        }\n                    }\n                    if (best_w != -1) {\n                        today.push_back({best_w, t});\n                        used[best_w] = 1;\n                    }\n                }\n            } else {\n                // More ready tasks than free workers: select top W tasks and use Hungarian\n                vector<int> sel(ready.begin(), ready.begin() + W);\n                // Build cost matrix W x W\n                vector<vector<int>> cost(W, vector<int>(W));\n                for (int i = 0; i < W; ++i) {\n                    int w = free[i];\n                    for (int j = 0; j < W; ++j) {\n                        cost[i][j] = estimate_duration(w, sel[j]);\n                    }\n                }\n                vector<int> assign = hungarian(cost);\n                for (int i = 0; i < W; ++i) {\n                    today.push_back({free[i], sel[assign[i]]});\n                }\n            }\n        }\n        \n        // Output assignments\n        cout << today.size();\n        for (auto &p : today) {\n            cout << \" \" << p.first + 1 << \" \" << p.second + 1;\n        }\n        cout << \"\\n\";\n        cout.flush();\n        \n        // Update state for started tasks\n        for (auto &p : today) {\n            int w = p.first, t = p.second;\n            worker_task[w] = t;\n            worker_start[w] = day;\n            task_status[t] = 1;\n        }\n        \n        // Read completions\n        int n;\n        cin >> n;\n        if (n == -1) break;\n        vector<int> finished(n);\n        for (int i = 0; i < n; ++i) {\n            cin >> finished[i];\n            --finished[i];\n        }\n        \n        // Process completions\n        for (int w : finished) {\n            int t = worker_task[w];\n            int start = worker_start[w];\n            int t_actual = day - start + 1;\n            int L, U;\n            if (t_actual == 1) {\n                L = 0;\n                U = 4;\n            } else {\n                L = max(1, t_actual - 3);\n                U = t_actual + 3;\n            }\n            obs[w].push_back({t, L, U});\n            \n            // Update bounds for this worker\n            update_bounds(w);\n            \n            task_status[t] = 2;\n            for (int v : out_edges[t]) {\n                --req_remaining[v];\n            }\n            worker_task[w] = -1;\n            worker_start[w] = -1;\n        }\n        \n        ++day;\n        if (day > 2000) break;\n    }\n    \n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct InsertResult {\n    int cost, i, j;\n};\n\nint main() {\n    auto start_time = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration_cast<chrono::milliseconds>(\n                   chrono::steady_clock::now() - start_time)\n            .count();\n    };\n\n    // ---------- input ----------\n    constexpr int N = 1000;\n    vector<int> ax(N), ay(N), cx(N), cy(N);\n    for (int i = 0; i < N; ++i)\n        cin >> ax[i] >> ay[i] >> cx[i] >> cy[i];\n\n    // ---------- coordinates and distances ----------\n    constexpr int V = 2 * N + 1;           // 2001\n    vector<int> X(V), Y(V);\n    X[0] = 400; Y[0] = 400;\n    for (int i = 0; i < N; ++i) {\n        X[2 * i + 1] = ax[i]; Y[2 * i + 1] = ay[i];\n        X[2 * i + 2] = cx[i]; Y[2 * i + 2] = cy[i];\n    }\n    vector<int> D(V * V);\n    for (int i = 0; i < V; ++i)\n        for (int j = 0; j < V; ++j)\n            D[i * V + j] = abs(X[i] - X[j]) + abs(Y[i] - Y[j]);\n    auto dist = [&](int u, int v) { return D[u * V + v]; };\n\n    // ---------- route total length ----------\n    auto calc_total = [&](const vector<int>& s) {\n        if (s.empty()) return 0;\n        int tot = dist(0, s[0]);\n        for (size_t i = 0; i + 1 < s.size(); ++i)\n            tot += dist(s[i], s[i + 1]);\n        tot += dist(s.back(), 0);\n        return tot;\n    };\n\n    // ---------- evaluate insertion of order o into sequence s ----------\n    auto eval_ins = [&](const vector<int>& s, int o) -> InsertResult {\n        int L = (int)s.size();\n        int P = 2 * o + 1, D_ = 2 * o + 2;\n        int best_cost = INT_MAX, best_i = -1, best_j = -1;\n        for (int i = 0; i <= L; ++i) {\n            int prev_i = (i == 0 ? 0 : s[i - 1]);\n            int next_i = (i == L ? 0 : s[i]);\n            int base_i = dist(prev_i, next_i);\n            // P and D consecutive\n            int cost_pd = dist(prev_i, P) + dist(P, D_) + dist(D_, next_i) - base_i;\n            if (cost_pd < best_cost) {\n                best_cost = cost_pd;\n                best_i = best_j = i;\n            }\n            int inc_P = dist(prev_i, P) + dist(P, next_i) - base_i;\n            for (int j = i + 1; j <= L; ++j) {\n                int prev_j = s[j - 1];\n                int next_j = (j == L ? 0 : s[j]);\n                int inc_D = dist(prev_j, D_) + dist(D_, next_j) - dist(prev_j, next_j);\n                int cost = inc_P + inc_D;\n                if (cost < best_cost) {\n                    best_cost = cost;\n                    best_i = i;\n                    best_j = j;\n                }\n            }\n        }\n        return {best_cost, best_i, best_j};\n    };\n\n    // ---------- apply insertion ----------\n    auto apply_ins = [&](vector<int>& s, int o, int i, int j) {\n        int P = 2 * o + 1, D_ = 2 * o + 2;\n        vector<int> ns;\n        ns.reserve(s.size() + 2);\n        for (int pos = 0; pos <= (int)s.size(); ++pos) {\n            if (pos == i && pos == j) {\n                ns.push_back(P);\n                ns.push_back(D_);\n            } else {\n                if (pos == i) ns.push_back(P);\n                if (pos == j) ns.push_back(D_);\n            }\n            if (pos < (int)s.size()) ns.push_back(s[pos]);\n        }\n        s = move(ns);\n    };\n\n    auto remove_order_seq = [&](vector<int>& s, int o) {\n        int P = 2 * o + 1, D_ = 2 * o + 2;\n        s.erase(remove(s.begin(), s.end(), P), s.end());\n        s.erase(remove(s.begin(), s.end(), D_), s.end());\n    };\n\n    // ---------- local search on the route (fixed selection) ----------\n    auto improve_route = [&](vector<int>& seq, vector<int>& sel, int& T) {\n        bool improved = true;\n        int pass = 0;\n        while (improved && pass < 10 && elapsed() < 1950) {\n            improved = false;\n            // 1) re\u2011insert whole order\n            for (int o : sel) {\n                vector<int> temp_s = seq;\n                remove_order_seq(temp_s, o);\n                int T_wo = calc_total(temp_s);\n                auto res = eval_ins(temp_s, o);\n                int delta = T_wo + res.cost - T;\n                if (delta < 0) {\n                    seq = move(temp_s);\n                    apply_ins(seq, o, res.i, res.j);\n                    T = T_wo + res.cost;\n                    improved = true;\n                    break;\n                }\n            }\n            if (improved) continue;\n\n            // 2) relocate a single node (preserving precedence)\n            int L = (int)seq.size();\n            for (int idx = 0; idx < L; ++idx) {\n                int node = seq[idx];\n                bool pickup = (node % 2 == 1);\n                int other_node = pickup ? node + 1 : node - 1;\n                int other_idx = -1;\n                for (int k = 0; k < L; ++k)\n                    if (seq[k] == other_node) { other_idx = k; break; }\n                vector<int> temp_s = seq;\n                temp_s.erase(temp_s.begin() + idx);\n                int other_temp = (other_idx > idx) ? other_idx - 1 : other_idx;\n                int best_delta = 0, best_pos = -1;\n                for (int pos = 0; pos <= (int)temp_s.size(); ++pos) {\n                    if (pickup && pos > other_temp) continue;\n                    if (!pickup && pos <= other_temp) continue;\n                    int prv = (pos == 0 ? 0 : temp_s[pos - 1]);\n                    int nxt = (pos == (int)temp_s.size() ? 0 : temp_s[pos]);\n                    int delta = dist(prv, node) + dist(node, nxt) - dist(prv, nxt);\n                    if (delta < best_delta) {\n                        best_delta = delta;\n                        best_pos = pos;\n                    }\n                }\n                if (best_delta < 0) {\n                    temp_s.insert(temp_s.begin() + best_pos, node);\n                    seq = move(temp_s);\n                    T += best_delta;\n                    improved = true;\n                    break;\n                }\n            }\n            if (improved) continue;\n\n            // 3) 2\u2011opt (reverse segment) with precedence check\n            vector<int> pos(V, -1);\n            for (int k = 0; k < L; ++k) pos[seq[k]] = k;\n            int best_delta = 0, best_i = -1, best_j = -1;\n            for (int i = 0; i < L; ++i) {\n                for (int j = i + 1; j < L; ++j) {\n                    bool feasible = true;\n                    for (int o : sel) {\n                        int p = pos[2 * o + 1], d = pos[2 * o + 2];\n                        if (p >= i && p <= j && d >= i && d <= j) {\n                            feasible = false;\n                            break;\n                        }\n                    }\n                    if (!feasible) continue;\n                    int prev_i = (i == 0 ? 0 : seq[i - 1]);\n                    int next_j = (j == L - 1 ? 0 : seq[j + 1]);\n                    int delta = dist(prev_i, seq[j]) + dist(seq[i], next_j) -\n                                dist(prev_i, seq[i]) - dist(seq[j], next_j);\n                    if (delta < best_delta) {\n                        best_delta = delta;\n                        best_i = i;\n                        best_j = j;\n                    }\n                }\n            }\n            if (best_delta < 0) {\n                reverse(seq.begin() + best_i, seq.begin() + best_j + 1);\n                T += best_delta;\n                improved = true;\n            }\n            ++pass;\n        }\n    };\n\n    // ---------- initial solution: farthest insertion ----------\n    vector<int> seq;\n    vector<bool> flag(N, false);\n    vector<int> sel;\n    for (int step = 0; step < 50; ++step) {\n        int best_o = -1, best_cost = -1;\n        InsertResult best_res;\n        for (int o = 0; o < N; ++o) {\n            if (flag[o]) continue;\n            auto res = eval_ins(seq, o);\n            if (res.cost > best_cost) {\n                best_cost = res.cost;\n                best_o = o;\n                best_res = res;\n            }\n        }\n        apply_ins(seq, best_o, best_res.i, best_res.j);\n        flag[best_o] = true;\n        sel.push_back(best_o);\n    }\n    int T = calc_total(seq);\n    improve_route(seq, sel, T);\n\n    // ---------- store global best ----------\n    vector<int> best_seq = seq;\n    vector<bool> best_flag = flag;\n    vector<int> best_sel = sel;\n    int best_T = T;\n\n    // ---------- simulated annealing ----------\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> rnd_idx(0, 49);\n    uniform_int_distribution<int> rnd_order(0, N - 1);\n    uniform_real_distribution<double> rnd_prob(0.0, 1.0);\n    auto last_improve = chrono::steady_clock::now();\n\n    while (elapsed() < 1900) {\n        double temp = 300.0 * (1.0 - elapsed() / 2000.0) + 0.1;\n\n        int idx = rnd_idx(rng) % sel.size();\n        int o_sel = sel[idx];\n        int o_unsel;\n        do { o_unsel = rnd_order(rng); } while (flag[o_unsel]);\n\n        vector<int> temp_s = seq;\n        remove_order_seq(temp_s, o_sel);\n        int T_wo = calc_total(temp_s);\n        auto res = eval_ins(temp_s, o_unsel);\n        int delta = T_wo + res.cost - T;\n\n        if (delta < 0 || exp(-delta / temp) > rnd_prob(rng)) {\n            seq = move(temp_s);\n            apply_ins(seq, o_unsel, res.i, res.j);\n            T = T_wo + res.cost;\n            flag[o_sel] = false;\n            flag[o_unsel] = true;\n            sel[idx] = o_unsel;\n\n            if (T < best_T) {\n                best_T = T;\n                best_seq = seq;\n                best_flag = flag;\n                best_sel = sel;\n            }\n        }\n\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - last_improve).count() > 200) {\n            improve_route(seq, sel, T);\n            last_improve = chrono::steady_clock::now();\n            if (T < best_T) {\n                best_T = T;\n                best_seq = seq;\n                best_flag = flag;\n                best_sel = sel;\n            }\n        }\n    }\n\n    // ---------- final polish on the best solution ----------\n    seq = best_seq; flag = best_flag; sel = best_sel; T = best_T;\n    int last_T = T;\n    do {\n        last_T = T;\n        improve_route(seq, sel, T);\n    } while (T < last_T && elapsed() < 1950);\n    if (T < best_T) {\n        best_T = T;\n        best_seq = seq;\n        best_sel = sel;\n    }\n\n    // ---------- output ----------\n    sort(best_sel.begin(), best_sel.end());\n    cout << 50;\n    for (int o : best_sel) cout << \" \" << o + 1;\n    cout << \"\\n\";\n    cout << best_seq.size() + 2;\n    cout << \" 400 400\";\n    for (int node : best_seq)\n        cout << \" \" << X[node] << \" \" << Y[node];\n    cout << \" 400 400\" << endl;\n\n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n#include <tuple>\n#include <queue>\n#include <unordered_map>\n#include <cstdint>\n#include <climits>\n\nusing namespace std;\n\nstruct DSU {\n    vector<int> parent, sz;\n    int comps;\n    DSU(int n) : parent(n), sz(n, 1), comps(n) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    DSU(const DSU& other) : parent(other.parent), sz(other.sz), comps(other.comps) {}\n    int find(int x) {\n        while (parent[x] != x) {\n            parent[x] = parent[parent[x]];\n            x = parent[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        parent[b] = a;\n        sz[a] += sz[b];\n        --comps;\n        return true;\n    }\n    bool same(int a, int b) { return find(a) == find(b); }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    constexpr int N = 400;\n    constexpr int M = 1995;\n    \n    // -------- read coordinates --------\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; ++i) cin >> x[i] >> y[i];\n    \n    // -------- read edge endpoints --------\n    vector<int> U(M), V(M);\n    for (int i = 0; i < M; ++i) cin >> U[i] >> V[i];\n    \n    // -------- rounded Euclidean distances --------\n    vector<int> d(M);\n    for (int i = 0; i < M; ++i) {\n        double dx = x[U[i]] - x[V[i]];\n        double dy = y[U[i]] - y[V[i]];\n        d[i] = (int)round(sqrt(dx * dx + dy * dy));\n    }\n    \n    // -------- XorShift random generator (for global MST prob) --------\n    uint32_t xs[4] = {123456789, 362436069, 521288629, 88675123};\n    auto xorshift = [&]() -> uint32_t {\n        uint32_t t = xs[0] ^ (xs[0] << 11);\n        xs[0] = xs[1];\n        xs[1] = xs[2];\n        xs[2] = xs[3];\n        xs[3] = xs[3] ^ (xs[3] >> 19) ^ t ^ (t >> 8);\n        return xs[3];\n    };\n    \n    // -------- Global MST probability via Monte Carlo --------\n    constexpr int NUM_SIM = 4000;\n    vector<int> mst_count(M, 0);\n    for (int sim = 0; sim < NUM_SIM; ++sim) {\n        vector<tuple<int, int, int, int>> sim_edges; // (l, u, v, idx)\n        sim_edges.reserve(M);\n        for (int i = 0; i < M; ++i) {\n            int range = 2 * d[i] + 1;\n            int l = d[i] + int(xorshift() % range);\n            sim_edges.emplace_back(l, U[i], V[i], i);\n        }\n        sort(sim_edges.begin(), sim_edges.end());\n        DSU dsu_sim(N);\n        for (auto [l, u, v, idx] : sim_edges) {\n            if (dsu_sim.unite(u, v)) {\n                mst_count[idx]++;\n            }\n        }\n    }\n    vector<double> prob(M);\n    for (int i = 0; i < M; ++i) {\n        prob[i] = (double)mst_count[i] / NUM_SIM;\n    }\n    \n    // -------- pre\u2011sort edges by d (for fast component\u2011graph construction) --------\n    vector<int> sorted_idx(M);\n    iota(sorted_idx.begin(), sorted_idx.end(), 0);\n    sort(sorted_idx.begin(), sorted_idx.end(), [&](int a, int b) {\n        return d[a] < d[b];\n    });\n    \n    // -------- online decision --------\n    DSU dsu(N);\n    \n    for (int i = 0; i < M; ++i) {\n        int l_i;\n        cin >> l_i;\n        int u = U[i], v = V[i];\n        \n        // already connected \u2192 safe to reject\n        if (dsu.same(u, v)) {\n            cout << 0 << endl;\n            continue;\n        }\n        \n        // very cheap edge \u2192 accept without further analysis\n        if (l_i <= d[i] * 1.1) {\n            dsu.unite(u, v);\n            cout << 1 << endl;\n            continue;\n        }\n        \n        int ru = dsu.find(u);\n        int rv = dsu.find(v);\n        \n        // -------- build component MST using future edges (weight = d) --------\n        unordered_map<int, int> comp_id;\n        for (int k = 0; k < N; ++k) {\n            int r = dsu.find(k);\n            if (comp_id.find(r) == comp_id.end()) {\n                int id = (int)comp_id.size();\n                comp_id[r] = id;\n            }\n        }\n        int total_comps = (int)comp_id.size();\n        vector<vector<pair<int, int>>> comp_tree(total_comps); // (neighbor comp, edge_index)\n        DSU comp_dsu(total_comps);\n        \n        int id_ru = comp_id[ru];\n        int id_rv = comp_id[rv];\n        bool connected_via_future = false;\n        \n        for (int idx : sorted_idx) {\n            if (idx <= i) continue;               // only future edges\n            int a = dsu.find(U[idx]);\n            int b = dsu.find(V[idx]);\n            if (a == b) continue;\n            int id_a = comp_id[a];\n            int id_b = comp_id[b];\n            if (comp_dsu.same(id_a, id_b)) continue;\n            comp_dsu.unite(id_a, id_b);\n            comp_tree[id_a].emplace_back(id_b, idx);\n            comp_tree[id_b].emplace_back(id_a, idx);\n            if (comp_dsu.same(id_ru, id_rv)) {\n                connected_via_future = true;\n                break;\n            }\n        }\n        \n        // forced acceptance: even using all future edges the components cannot be connected\n        if (!connected_via_future) {\n            dsu.unite(u, v);\n            cout << 1 << endl;\n            continue;\n        }\n        \n        // -------- extract the unique path between ru and rv in the component tree --------\n        vector<int> path_edges;\n        {\n            vector<int> parent(total_comps, -1);\n            vector<int> parent_edge(total_comps, -1);\n            queue<int> q;\n            q.push(id_ru);\n            parent[id_ru] = id_ru;\n            while (!q.empty()) {\n                int cur = q.front(); q.pop();\n                if (cur == id_rv) break;\n                for (auto [nxt, ei] : comp_tree[cur]) {\n                    if (parent[nxt] == -1) {\n                        parent[nxt] = cur;\n                        parent_edge[nxt] = ei;\n                        q.push(nxt);\n                    }\n                }\n            }\n            for (int cur = id_rv; cur != id_ru; cur = parent[cur]) {\n                path_edges.push_back(parent_edge[cur]);\n            }\n        }\n        \n        // -------- exact probability that alternative bottleneck >= l_i --------\n        double prod_smaller = 1.0;   // P(all future edges on the path < l_i)\n        bool definitely_better = false;\n        for (int ei : path_edges) {\n            if (l_i <= d[ei]) {\n                // The smallest possible length of ei is already >= l_i\n                definitely_better = true;\n                prod_smaller = 0.0;\n                break;\n            } else if (l_i > 3 * d[ei]) {\n                continue;   // always < l_i, factor = 1.0\n            } else {\n                double p_less = (double)(l_i - d[ei]) / (2.0 * d[ei] + 1.0);\n                prod_smaller *= p_less;\n            }\n        }\n        double p_better = 1.0 - prod_smaller;   // P(max >= l_i)\n        \n        // -------- dynamic acceptance threshold --------\n        double progress = (double)i / M;\n        int comps_now = dsu.comps;\n        int R = M - i - 1;\n        double urgency = (R > 0) ? (double)(comps_now - 1) / R : 1.0;\n        \n        double threshold = 0.7 - 0.2 * progress - 0.1 * urgency;\n        \n        // Adjust for global MST probability: important edges get lower threshold (easier to accept)\n        if (prob[i] > 0.7)        threshold -= 0.05;\n        else if (prob[i] < 0.3)   threshold += 0.05;\n        \n        // Adjust for observed cheapness of current edge\n        double ratio = (double)l_i / d[i];\n        if (ratio < 1.2)          threshold -= 0.06;\n        else if (ratio > 2.5)     threshold += 0.06;\n        else if (ratio > 2.0)     threshold += 0.03;\n        \n        // Adjust for path length: longer path -> alternative is more likely to be expensive ->\n        // we can be slightly more careful (higher threshold)\n        threshold += 0.01 * ((int)path_edges.size() - 1);\n        \n        // clamp to sensible range\n        if (threshold < 0.40) threshold = 0.40;\n        if (threshold > 0.85) threshold = 0.85;\n        \n        // -------- final decision --------\n        if (p_better >= threshold || definitely_better) {\n            dsu.unite(u, v);\n            cout << 1 << endl;\n        } else {\n            cout << 0 << endl;\n        }\n    }\n    \n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\n\nconst ll INF_CAP = 1e12;\n\n// ---------- Dinic for min-cut ----------\nstruct Dinic {\n    struct Edge { int to, rev; ll cap; };\n    vector<vector<Edge>> g;\n    vector<int> level, iter;\n    Dinic(int n) : g(n), level(n), iter(n) {}\n    void add_edge(int from, int to, ll cap) {\n        g[from].push_back({to, (int)g[to].size(), cap});\n        g[to].push_back({from, (int)g[from].size() - 1, 0});\n    }\n    void bfs(int s) {\n        fill(level.begin(), level.end(), -1);\n        queue<int> q;\n        level[s] = 0; q.push(s);\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (auto &e : g[v]) if (e.cap > 0 && level[e.to] < 0) {\n                level[e.to] = level[v] + 1;\n                q.push(e.to);\n            }\n        }\n    }\n    ll dfs(int v, int t, ll f) {\n        if (v == t) return f;\n        for (int &i = iter[v]; i < (int)g[v].size(); ++i) {\n            auto &e = g[v][i];\n            if (e.cap > 0 && level[v] < level[e.to]) {\n                ll d = dfs(e.to, t, min(f, e.cap));\n                if (d > 0) {\n                    e.cap -= d;\n                    g[e.to][e.rev].cap += d;\n                    return d;\n                }\n            }\n        }\n        return 0;\n    }\n    ll max_flow(int s, int t) {\n        ll flow = 0;\n        while (true) {\n            bfs(s);\n            if (level[t] < 0) return flow;\n            fill(iter.begin(), iter.end(), 0);\n            ll f;\n            while ((f = dfs(s, t, 1LL << 60)) > 0) flow += f;\n        }\n    }\n};\n\n// ---------- Hungarian for assignment (min cost, square matrix) ----------\nll hungarian(const vector<vector<ll>> &a, vector<int> &ans) {\n    int n = (int)a.size(), m = (int)a[0].size(); // assumed n == m\n    vector<ll> u(n+1), v(m+1);\n    vector<int> p(m+1), way(m+1);\n    for (int i=1; i<=n; ++i) {\n        p[0] = i;\n        int j0 = 0;\n        vector<ll> minv(m+1, INF_CAP);\n        vector<char> used(m+1, false);\n        do {\n            used[j0] = true;\n            int i0 = p[j0], j1 = 0;\n            ll delta = INF_CAP;\n            for (int j=1; j<=m; ++j) if (!used[j]) {\n                ll cur = a[i0-1][j-1] - u[i0] - v[j];\n                if (cur < minv[j]) { minv[j] = cur; way[j] = j0; }\n                if (minv[j] < delta) { delta = minv[j]; j1 = j; }\n            }\n            for (int j=0; j<=m; ++j) {\n                if (used[j]) u[p[j]] += delta, v[j] -= delta;\n                else minv[j] -= delta;\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    ans.assign(n, -1);\n    for (int j=1; j<=m; ++j) if (p[j] != 0) ans[p[j]-1] = j-1;\n    return -v[0];\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int dx[4] = {-1, 1, 0, 0};\n    const int dy[4] = {0, 0, -1, 1};\n    const char moveC[4] = {'U', 'D', 'L', 'R'};\n    const char buildC[4] = {'u', 'd', 'l', 'r'};\n\n    int N; cin >> N;\n    vector<int> px(N), py(N), pt(N);\n    for (int i = 0; i < N; ++i) cin >> px[i] >> py[i] >> pt[i];\n    int M; cin >> M;\n    vector<int> hx(M), hy(M);\n    for (int i = 0; i < M; ++i) cin >> hx[i] >> hy[i];\n\n    int grid[32][32];\n    memset(grid, 0, sizeof(grid)); // 0: passable, 1: impassable\n\n    auto buildable_now = [&](int x, int y) -> bool {\n        if (grid[x][y] != 0) return false;\n        for (int i = 0; i < M; ++i) if (hx[i] == x && hy[i] == y) return false;\n        for (int i = 0; i < N; ++i) if (px[i] == x && py[i] == y) return false;\n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (nx >= 1 && nx <= 30 && ny >= 1 && ny <= 30) {\n                for (int i = 0; i < N; ++i)\n                    if (px[i] == nx && py[i] == ny) return false;\n            }\n        }\n        return true;\n    };\n\n    auto bfs = [&](int sx, int sy) {\n        vector<vector<int>> dist(31, vector<int>(31, -1));\n        vector<vector<pair<int,int>>> par(31, vector<pair<int,int>>(31, {-1,-1}));\n        queue<pair<int,int>> q;\n        if (grid[sx][sy] == 0) {\n            dist[sx][sy] = 0;\n            q.push({sx, sy});\n        }\n        while (!q.empty()) {\n            auto [x,y] = q.front(); q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int nx = x + dx[d], ny = y + dy[d];\n                if (nx>=1 && nx<=30 && ny>=1 && ny<=30 &&\n                    grid[nx][ny]==0 && dist[nx][ny]==-1) {\n                    dist[nx][ny] = dist[x][y] + 1;\n                    par[nx][ny] = {x, y};\n                    q.push({nx, ny});\n                }\n            }\n        }\n        return make_pair(dist, par);\n    };\n\n    auto pet_dist_map = [&]() {\n        vector<vector<int>> dist(31, vector<int>(31, -1));\n        queue<pair<int,int>> q;\n        for (int i = 0; i < N; ++i) {\n            if (grid[px[i]][py[i]] == 0) {\n                dist[px[i]][py[i]] = 0;\n                q.push({px[i], py[i]});\n            }\n        }\n        while (!q.empty()) {\n            auto [x,y] = q.front(); q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int nx = x + dx[d], ny = y + dy[d];\n                if (nx>=1 && nx<=30 && ny>=1 && ny<=30 &&\n                    grid[nx][ny]==0 && dist[nx][ny]==-1) {\n                    dist[nx][ny] = dist[x][y] + 1;\n                    q.push({nx, ny});\n                }\n            }\n        }\n        return dist;\n    };\n\n    // Min-cut with urgency\n    auto min_cut_walls = [&](const vector<vector<int>> &urgency) -> set<pair<int,int>> {\n        int id[32][32]; memset(id, -1, sizeof(id));\n        vector<pair<int,int>> cells;\n        for (int i = 1; i <= 30; ++i)\n            for (int j = 1; j <= 30; ++j)\n                if (grid[i][j] == 0) {\n                    id[i][j] = (int)cells.size();\n                    cells.emplace_back(i, j);\n                }\n        int V = (int)cells.size();\n        int src = 2*V, sink = 2*V+1;\n        Dinic dinic(2*V+2);\n        for (auto [x,y] : cells) {\n            int u = id[x][y];\n            bool has_hum = false, has_pet = false, adj_pet = false;\n            for (int i = 0; i < M; ++i) if (hx[i]==x && hy[i]==y) has_hum = true;\n            for (int i = 0; i < N; ++i) if (px[i]==x && py[i]==y) has_pet = true;\n            if (!has_pet) {\n                for (int d = 0; d < 4; ++d) {\n                    int nx = x+dx[d], ny = y+dy[d];\n                    if (nx>=1 && nx<=30 && ny>=1 && ny<=30)\n                        for (int i = 0; i < N; ++i)\n                            if (px[i]==nx && py[i]==ny) adj_pet = true;\n                }\n            }\n            bool buildable = !has_hum && !has_pet && !adj_pet;\n            ll cap = buildable ? (100 + (urgency[x][y]==-1 ? 1000 : urgency[x][y])) : INF_CAP;\n            dinic.add_edge(2*u, 2*u+1, cap);\n        }\n        for (int u = 0; u < V; ++u) {\n            auto [x,y] = cells[u];\n            for (int d = 0; d < 4; ++d) {\n                int nx = x+dx[d], ny = y+dy[d];\n                if (nx>=1 && nx<=30 && ny>=1 && ny<=30 && id[nx][ny]!=-1)\n                    dinic.add_edge(2*u+1, 2*id[nx][ny], INF_CAP);\n            }\n        }\n        for (int i = 0; i < M; ++i) {\n            int u = id[hx[i]][hy[i]];\n            if (u != -1) dinic.add_edge(src, 2*u, INF_CAP);\n        }\n        for (int i = 0; i < N; ++i) {\n            int u = id[px[i]][py[i]];\n            if (u != -1) dinic.add_edge(2*u+1, sink, INF_CAP);\n        }\n        dinic.max_flow(src, sink);\n        vector<bool> visited(2*V+2, false);\n        queue<int> q;\n        visited[src] = true; q.push(src);\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (auto &e : dinic.g[v]) if (e.cap > 0 && !visited[e.to]) {\n                visited[e.to] = true;\n                q.push(e.to);\n            }\n        }\n        set<pair<int,int>> cut;\n        for (int u = 0; u < V; ++u)\n            if (visited[2*u] && !visited[2*u+1])\n                cut.insert(cells[u]);\n        return cut;\n    };\n\n    vector<pair<int,int>> prev_target(M, {-1,-1}); // for bonus in Hungarian\n\n    for (int turn = 0; turn < 300; ++turn) {\n        auto pet_dist = pet_dist_map();\n        auto target_set = min_cut_walls(pet_dist);\n        vector<pair<int,int>> walls(target_set.begin(), target_set.end());\n        int W = (int)walls.size();\n\n        // BFS for each human\n        vector<vector<vector<int>>> dist_h(M);\n        vector<vector<vector<pair<int,int>>>> par_h(M);\n        for (int i = 0; i < M; ++i) {\n            auto [d, p] = bfs(hx[i], hy[i]);\n            dist_h[i] = move(d);\n            par_h[i] = move(p);\n        }\n\n        // Build cost matrix for Hungarian\n        int K = max(W, M);\n        vector<vector<ll>> cost(K, vector<ll>(K, 0));\n        for (int i = 0; i < M; ++i) {\n            for (int j = 0; j < W; ++j) {\n                auto [wx, wy] = walls[j];\n                int minGateDist = 1e9;\n                for (int d = 0; d < 4; ++d) {\n                    int gx = wx + dx[d], gy = wy + dy[d];\n                    if (gx>=1 && gx<=30 && gy>=1 && gy<=30 && grid[gx][gy]==0) {\n                        int dd = dist_h[i][gx][gy];\n                        if (dd != -1 && dd < minGateDist) minGateDist = dd;\n                    }\n                }\n                if (minGateDist >= 1e9) {\n                    cost[i][j] = INF_CAP; // unreachable\n                } else {\n                    ll urg = pet_dist[wx][wy];\n                    if (urg == -1) urg = 1000;\n                    cost[i][j] = minGateDist * 10000LL + urg * 10LL;\n                    if (make_pair(wx, wy) == prev_target[i]) cost[i][j] -= 500000LL; // keep assignment\n                }\n            }\n            // dummy columns (j >= W) have cost 0\n        }\n        // dummy rows (i >= M) have cost 0 (already zero)\n\n        vector<int> assignment;\n        hungarian(cost, assignment);\n        vector<pair<int,int>> target_wall(M, {-1,-1});\n        vector<pair<int,int>> target_gate(M, {-1,-1});\n        for (int wi = 0; wi < W; ++wi) {\n            int hum = assignment[wi];\n            if (hum < M) {\n                target_wall[hum] = walls[wi];\n                // find best gate\n                auto [wx, wy] = walls[wi];\n                int bestD = 1e9;\n                pair<int,int> bestGate = {-1,-1};\n                for (int d = 0; d < 4; ++d) {\n                    int gx = wx + dx[d], gy = wy + dy[d];\n                    if (gx>=1 && gx<=30 && gy>=1 && gy<=30 && grid[gx][gy]==0) {\n                        int dg = dist_h[hum][gx][gy];\n                        if (dg != -1 && dg < bestD) {\n                            bestD = dg;\n                            bestGate = {gx, gy};\n                        }\n                    }\n                }\n                target_gate[hum] = bestGate;\n            }\n        }\n        // update prev_target for next turn\n        prev_target = target_wall;\n\n        // Safety function\n        auto safe = [&](int x, int y) {\n            return pet_dist[x][y] == -1 ? 1000000 : pet_dist[x][y];\n        };\n\n        set<pair<int,int>> build_set;\n        string act(M, '.');\n\n        // Phase 1: humans with target\n        for (int i = 0; i < M; ++i) {\n            if (target_wall[i].first == -1) continue;\n            auto [wx, wy] = target_wall[i];\n\n            // try to build if adjacent\n            bool built = false;\n            for (int d = 0; d < 4; ++d) {\n                if (hx[i] + dx[d] == wx && hy[i] + dy[d] == wy) {\n                    if (grid[wx][wy] == 0 && buildable_now(wx, wy) && !build_set.count({wx, wy})) {\n                        act[i] = buildC[d];\n                        build_set.insert({wx, wy});\n                        built = true;\n                        break;\n                    }\n                }\n            }\n            if (built) continue;\n\n            // move towards gate\n            auto [gx, gy] = target_gate[i];\n            if (gx == -1 || dist_h[i][gx][gy] <= 0) continue;\n            // trace back one step\n            int cx = gx, cy = gy;\n            while (par_h[i][cx][cy] != make_pair(hx[i], hy[i])) {\n                auto p = par_h[i][cx][cy];\n                if (p.first == -1) break;\n                cx = p.first; cy = p.second;\n            }\n            if (cx == hx[i] && cy == hy[i]) continue;\n            if (cx < hx[i]) act[i] = 'U';\n            else if (cx > hx[i]) act[i] = 'D';\n            else if (cy < hy[i]) act[i] = 'L';\n            else act[i] = 'R';\n        }\n\n        // Conflict resolution: cancel moves that conflict with builds\n        for (int i = 0; i < M; ++i) {\n            char c = act[i];\n            if (c=='U' || c=='D' || c=='L' || c=='R') {\n                int nx = hx[i], ny = hy[i];\n                if (c=='U') nx--;\n                else if (c=='D') nx++;\n                else if (c=='L') ny--;\n                else if (c=='R') ny++;\n                if (build_set.count({nx, ny})) act[i] = '.';\n            }\n        }\n\n        // Fallback for humans without action\n        for (int i = 0; i < M; ++i) {\n            if (act[i] != '.') continue;\n            // try to move away from pets, preferring to get closer to other humans\n            int curSafe = safe(hx[i], hy[i]);\n            int bestSafe = curSafe, bestNx = -1, bestNy = -1;\n            int bestHuDist = 1e9;\n            for (int d = 0; d < 4; ++d) {\n                int nx = hx[i] + dx[d], ny = hy[i] + dy[d];\n                if (nx>=1 && nx<=30 && ny>=1 && ny<=30 &&\n                    grid[nx][ny]==0 && !build_set.count({nx, ny})) {\n                    int sf = safe(nx, ny);\n                    if (sf > bestSafe) {\n                        bestSafe = sf; bestNx = nx; bestNy = ny;\n                        // compute min distance to another human\n                        int hu = 1e9;\n                        for (int j = 0; j < M; ++j) if (j != i) {\n                            int d2 = dist_h[j][nx][ny];\n                            if (d2 != -1 && d2 < hu) hu = d2;\n                        }\n                        bestHuDist = hu;\n                    } else if (sf == bestSafe) {\n                        int hu = 1e9;\n                        for (int j = 0; j < M; ++j) if (j != i) {\n                            int d2 = dist_h[j][nx][ny];\n                            if (d2 != -1 && d2 < hu) hu = d2;\n                        }\n                        if (hu < bestHuDist) {\n                            bestHuDist = hu;\n                            bestNx = nx; bestNy = ny;\n                        }\n                    }\n                }\n            }\n            if (bestNx != -1) {\n                if (bestNx < hx[i]) act[i] = 'U';\n                else if (bestNx > hx[i]) act[i] = 'D';\n                else if (bestNy < hy[i]) act[i] = 'L';\n                else act[i] = 'R';\n            } else {\n                // try to build any adjacent target wall\n                for (auto [wx, wy] : walls) {\n                    for (int d = 0; d < 4; ++d) {\n                        if (hx[i] + dx[d] == wx && hy[i] + dy[d] == wy) {\n                            if (grid[wx][wy]==0 && buildable_now(wx, wy) && !build_set.count({wx, wy})) {\n                                act[i] = buildC[d];\n                                build_set.insert({wx, wy});\n                                goto fallback_done;\n                            }\n                        }\n                    }\n                }\n                fallback_done:;\n            }\n        }\n\n        // Final safety: ensure moves are valid\n        for (int i = 0; i < M; ++i) {\n            char c = act[i];\n            if (c=='U' || c=='D' || c=='L' || c=='R') {\n                int nx = hx[i], ny = hy[i];\n                if (c=='U') nx--;\n                else if (c=='D') nx++;\n                else if (c=='L') ny--;\n                else if (c=='R') ny++;\n                if (grid[nx][ny] != 0 || build_set.count({nx, ny})) {\n                    act[i] = '.'; // stay, already safe\n                }\n            }\n        }\n\n        cout << act << endl;\n\n        // Apply actions\n        for (int i = 0; i < M; ++i) {\n            char c = act[i];\n            if (c == 'u') grid[hx[i]-1][hy[i]] = 1;\n            else if (c == 'd') grid[hx[i]+1][hy[i]] = 1;\n            else if (c == 'l') grid[hx[i]][hy[i]-1] = 1;\n            else if (c == 'r') grid[hx[i]][hy[i]+1] = 1;\n            else if (c == 'U') hx[i]--;\n            else if (c == 'D') hx[i]++;\n            else if (c == 'L') hy[i]--;\n            else if (c == 'R') hy[i]++;\n        }\n\n        // Read pet movements\n        for (int i = 0; i < N; ++i) {\n            string s; cin >> s;\n            if (s == \".\") continue;\n            for (char c : s) {\n                if (c == 'U') px[i]--;\n                else if (c == 'D') px[i]++;\n                else if (c == 'L') py[i]--;\n                else if (c == 'R') py[i]++;\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <iostream>\n#include <string>\n#include <vector>\n#include <array>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <numeric>\n#include <queue>\n#include <cmath>\n#include <set>\n\nusing namespace std;\n\nconst int L = 200;\nconst int H = 20, W = 20;\nconst int N = H * W;\n\nint start_id, target_id;\ndouble p;\nint next_cell[4][N];\ndouble p_stay[4][N], p_move[4][N];\nchar dir_chars[4] = {'U', 'D', 'L', 'R'};\ndouble reward[L];\n\n// Optimal adaptive DP for beam search heuristic\ndouble V_opt[L + 1][N];\n\n// forward/backward arrays for coordinate ascent\nvector<array<double, N>> F, V;\nvector<double> base_reward_prefix;\n\ndouble evaluate(const string &s) {\n    array<double, N> prob;\n    prob.fill(0.0);\n    prob[start_id] = 1.0;\n    vector<int> active = {start_id};\n    double er = 0.0;\n    for (int t = 0; t < L; ++t) {\n        if (active.empty()) break;\n        char c = s[t];\n        int d;\n        if (c == 'U') d = 0;\n        else if (c == 'D') d = 1;\n        else if (c == 'L') d = 2;\n        else d = 3;\n        array<double, N> next_prob;\n        next_prob.fill(0.0);\n        array<bool, N> next_mark;\n        next_mark.fill(false);\n        for (int i : active) {\n            double pr = prob[i];\n            double stay = p_stay[d][i];\n            double move = p_move[d][i];\n            next_prob[i] += pr * stay;\n            next_mark[i] = true;\n            if (move > 0.0) {\n                int nxt = next_cell[d][i];\n                if (nxt == target_id) {\n                    er += pr * move * reward[t];\n                } else {\n                    next_prob[nxt] += pr * move;\n                    next_mark[nxt] = true;\n                }\n            }\n        }\n        prob.fill(0.0);\n        active.clear();\n        for (int i = 0; i < N; ++i) {\n            if (next_mark[i]) {\n                prob[i] = next_prob[i];\n                active.push_back(i);\n            }\n        }\n    }\n    return er;\n}\n\nint main() {\n    auto start_time = chrono::steady_clock::now();\n    auto time_ms = [&]() {\n        return chrono::duration_cast<chrono::milliseconds>(\n            chrono::steady_clock::now() - start_time).count();\n    };\n\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj, ti, tj;\n    cin >> si >> sj >> ti >> tj >> p;\n    start_id = si * W + sj;\n    target_id = ti * W + tj;\n\n    vector<string> h(20), v(20);\n    for (int i = 0; i < 20; ++i) cin >> h[i];\n    for (int i = 0; i < 19; ++i) cin >> v[i]; // v has 19 rows of length 20\n\n    for (int t = 0; t < L; ++t) reward[t] = 401.0 - (t + 1);\n\n    // precompute walls and transition probabilities\n    int di[4] = {-1, 1, 0, 0};\n    int dj[4] = {0, 0, -1, 1};\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = i * W + j;\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + di[d];\n                int nj = j + dj[d];\n                bool wall = true;\n                if (ni >= 0 && ni < H && nj >= 0 && nj < W) {\n                    if (d == 0) {        // U\n                        if (v[i - 1][j] == '0') wall = false;\n                    } else if (d == 1) { // D\n                        if (v[i][j] == '0') wall = false;\n                    } else if (d == 2) { // L\n                        if (h[i][j - 1] == '0') wall = false;\n                    } else {             // R\n                        if (h[i][j] == '0') wall = false;\n                    }\n                }\n                if (!wall) {\n                    next_cell[d][id] = ni * W + nj;\n                } else {\n                    next_cell[d][id] = id;\n                }\n                p_stay[d][id] = wall ? 1.0 : p;\n                p_move[d][id] = wall ? 0.0 : (1.0 - p);\n            }\n        }\n    }\n\n    // Optimal adaptive DP (upper bound for beam search)\n    for (int i = 0; i < N; ++i) V_opt[0][i] = 0.0;\n    for (int r = 1; r <= L; ++r) {\n        double target_rew = 200.0 + r;\n        for (int i = 0; i < N; ++i) {\n            if (i == target_id) {\n                V_opt[r][i] = 0.0;\n                continue;\n            }\n            double best = 0.0;\n            for (int d = 0; d < 4; ++d) {\n                double stay = p_stay[d][i];\n                double move = p_move[d][i];\n                double val;\n                if (move == 0.0) {\n                    val = V_opt[r - 1][i];\n                } else {\n                    int nxt = next_cell[d][i];\n                    double move_val = (nxt == target_id) ? target_rew : V_opt[r - 1][nxt];\n                    val = stay * V_opt[r - 1][i] + move * move_val;\n                }\n                if (val > best) best = val;\n            }\n            V_opt[r][i] = best;\n        }\n    }\n\n    // ---------- Beam search ----------\n    const int K = 200;\n    vector<array<double, N>> beam_prob;\n    vector<string> beam_str;\n    vector<double> beam_er;\n\n    {\n        array<double, N> prob;\n        prob.fill(0.0);\n        prob[start_id] = 1.0;\n        beam_prob.push_back(prob);\n        beam_str.push_back(\"\");\n        beam_er.push_back(0.0);\n    }\n\n    for (int step = 0; step < L; ++step) {\n        vector<array<double, N>> next_prob_vec;\n        vector<string> next_str;\n        vector<double> next_er;\n        vector<double> next_score;\n\n        for (int idx = 0; idx < (int)beam_prob.size(); ++idx) {\n            const auto &prob = beam_prob[idx];\n            const string &s = beam_str[idx];\n            double er = beam_er[idx];\n\n            for (int d = 0; d < 4; ++d) {\n                array<double, N> ns_prob;\n                ns_prob.fill(0.0);\n                double ns_er = er;\n                for (int i = 0; i < N; ++i) {\n                    double pr = prob[i];\n                    if (pr == 0.0) continue;\n                    double stay = p_stay[d][i];\n                    double move = p_move[d][i];\n                    ns_prob[i] += pr * stay;\n                    if (move > 0.0) {\n                        int nxt = next_cell[d][i];\n                        if (nxt == target_id) {\n                            ns_er += pr * move * reward[step];\n                        } else {\n                            ns_prob[nxt] += pr * move;\n                        }\n                    }\n                }\n                int R = L - (step + 1);\n                double future = 0.0;\n                for (int i = 0; i < N; ++i) future += ns_prob[i] * V_opt[R][i];\n                double score = ns_er + future;\n\n                next_prob_vec.push_back(move(ns_prob));\n                next_str.push_back(s + dir_chars[d]);\n                next_er.push_back(ns_er);\n                next_score.push_back(score);\n            }\n        }\n\n        if (next_score.size() > K) {\n            vector<int> indices(next_score.size());\n            iota(indices.begin(), indices.end(), 0);\n            nth_element(indices.begin(), indices.begin() + K, indices.end(),\n                        [&](int a, int b) { return next_score[a] > next_score[b]; });\n            beam_prob.clear(); beam_str.clear(); beam_er.clear();\n            for (int i = 0; i < K; ++i) {\n                int id = indices[i];\n                beam_prob.push_back(move(next_prob_vec[id]));\n                beam_str.push_back(move(next_str[id]));\n                beam_er.push_back(next_er[id]);\n            }\n        } else {\n            beam_prob = move(next_prob_vec);\n            beam_str = move(next_str);\n            beam_er = move(next_er);\n        }\n    }\n\n    // collect distinct best strings from beam\n    vector<pair<double, string>> candidates;\n    {\n        vector<int> order(beam_er.size());\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) { return beam_er[a] > beam_er[b]; });\n        set<string> seen;\n        for (int idx : order) {\n            if (seen.insert(beam_str[idx]).second) {\n                candidates.emplace_back(beam_er[idx], beam_str[idx]);\n                if (candidates.size() >= 5) break;\n            }\n        }\n    }\n\n    // add deterministic shortest path repeated as fallback\n    {\n        vector<int> prev(N, -1);\n        vector<char> prev_move(N);\n        queue<int> q;\n        q.push(start_id);\n        prev[start_id] = start_id;\n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            if (u == target_id) break;\n            for (int d = 0; d < 4; ++d) {\n                if (p_stay[d][u] < 1.0) { // not wall\n                    int v = next_cell[d][u];\n                    if (prev[v] == -1) {\n                        prev[v] = u;\n                        prev_move[v] = dir_chars[d];\n                        q.push(v);\n                    }\n                }\n            }\n        }\n        string path;\n        for (int v = target_id; v != start_id; v = prev[v])\n            path += prev_move[v];\n        reverse(path.begin(), path.end());\n        string repeated;\n        while (repeated.size() < L) repeated += path;\n        repeated.resize(L);\n        double val = evaluate(repeated);\n        candidates.emplace_back(val, repeated);\n    }\n\n    // keep up to 5 distinct best\n    sort(candidates.begin(), candidates.end(),\n         [](const auto &a, const auto &b) { return a.first > b.first; });\n    set<string> unique_cands;\n    vector<string> start_strings;\n    for (auto &[val, s] : candidates) {\n        if (unique_cands.insert(s).second) {\n            start_strings.push_back(s);\n            if (start_strings.size() >= 5) break;\n        }\n    }\n\n    // ---------- Coordinate ascent ----------\n    F.resize(L + 1);\n    V.resize(L + 1);\n    base_reward_prefix.resize(L + 1);\n\n    auto char_to_dir = [](char c) -> int {\n        if (c == 'U') return 0;\n        if (c == 'D') return 1;\n        if (c == 'L') return 2;\n        return 3;\n    };\n\n    auto compute_forward = [&](const string &s) -> double {\n        F[0].fill(0.0);\n        F[0][start_id] = 1.0;\n        fill(base_reward_prefix.begin(), base_reward_prefix.end(), 0.0);\n        double total_er = 0.0;\n        for (int t = 0; t < L; ++t) {\n            int d = char_to_dir(s[t]);\n            double step_reward = 0.0;\n            auto &cur = F[t];\n            auto &nxt = F[t + 1];\n            nxt.fill(0.0);\n            for (int i = 0; i < N; ++i) {\n                double pr = cur[i];\n                if (pr == 0.0) continue;\n                double stay = p_stay[d][i];\n                double move = p_move[d][i];\n                nxt[i] += pr * stay;\n                if (move > 0.0) {\n                    int nc = next_cell[d][i];\n                    if (nc == target_id) {\n                        step_reward += pr * move * reward[t];\n                    } else {\n                        nxt[nc] += pr * move;\n                    }\n                }\n            }\n            base_reward_prefix[t + 1] = base_reward_prefix[t] + step_reward;\n            total_er += step_reward;\n        }\n        return total_er;\n    };\n\n    auto compute_backward = [&](const string &s) {\n        V[L].fill(0.0);\n        for (int t = L - 1; t >= 0; --t) {\n            int d = char_to_dir(s[t]);\n            auto &cur = V[t];\n            auto &nxt = V[t + 1];\n            for (int i = 0; i < N; ++i) {\n                double stay = p_stay[d][i];\n                double move = p_move[d][i];\n                double val = stay * nxt[i];\n                if (move > 0.0) {\n                    int nc = next_cell[d][i];\n                    if (nc == target_id) {\n                        val += move * reward[t];\n                    } else {\n                        val += move * nxt[nc];\n                    }\n                }\n                cur[i] = val;\n            }\n        }\n    };\n\n    double best_overall_er = -1e9;\n    string best_overall_str;\n\n    for (string &cur_str : start_strings) {\n        if (time_ms() > 1900) break;\n\n        // coordinate ascent\n        while (true) {\n            if (time_ms() > 1900) break;\n            double total_er = compute_forward(cur_str);\n            compute_backward(cur_str);\n\n            double best_improvement = -1e-12;\n            int best_pos = -1, best_dir = -1;\n            double best_new_total = total_er;\n\n            vector<int> cur_dirs(L);\n            for (int t = 0; t < L; ++t) cur_dirs[t] = char_to_dir(cur_str[t]);\n\n            for (int pos = 0; pos < L; ++pos) {\n                double base_val = base_reward_prefix[pos];\n                const auto &f = F[pos];\n                const auto &v_next = V[pos + 1];\n\n                for (int d = 0; d < 4; ++d) {\n                    if (d == cur_dirs[pos]) continue;\n                    double sum = base_val;\n                    for (int i = 0; i < N; ++i) {\n                        double pr = f[i];\n                        if (pr == 0.0) continue;\n                        double stay = p_stay[d][i];\n                        double move = p_move[d][i];\n                        double contrib = stay * v_next[i];\n                        if (move > 0.0) {\n                            int nxt = next_cell[d][i];\n                            if (nxt == target_id) {\n                                contrib += move * reward[pos];\n                            } else {\n                                contrib += move * v_next[nxt];\n                            }\n                        }\n                        sum += pr * contrib;\n                    }\n                    double improvement = sum - total_er;\n                    if (improvement > best_improvement) {\n                        best_improvement = improvement;\n                        best_pos = pos;\n                        best_dir = d;\n                        best_new_total = sum;\n                    }\n                }\n            }\n            if (best_improvement <= 1e-12) break;\n            cur_str[best_pos] = dir_chars[best_dir];\n        }\n        double final_er = evaluate(cur_str);\n        if (final_er > best_overall_er) {\n            best_overall_er = final_er;\n            best_overall_str = cur_str;\n        }\n    }\n\n    // ---------- Simulated Annealing (if time remains) ----------\n    if (time_ms() < 1850) {\n        mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n        uniform_real_distribution<double> real(0.0, 1.0);\n        uniform_int_distribution<int> pos_dis(0, L - 1);\n        uniform_int_distribution<int> dir_dis(0, 3);\n\n        string cur = best_overall_str;\n        double cur_val = best_overall_er;\n        string best_cur = cur;\n        double best_val = cur_val;\n        double T = 0.5;\n        double alpha = 0.999;\n\n        while (time_ms() < 1950) {\n            string nxt = cur;\n            int op = (int)(real(rng) * 100);\n            if (op < 60) {\n                int pos = pos_dis(rng);\n                char old = nxt[pos];\n                char nc = dir_chars[dir_dis(rng)];\n                while (nc == old) nc = dir_chars[dir_dis(rng)];\n                nxt[pos] = nc;\n            } else if (op < 80) {\n                int a = pos_dis(rng), b = pos_dis(rng);\n                swap(nxt[a], nxt[b]);\n            } else {\n                int a = pos_dis(rng), b = pos_dis(rng);\n                if (a > b) swap(a, b);\n                reverse(nxt.begin() + a, nxt.begin() + b + 1);\n            }\n            double nxt_val = evaluate(nxt);\n            double diff = nxt_val - cur_val;\n            if (diff > 0 || exp(diff / T) > real(rng)) {\n                cur = nxt;\n                cur_val = nxt_val;\n                if (cur_val > best_val) {\n                    best_val = cur_val;\n                    best_cur = cur;\n                }\n            }\n            T *= alpha;\n        }\n        best_overall_str = best_cur;\n    }\n\n    cout << best_overall_str << \"\\n\";\n    return 0;\n}","ahc010":"#include <iostream>\n#include <string>\n#include <cstring>\n#include <chrono>\n#include <cstdint>\n#include <vector>\n#include <cmath>\n#include <queue>\n\nusing namespace std;\n\n// fast xorshift random\nuint64_t xor64_state = 123456789ULL;\ninline uint64_t xor64() {\n    xor64_state ^= xor64_state << 13;\n    xor64_state ^= xor64_state >> 7;\n    xor64_state ^= xor64_state << 17;\n    return xor64_state;\n}\ninline int rand_int(int n) {\n    return xor64() % n;\n}\ninline double rand_double() {\n    return (xor64() >> 11) * (1.0 / (1ULL << 53));\n}\n\nchrono::steady_clock::time_point start_time;\ninline double elapsed_sec() {\n    return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n}\n\nconst int N = 30, TOTAL = 900;\nint init_tiles[TOTAL];\nint rot_table[8][4];\nint neig[3600];\nconst int to[8][4] = {\n    {1, 0, -1, -1},\n    {3, -1, -1, 0},\n    {-1, -1, 3, 2},\n    {-1, 2, 1, -1},\n    {1, 0, 3, 2},\n    {3, 2, 1, 0},\n    {2, -1, 0, -1},\n    {-1, 3, -1, 1}\n};\n\n// ---------- static full evaluation (used for quick selection) ----------\nstatic uint16_t static_vis[3600] = {0};\nstatic uint16_t static_vis_id = 0;\nint evaluate_full(const int* cur) {\n    ++static_vis_id;\n    int m1 = 0, m2 = 0;\n    for (int i = 0; i < TOTAL; ++i) {\n        int t = cur[i];\n        int base = i * 4;\n        for (int d = 0; d < 4; ++d) {\n            int idx = base + d;\n            if (static_vis[idx] == static_vis_id) continue;\n            int d0 = to[t][d];\n            if (d0 < 0) continue;\n            int si = i, sd = d;\n            int ci = i, cd = d;\n            int len = 0;\n            while (true) {\n                static_vis[ci * 4 + cd] = static_vis_id;\n                int d2 = to[cur[ci]][cd];\n                if (d2 < 0) { len = -1; break; }\n                int ni = neig[ci * 4 + d2];\n                if (ni < 0) { len = -1; break; }\n                ++len;\n                ci = ni;\n                cd = (d2 + 2) & 3;\n                if (ci == si && cd == sd) break;\n                if (len > 4000) { len = -1; break; }\n            }\n            if (len > 0) {\n                if (len > m1) { m2 = m1; m1 = len; }\n                else if (len > m2) { m2 = len; }\n            }\n        }\n    }\n    if (m2 == 0) return 0;\n    return m1 * m2;\n}\n\n// ---------- incremental evaluation ----------\nint cur_state[TOTAL];\nint rot_state[TOTAL];\nint loop_id[3600];            // -1 if no loop\nvector<int> loop_lens;\nint freq_len[4005] = {0};\nint max1 = 0, max2 = 0;\nbool max_need_recalc = false;\n\ninline void recalc_max() {\n    if (!max_need_recalc) return;\n    max1 = max2 = 0;\n    for (int l = 4000; l >= 1; --l) {\n        if (freq_len[l] > 0) {\n            if (max1 == 0) max1 = l;\n            else if (max2 == 0) { max2 = l; break; }\n        }\n    }\n    max_need_recalc = false;\n}\n\nint trace_path(int si, int sd) {\n    int i = si, d = sd;\n    int len = 0;\n    while (true) {\n        int d2 = to[cur_state[i]][d];\n        if (d2 < 0) return -1;\n        int ni = neig[i * 4 + d2];\n        if (ni < 0) return -1;\n        ++len;\n        i = ni;\n        d = (d2 + 2) & 3;\n        if (i == si && d == sd) return len;\n        if (len > 4000) return -1;\n    }\n}\n\nvoid set_loop_edges(int si, int sd, int id) {\n    int i = si, d = sd;\n    while (true) {\n        loop_id[i * 4 + d] = id;\n        int d2 = to[cur_state[i]][d];\n        int ni = neig[i * 4 + d2];\n        i = ni;\n        d = (d2 + 2) & 3;\n        if (i == si && d == sd) break;\n    }\n}\n\nvoid clear_loop_edges(int si, int sd) {\n    int i = si, d = sd;\n    while (true) {\n        loop_id[i * 4 + d] = -1;\n        int d2 = to[cur_state[i]][d];\n        int ni = neig[i * 4 + d2];\n        i = ni;\n        d = (d2 + 2) & 3;\n        if (i == si && d == sd) break;\n    }\n}\n\nint add_loop(int si, int sd) {\n    int len = trace_path(si, sd);\n    if (len <= 0) return -1;\n    int id = loop_lens.size();\n    loop_lens.push_back(len);\n    set_loop_edges(si, sd, id);\n    freq_len[len]++;\n    if (len > max1) {\n        max2 = max1;\n        max1 = len;\n    } else if (len > max2) {\n        max2 = len;\n    }\n    return id;\n}\n\nvoid remove_loop_by_edge(int si, int sd) {\n    int id = loop_id[si * 4 + sd];\n    if (id == -1) return;\n    int len = loop_lens[id];\n    clear_loop_edges(si, sd);\n    freq_len[len]--;\n    if (freq_len[len] == 0 && (len == max1 || len == max2))\n        max_need_recalc = true;\n}\n\nvoid build_all_loops() {\n    memset(loop_id, -1, sizeof(loop_id));\n    memset(freq_len, 0, sizeof(freq_len));\n    max1 = max2 = 0;\n    max_need_recalc = false;\n    loop_lens.clear();\n    for (int i = 0; i < TOTAL; ++i) {\n        for (int d = 0; d < 4; ++d) {\n            if (loop_id[i * 4 + d] == -1 && to[cur_state[i]][d] != -1) {\n                int len = trace_path(i, d);\n                if (len > 0) {\n                    int id = loop_lens.size();\n                    loop_lens.push_back(len);\n                    set_loop_edges(i, d, id);\n                    freq_len[len]++;\n                    if (len > max1) { max2 = max1; max1 = len; }\n                    else if (len > max2) { max2 = len; }\n                }\n            }\n        }\n    }\n}\n\nstruct TileChange {\n    int idx;\n    int old_rot, new_rot;\n    int old_type, new_type;\n    int old_count;\n    int old_starts_d[4];\n    int new_count;\n    int new_starts_d[4];\n};\n\nbool try_rotation(int idx, int new_rot, TileChange& ch) {\n    ch.idx = idx;\n    ch.old_rot = rot_state[idx];\n    ch.old_type = cur_state[idx];\n    ch.new_rot = new_rot;\n    ch.new_type = rot_table[init_tiles[idx]][new_rot];\n    if (ch.new_type == ch.old_type) return false;\n\n    ch.old_count = 0;\n    for (int d = 0; d < 4; ++d) {\n        if (to[ch.old_type][d] != -1) {\n            int lid = loop_id[idx * 4 + d];\n            if (lid != -1) {\n                bool dup = false;\n                for (int k = 0; k < ch.old_count; ++k) {\n                    int dd = ch.old_starts_d[k];\n                    if (loop_id[idx * 4 + dd] == lid) { dup = true; break; }\n                }\n                if (!dup) ch.old_starts_d[ch.old_count++] = d;\n            }\n        }\n    }\n    for (int k = 0; k < ch.old_count; ++k) {\n        remove_loop_by_edge(idx, ch.old_starts_d[k]);\n    }\n\n    cur_state[idx] = ch.new_type;\n    rot_state[idx] = ch.new_rot;\n\n    ch.new_count = 0;\n    for (int d = 0; d < 4; ++d) {\n        if (to[ch.new_type][d] != -1 && loop_id[idx * 4 + d] == -1) {\n            int lid = add_loop(idx, d);\n            if (lid != -1) ch.new_starts_d[ch.new_count++] = d;\n        }\n    }\n    recalc_max();\n    return true;\n}\n\nvoid revert_rotation(const TileChange& ch) {\n    for (int k = 0; k < ch.new_count; ++k) {\n        remove_loop_by_edge(ch.idx, ch.new_starts_d[k]);\n    }\n    cur_state[ch.idx] = ch.old_type;\n    rot_state[ch.idx] = ch.old_rot;\n    for (int k = 0; k < ch.old_count; ++k) {\n        add_loop(ch.idx, ch.old_starts_d[k]);\n    }\n    recalc_max();\n}\n\ninline int current_score() {\n    recalc_max();\n    if (max2 == 0) return 0;\n    return max1 * max2;\n}\n\n// Hill climbing on a set of tile indices (modifies rot_state, cur_state, score)\nvoid hill_climb_on_set(const vector<int>& tiles, int& score, double time_limit) {\n    bool improved = true;\n    while (improved && elapsed_sec() < time_limit) {\n        improved = false;\n        for (int idx : tiles) {\n            if (elapsed_sec() >= time_limit) break;\n            int orig_rot = rot_state[idx];\n            int best_local = score;\n            int best_r = orig_rot;\n            for (int r = 0; r < 4; ++r) {\n                if (r == orig_rot) continue;\n                TileChange ch;\n                if (try_rotation(idx, r, ch)) {\n                    int ns = current_score();\n                    if (ns > best_local) { best_local = ns; best_r = r; }\n                    revert_rotation(ch);\n                }\n            }\n            if (best_r != orig_rot) {\n                TileChange ch;\n                try_rotation(idx, best_r, ch);\n                score = best_local;\n                improved = true;\n            }\n        }\n    }\n}\n\n// collect tiles that touch at least two distinct loops (merge candidates)\nvector<int> collect_merge_candidates() {\n    vector<int> candidates;\n    for (int i = 0; i < TOTAL; ++i) {\n        int type = cur_state[i];\n        int lids[4] = {-1,-1,-1,-1};\n        int cnt = 0;\n        for (int d = 0; d < 4; ++d) {\n            if (to[type][d] != -1) {\n                int lid = loop_id[i * 4 + d];\n                if (lid != -1) {\n                    bool dup = false;\n                    for (int k = 0; k < cnt; ++k) if (lids[k] == lid) { dup = true; break; }\n                    if (!dup) lids[cnt++] = lid;\n                }\n            }\n        }\n        if (cnt >= 2) candidates.push_back(i);\n    }\n    return candidates;\n}\n\n// ---------- main ----------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    start_time = chrono::steady_clock::now();\n    xor64_state = chrono::steady_clock::now().time_since_epoch().count();\n\n    // read tiles\n    for (int i = 0; i < N; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; ++j) {\n            init_tiles[i * N + j] = s[j] - '0';\n        }\n    }\n\n    // rotation table\n    const int rot1[8] = {1, 2, 3, 0, 5, 4, 7, 6};\n    for (int t = 0; t < 8; ++t) {\n        rot_table[t][0] = t;\n        for (int r = 1; r < 4; ++r) rot_table[t][r] = rot1[rot_table[t][r-1]];\n    }\n\n    // neighbor table\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int idx = i * N + j;\n            int b = idx * 4;\n            neig[b+0] = (j > 0) ? idx - 1 : -1;\n            neig[b+1] = (i > 0) ? idx - N : -1;\n            neig[b+2] = (j < N-1) ? idx + 1 : -1;\n            neig[b+3] = (i < N-1) ? idx + N : -1;\n        }\n    }\n\n    vector<int> all_tiles(TOTAL);\n    for (int i = 0; i < TOTAL; ++i) all_tiles[i] = i;\n\n    int best_rot[TOTAL];\n    int best_score = -1;\n    const double time_budget = 1.95;\n\n    // ----- initial greedy + HC -----\n    {\n        // forward pass\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                int idx = i * N + j;\n                int best_r = 0, best_conn = -1;\n                for (int r = 0; r < 4; ++r) {\n                    int t = rot_table[init_tiles[idx]][r];\n                    int conn = 0;\n                    if (j > 0) { int lt = cur_state[idx - 1]; if (to[t][0] != -1 && to[lt][2] != -1) ++conn; }\n                    if (i > 0) { int ut = cur_state[idx - N]; if (to[t][1] != -1 && to[ut][3] != -1) ++conn; }\n                    if (conn > best_conn) { best_conn = conn; best_r = r; }\n                }\n                rot_state[idx] = best_r;\n                cur_state[idx] = rot_table[init_tiles[idx]][best_r];\n            }\n        }\n        // backward pass\n        for (int i = N-1; i >= 0; --i) {\n            for (int j = N-1; j >= 0; --j) {\n                int idx = i * N + j;\n                int best_r = rot_state[idx], best_conn = 0;\n                for (int r = 0; r < 4; ++r) {\n                    int t = rot_table[init_tiles[idx]][r];\n                    int conn = 0;\n                    if (j > 0 && to[t][0] != -1) { int lt = cur_state[idx-1]; if (to[lt][2] != -1) ++conn; }\n                    if (i > 0 && to[t][1] != -1) { int ut = cur_state[idx-N]; if (to[ut][3] != -1) ++conn; }\n                    if (j < N-1 && to[t][2] != -1) { int rt = cur_state[idx+1]; if (to[rt][0] != -1) ++conn; }\n                    if (i < N-1 && to[t][3] != -1) { int dt = cur_state[idx+N]; if (to[dt][1] != -1) ++conn; }\n                    if (conn > best_conn) { best_conn = conn; best_r = r; }\n                }\n                rot_state[idx] = best_r;\n                cur_state[idx] = rot_table[init_tiles[idx]][best_r];\n            }\n        }\n        build_all_loops();\n        int score = current_score();\n        vector<int> merge_cand = collect_merge_candidates();\n        hill_climb_on_set(merge_cand, score, time_budget);\n        hill_climb_on_set(all_tiles, score, time_budget);\n        if (score > best_score) {\n            best_score = score;\n            memcpy(best_rot, rot_state, sizeof(rot_state));\n        }\n    }\n\n    // ----- Quick random restarts to select best initial solution -----\n    {\n        int tmp_rot[TOTAL];\n        int tmp_cur[TOTAL];\n        for (int restart = 0; restart < 30 && elapsed_sec() < 0.2; ++restart) {\n            for (int i = 0; i < TOTAL; ++i) {\n                tmp_rot[i] = rand_int(4);\n                tmp_cur[i] = rot_table[init_tiles[i]][tmp_rot[i]];\n            }\n            int ns = evaluate_full(tmp_cur);\n            if (ns > best_score) {\n                best_score = ns;\n                memcpy(best_rot, tmp_rot, sizeof(tmp_rot));\n            }\n        }\n    }\n\n    // ----- Main ILS with time slicing -----\n    while (elapsed_sec() < 1.92) {\n        // start from best\n        memcpy(rot_state, best_rot, sizeof(best_rot));\n        for (int i = 0; i < TOTAL; ++i) cur_state[i] = rot_table[init_tiles[i]][rot_state[i]];\n        build_all_loops();\n\n        // Perturb: region BFS\n        {\n            int region_size = 5 + rand_int(9);\n            int seed = rand_int(TOTAL);\n            vector<int> region;\n            vector<bool> in_region(TOTAL, false);\n            queue<int> q;\n            q.push(seed);\n            in_region[seed] = true;\n            while (!q.empty() && (int)region.size() < region_size) {\n                int v = q.front(); q.pop();\n                region.push_back(v);\n                int vi = v / N, vj = v % N;\n                int dirs[4][2] = {{0,-1},{-1,0},{0,1},{1,0}};\n                for (int k = 0; k < 4; ++k) {\n                    int ni = vi + dirs[k][0], nj = vj + dirs[k][1];\n                    if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                        int nidx = ni * N + nj;\n                        if (!in_region[nidx]) {\n                            in_region[nidx] = true;\n                            q.push(nidx);\n                            if ((int)region.size() + (int)q.size() >= region_size) break;\n                        }\n                    }\n                }\n            }\n            for (int i = 0; i < min((int)region.size(), region_size); ++i) {\n                int idx = region[i];\n                rot_state[idx] = rand_int(4);\n                cur_state[idx] = rot_table[init_tiles[idx]][rot_state[idx]];\n            }\n            build_all_loops();\n        }\n\n        int sa_score = current_score();\n        int restart_best_score = sa_score;\n        int restart_best_rot[TOTAL];\n        memcpy(restart_best_rot, rot_state, sizeof(rot_state));\n\n        // SA phase (time-sliced)\n        double T = 120.0;\n        const double alpha = 0.9995;\n        double sa_time = elapsed_sec() + 0.12; // allocate ~0.12 sec for SA\n        if (sa_time > time_budget - 0.05) sa_time = time_budget - 0.05;\n        while (elapsed_sec() < sa_time) {\n            for (int steps = 0; steps < 200 && elapsed_sec() < sa_time; ++steps) {\n                int idx = rand_int(TOTAL);\n                int new_rot = (rot_state[idx] + 1 + rand_int(3)) % 4;\n                TileChange ch;\n                if (try_rotation(idx, new_rot, ch)) {\n                    int new_score = current_score();\n                    int diff = new_score - sa_score;\n                    if (diff >= 0 || rand_double() < exp(diff / T)) {\n                        sa_score = new_score;\n                        if (new_score > restart_best_score) {\n                            restart_best_score = new_score;\n                            memcpy(restart_best_rot, rot_state, sizeof(rot_state));\n                        }\n                    } else {\n                        revert_rotation(ch);\n                    }\n                }\n            }\n            T *= pow(alpha, 200); // update temperature after batch\n        }\n\n        // HC phase (time-sliced)\n        double hc_time = elapsed_sec() + 0.08;\n        if (hc_time > time_budget - 0.02) hc_time = time_budget - 0.02;\n        if (elapsed_sec() < hc_time) {\n            memcpy(rot_state, restart_best_rot, sizeof(rot_state));\n            for (int i = 0; i < TOTAL; ++i) cur_state[i] = rot_table[init_tiles[i]][rot_state[i]];\n            build_all_loops();\n            int hc_score = current_score();\n            vector<int> merge_cand = collect_merge_candidates();\n            hill_climb_on_set(merge_cand, hc_score, hc_time);\n            if (elapsed_sec() < hc_time)\n                hill_climb_on_set(all_tiles, hc_score, hc_time);\n            if (hc_score > best_score) {\n                best_score = hc_score;\n                memcpy(best_rot, rot_state, sizeof(rot_state));\n            }\n        }\n    }\n\n    // final polish on global best\n    if (elapsed_sec() < time_budget - 0.02) {\n        memcpy(rot_state, best_rot, sizeof(best_rot));\n        for (int i = 0; i < TOTAL; ++i) cur_state[i] = rot_table[init_tiles[i]][rot_state[i]];\n        build_all_loops();\n        int final_score = current_score();\n        vector<int> merge_cand = collect_merge_candidates();\n        hill_climb_on_set(merge_cand, final_score, time_budget);\n        if (elapsed_sec() < time_budget)\n            hill_climb_on_set(all_tiles, final_score, time_budget);\n        if (final_score > best_score) best_score = final_score;\n    }\n\n    // output\n    for (int i = 0; i < TOTAL; ++i) cout << best_rot[i];\n    cout << endl;\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\nusing uint64 = unsigned long long;\n\nconst int MAXN = 10;\nconst int MAXV = MAXN * MAXN; // 100\n\nint N, T, V;\nint EMPTY_ID = -1; // we don't use a special ID, just treat 0 as empty type\n\n// Directions: 0:left, 1:up, 2:right, 3:down (vector from empty to neighbor)\nint drow[4] = {0, -1, 0, 1};\nint dcol[4] = {-1, 0, 1, 0};\n// Move character: the tile at the neighbor slides into the empty square.\nchar move_chars[4] = {'L', 'U', 'R', 'D'};\nint opp_dir[4] = {2, 3, 0, 1};  // opposite direction index\n\n// Tile line masks: bit 1 = left, 2 = up, 4 = right, 8 = down\nint tile_has[16][4]; // 0:left, 1:up, 2:right, 3:down\n\nvoid precompute_tile_masks() {\n    int dir_bit[4] = {1, 2, 4, 8};  // left, up, right, down\n    for (int t = 0; t < 16; ++t) {\n        for (int d = 0; d < 4; ++d) {\n            tile_has[t][d] = (t & dir_bit[d]) ? 1 : 0;\n        }\n    }\n}\n\n// Compute size of the largest tree component.\nint compute_tree_size(const vector<int>& board) {\n    vector<int> adj[MAXV];\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = i * N + j;\n            if (board[u] == 0) continue;\n            // down edge\n            if (i + 1 < N) {\n                int v = (i + 1) * N + j;\n                if (board[v] != 0) {\n                    if (tile_has[board[u]][3] && tile_has[board[v]][1]) {\n                        adj[u].push_back(v);\n                        adj[v].push_back(u);\n                    }\n                }\n            }\n            // right edge\n            if (j + 1 < N) {\n                int v = i * N + (j + 1);\n                if (board[v] != 0) {\n                    if (tile_has[board[u]][2] && tile_has[board[v]][0]) {\n                        adj[u].push_back(v);\n                        adj[v].push_back(u);\n                    }\n                }\n            }\n        }\n    }\n    vector<bool> vis(V, false);\n    int max_tree = 0;\n    for (int u = 0; u < V; ++u) {\n        if (board[u] == 0 || vis[u]) continue;\n        vector<int> comp;\n        queue<int> q;\n        q.push(u);\n        vis[u] = true;\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            comp.push_back(v);\n            for (int w : adj[v]) {\n                if (!vis[w]) {\n                    vis[w] = true;\n                    q.push(w);\n                }\n            }\n        }\n        int edges = 0;\n        for (int v : comp) edges += adj[v].size();\n        edges /= 2;\n        int nodes = (int)comp.size();\n        if (edges == nodes - 1) {\n            if (nodes > max_tree) max_tree = nodes;\n        }\n    }\n    return max_tree;\n}\n\nint score_val(int S, int K) {\n    int MaxS = V - 1;\n    if (S < MaxS) {\n        return (int)round(500000.0 * S / MaxS);\n    } else {\n        return (int)round(500000.0 * (2.0 - (double)K / T));\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> T;\n    V = N * N;\n    precompute_tile_masks();\n\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n\n    vector<int> init_board(V);\n    int empty_start = -1;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            char c = grid[i][j];\n            int t = (c >= '0' && c <= '9') ? (c - '0') : (c - 'a' + 10);\n            init_board[i * N + j] = t;\n            if (t == 0) empty_start = i * N + j;\n        }\n    }\n\n    int initial_S = compute_tree_size(init_board);\n    int best_score = score_val(initial_S, 0);\n    string best_seq = \"\";\n\n    // If already perfect, output empty.\n    if (initial_S == V - 1) {\n        cout << \"\" << endl;\n        return 0;\n    }\n\n    const double TIME_LIMIT = 2.9 * CLOCKS_PER_SEC;\n    clock_t start_time = clock();\n    mt19937 rng(12345);\n\n    while (double(clock() - start_time) < TIME_LIMIT) {\n        vector<int> board = init_board;\n        int empty = empty_start;\n        string seq;\n        int prev_d = -1;\n        int K = 0;\n        int current_S = initial_S;\n        while (K < T) {\n            int best_d = -1;\n            int best_tree = -1;\n            vector<int> candidates;\n            for (int d = 0; d < 4; ++d) {\n                int r = empty / N, c = empty % N;\n                int nr = r + drow[d], nc = c + dcol[d];\n                if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n                if (prev_d != -1 && d == opp_dir[prev_d]) continue; // avoid immediate reverse\n                // simulate move\n                int neighbor = nr * N + nc;\n                swap(board[empty], board[neighbor]);\n                int S = compute_tree_size(board);\n                swap(board[empty], board[neighbor]);\n                if (S > best_tree) {\n                    best_tree = S;\n                    candidates.clear();\n                    candidates.push_back(d);\n                } else if (S == best_tree) {\n                    candidates.push_back(d);\n                }\n            }\n            if (candidates.empty()) break;\n            int d = candidates[uniform_int_distribution<int>(0, (int)candidates.size() - 1)(rng)];\n            int neighbor = (empty / N + drow[d]) * N + (empty % N + dcol[d]);\n            swap(board[empty], board[neighbor]);\n            empty = neighbor;\n            seq.push_back(move_chars[d]);\n            prev_d = d;\n            ++K;\n            current_S = best_tree;\n            if (current_S == V - 1) break; // perfect tree\n        }\n        // Evaluate final score\n        int final_S = compute_tree_size(board);\n        int cur_score = score_val(final_S, (int)seq.length());\n        if (cur_score > best_score) {\n            best_score = cur_score;\n            best_seq = seq;\n            if (final_S == V - 1 && cur_score == score_val(final_S, seq.length())) {\n                // perfect tree, we can stop searching for better perfect score\n                // but could exist shorter sequence, so continue\n                if (seq.length() <= 1) break; // unlikely\n            }\n        }\n    }\n\n    if (best_seq.empty()) {\n        // if no improvement, output empty (which is legal)\n        cout << \"\" << endl;\n    } else {\n        cout << best_seq << endl;\n    }\n\n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <numeric>\n#include <cmath>\n#include <climits>\n#include <tuple>\n\nusing namespace std;\n\nstruct Point { int x, y; };\nstruct Line  { int p1x, p1y, p2x, p2y; };\n\nvector<int> a(11);\nint total_attendees = 0;\nvector<Point> pts;\nint N, K;\nchrono::steady_clock::time_point prog_start;\n\n// ---------- geometry ----------\nlong long cross(const Line& L, const Point& p) {\n    return (long long)(L.p2x - L.p1x) * (p.y - L.p1y) -\n           (long long)(L.p2y - L.p1y) * (p.x - L.p1x);\n}\n\nbool line_intersects_circle(const Line& L) {\n    long long dx = L.p2x - L.p1x;\n    long long dy = L.p2y - L.p1y;\n    long long cross_val = llabs((long long)L.p1x * L.p2y - (long long)L.p1y * L.p2x);\n    long long lhs = cross_val * cross_val;\n    long long rhs = 100000000LL * (dx * dx + dy * dy);\n    return lhs <= rhs;\n}\n\n// ---------- state ----------\nstruct State {\n    vector<int> cell_of_point;\n    vector<int> cell_count;\n    vector<vector<int>> cell_points;\n    int real_score = 0;        // sum_{d} min(a[d], b[d])\n    long long heuristic = 0;   // 100000*real - penalty\n};\n\nlong long compute_heuristic(const vector<int>& cell_count, int& real) {\n    int b[11] = {0};\n    int penalty = 0;\n    for (int cnt : cell_count) {\n        if (cnt >= 1 && cnt <= 10) b[cnt]++;\n        else if (cnt > 10) penalty += (cnt - 10);\n    }\n    real = 0;\n    for (int d = 1; d <= 10; ++d) real += min(a[d], b[d]);\n    return 100000LL * real - penalty;\n}\n\nState build_initial_state() {\n    State st;\n    st.cell_of_point.assign(N, 0);\n    st.cell_count = {N};\n    st.cell_points = { vector<int>(N) };\n    iota(st.cell_points[0].begin(), st.cell_points[0].end(), 0);\n    st.heuristic = compute_heuristic(st.cell_count, st.real_score);\n    return st;\n}\n\n// returns (new_counts, bits, heuristic) ; heuristic == -1 means line hits a berry\ntuple<vector<int>, vector<int>, long long> simulate(const State& st, const Line& L) {\n    int C = st.cell_count.size();\n    vector<int> new_count(2 * C, 0);\n    vector<int> bits(N);\n    long long dx = L.p2x - L.p1x;\n    long long dy = L.p2y - L.p1y;\n    for (int i = 0; i < N; ++i) {\n        int old_c = st.cell_of_point[i];\n        long long px = pts[i].x - L.p1x;\n        long long py = pts[i].y - L.p1y;\n        long long c = dx * py - dy * px;\n        if (c == 0) return { {}, {}, -1 };\n        int bit = (c > 0) ? 1 : 0;\n        bits[i] = bit;\n        new_count[old_c * 2 + bit]++;\n    }\n    int real_dummy;\n    long long h = compute_heuristic(new_count, real_dummy);\n    return {new_count, bits, h};\n}\n\nvoid apply_line(State& st, const vector<int>& new_count, const vector<int>& bits) {\n    int C = st.cell_count.size();\n    vector<int> new_cell_id(2 * C, -1);\n    int new_C = 0;\n    for (int c = 0; c < 2 * C; ++c)\n        if (new_count[c] > 0) new_cell_id[c] = new_C++;\n    st.cell_count.resize(new_C);\n    st.cell_points.assign(new_C, vector<int>());\n    for (int c = 0; c < 2 * C; ++c) {\n        if (new_count[c] > 0) {\n            int nid = new_cell_id[c];\n            st.cell_count[nid] = new_count[c];\n            st.cell_points[nid].reserve(new_count[c]);\n        }\n    }\n    for (int i = 0; i < N; ++i) {\n        int old_c = st.cell_of_point[i];\n        int nid = new_cell_id[old_c * 2 + bits[i]];\n        st.cell_of_point[i] = nid;\n        st.cell_points[nid].push_back(i);\n    }\n    st.heuristic = compute_heuristic(st.cell_count, st.real_score);\n}\n\n// ---------- candidate generators ----------\nLine random_line_through_cake(mt19937& rng) {\n    uniform_int_distribution<int> coord(-10000, 10000);\n    uniform_int_distribution<int> delta(-1000, 1000);\n    while (true) {\n        int x = coord(rng);\n        int y = coord(rng);\n        if ((long long)x * x + (long long)y * y < 100000000LL) {\n            int dx = delta(rng);\n            int dy = delta(rng);\n            if (dx == 0 && dy == 0) dx = 1;\n            return {x, y, x + dx, y + dy};\n        }\n    }\n}\n\nLine random_boundary_line(mt19937& rng) {\n    const double PI = acos(-1.0);\n    uniform_real_distribution<double> angle(0, 2 * PI);\n    double a1 = angle(rng);\n    double a2 = angle(rng);\n    int p1x = (int)round(10000 * cos(a1));\n    int p1y = (int)round(10000 * sin(a1));\n    int p2x = (int)round(10000 * cos(a2));\n    int p2y = (int)round(10000 * sin(a2));\n    if (p1x == p2x && p1y == p2y) p1x++;\n    return {p1x, p1y, p2x, p2y};\n}\n\nLine random_cell_split_line(const State& st, mt19937& rng) {\n    const auto& cell_points = st.cell_points;\n    vector<int> big;\n    for (int c = 0; c < (int)cell_points.size(); ++c)\n        if (cell_points[c].size() >= 2) big.push_back(c);\n    if (big.empty()) return random_line_through_cake(rng);\n    uniform_int_distribution<int> cell_sel(0, big.size() - 1);\n    int c = big[cell_sel(rng)];\n    const auto& pvec = cell_points[c];\n    uniform_int_distribution<int> pt_sel(0, pvec.size() - 1);\n    int i1 = pvec[pt_sel(rng)];\n    int i2 = pvec[pt_sel(rng)];\n    while (i2 == i1) i2 = pvec[pt_sel(rng)];\n    Point p1 = pts[i1], p2 = pts[i2];\n    int mx = (p1.x + p2.x) / 2;\n    int my = (p1.y + p2.y) / 2;\n    uniform_int_distribution<int> delta(-200, 200);\n    int dx = delta(rng);\n    int dy = delta(rng);\n    if (dx == 0 && dy == 0) dx = 1;\n    Line L = {mx, my, mx + dx, my + dy};\n    long long c1 = cross(L, p1), c2 = cross(L, p2);\n    if (c1 == 0 || c2 == 0 || (c1 > 0) == (c2 > 0)) {\n        int ndx = -dy, ndy = dx;\n        L = {mx, my, mx + ndx, my + ndy};\n        c1 = cross(L, p1); c2 = cross(L, p2);\n        if (c1 == 0 || c2 == 0 || (c1 > 0) == (c2 > 0))\n            return random_line_through_cake(rng);\n    }\n    return L;\n}\n\nLine random_separating_line(mt19937& rng) {\n    uniform_int_distribution<int> pt_sel(0, N - 1);\n    int i1 = pt_sel(rng);\n    int i2 = pt_sel(rng);\n    while (i2 == i1) i2 = pt_sel(rng);\n    Point p1 = pts[i1], p2 = pts[i2];\n    int mx = (p1.x + p2.x) / 2;\n    int my = (p1.y + p2.y) / 2;\n    uniform_int_distribution<int> delta(-1000, 1000);\n    int dx = delta(rng);\n    int dy = delta(rng);\n    if (dx == 0 && dy == 0) dx = 1;\n    Line L = {mx, my, mx + dx, my + dy};\n    long long c1 = cross(L, p1), c2 = cross(L, p2);\n    if (c1 == 0 || c2 == 0 || (c1 > 0) == (c2 > 0)) {\n        swap(dx, dy); dx = -dx;\n        L = {mx, my, mx + dx, my + dy};\n        c1 = cross(L, p1); c2 = cross(L, p2);\n        if (c1 == 0 || c2 == 0 || (c1 > 0) == (c2 > 0))\n            return random_line_through_cake(rng);\n    }\n    return L;\n}\n\nLine perturb_existing_line(const vector<Line>& lines, mt19937& rng) {\n    if (lines.empty()) return random_line_through_cake(rng);\n    uniform_int_distribution<int> idx(0, lines.size() - 1);\n    uniform_int_distribution<int> delta(-300, 300);\n    uniform_int_distribution<int> coord(0, 3);\n    Line L = lines[idx(rng)];\n    int d = delta(rng);\n    int c = coord(rng);\n    if (c == 0) L.p1x += d;\n    else if (c == 1) L.p1y += d;\n    else if (c == 2) L.p2x += d;\n    else L.p2y += d;\n    if (L.p1x == L.p2x && L.p1y == L.p2y) L.p1x++;\n    return L;\n}\n\nLine shifted_parallel_line(const Line& L, int delta, mt19937& rng) {\n    // line in form a*x + b*y = c\n    long long a = L.p2y - L.p1y;\n    long long b = L.p1x - L.p2x;\n    long long c = a * L.p1x + b * L.p1y;\n    c += delta;\n    // pick two integer points on the new line that are likely inside the box and distinct\n    int px, py, qx, qy;\n    if (a == 0) {\n        if (b == 0) return L;\n        py = (int)(c / b);\n        px = 0;\n        qx = 10000;\n        qy = (int)((c - a * 10000) / b);\n    } else if (b == 0) {\n        px = (int)(c / a);\n        py = 0;\n        qx = px;\n        qy = 10000;\n    } else {\n        px = 0; py = (int)(c / b);\n        qx = 10000; qy = (int)((c - a * 10000) / b);\n    }\n    if (px == qx && py == qy) { px += 1; qx += 1; }\n    return {px, py, qx, qy};\n}\n\nLine targeted_candidate(const State& st, mt19937& rng) {\n    vector<int> need(11, 0);\n    for (int d = 1; d <= 10; ++d) {\n        int bd = 0;\n        for (int cnt : st.cell_count) if (cnt == d) bd++;\n        if (bd < a[d]) need[d] = a[d] - bd;\n    }\n    bool any = false;\n    for (int d = 1; d <= 10; ++d) if (need[d] > 0) any = true;\n    if (!any) return random_line_through_cake(rng);\n\n    vector<int> missing;\n    for (int d = 1; d <= 10; ++d) if (need[d] > 0) missing.push_back(d);\n    uniform_int_distribution<int> d_sel(0, missing.size() - 1);\n    int d = missing[d_sel(rng)];\n\n    vector<int> cells;\n    for (int c = 0; c < (int)st.cell_count.size(); ++c)\n        if (st.cell_count[c] >= d + 1) cells.push_back(c);\n    if (cells.empty()) return random_line_through_cake(rng);\n\n    uniform_int_distribution<int> cell_sel(0, cells.size() - 1);\n    int c = cells[cell_sel(rng)];\n    const auto& pvec = st.cell_points[c];\n    int sz = pvec.size();\n    if (sz < d + 1) return random_line_through_cake(rng);\n\n    vector<int> perm(sz);\n    iota(perm.begin(), perm.end(), 0);\n    shuffle(perm.begin(), perm.end(), rng);\n    vector<Point> A(d), B(sz - d);\n    for (int i = 0; i < d; ++i) A[i] = pts[pvec[perm[i]]];\n    for (int i = d; i < sz; ++i) B[i - d] = pts[pvec[perm[i]]];\n\n    const double PI = acos(-1.0);\n    uniform_real_distribution<double> angle(0, 2 * PI);\n    for (int attempt = 0; attempt < 80; ++attempt) {\n        double ang = angle(rng);\n        long long dx = (long long)(cos(ang) * 10000);\n        long long dy = (long long)(sin(ang) * 10000);\n        if (dx == 0 && dy == 0) continue;\n        long long minA = LLONG_MAX, maxA = LLONG_MIN;\n        for (const Point& p : A) {\n            long long proj = dx * p.x + dy * p.y;\n            if (proj < minA) minA = proj;\n            if (proj > maxA) maxA = proj;\n        }\n        long long minB = LLONG_MAX, maxB = LLONG_MIN;\n        for (const Point& p : B) {\n            long long proj = dx * p.x + dy * p.y;\n            if (proj < minB) minB = proj;\n            if (proj > maxB) maxB = proj;\n        }\n        if (maxA < minB) {\n            long long mid = (maxA + minB) / 2;\n            if (dx == 0) {\n                int y = (int)(mid / dy);\n                return {0, y, 10000, y};\n            } else if (dy == 0) {\n                int x = (int)(mid / dx);\n                return {x, 0, x, 10000};\n            } else {\n                int y0 = (int)(mid / dy);\n                int y1 = (int)((mid - dx * 10000) / dy);\n                return {0, y0, 10000, y1};\n            }\n        } else if (maxB < minA) {\n            long long mid = (maxB + minA) / 2;\n            if (dx == 0) {\n                int y = (int)(mid / dy);\n                return {0, y, 10000, y};\n            } else if (dy == 0) {\n                int x = (int)(mid / dx);\n                return {x, 0, x, 10000};\n            } else {\n                int y0 = (int)(mid / dy);\n                int y1 = (int)((mid - dx * 10000) / dy);\n                return {0, y0, 10000, y1};\n            }\n        }\n    }\n    return random_line_through_cake(rng);\n}\n\nLine targeted_projection_candidate(const State& st, mt19937& rng) {\n    vector<int> need(11, 0);\n    for (int d = 1; d <= 10; ++d) {\n        int bd = 0;\n        for (int cnt : st.cell_count) if (cnt == d) bd++;\n        if (bd < a[d]) need[d] = a[d] - bd;\n    }\n    bool any = false;\n    for (int d = 1; d <= 10; ++d) if (need[d] > 0) any = true;\n    if (!any) return random_line_through_cake(rng);\n\n    vector<int> missing;\n    for (int d = 1; d <= 10; ++d) if (need[d] > 0) missing.push_back(d);\n    shuffle(missing.begin(), missing.end(), rng);\n\n    for (int d : missing) {\n        vector<int> cells;\n        for (int c = 0; c < (int)st.cell_count.size(); ++c)\n            if (st.cell_count[c] >= d + 1) cells.push_back(c);\n        if (cells.empty()) continue;\n        shuffle(cells.begin(), cells.end(), rng);\n        for (int c : cells) {\n            const auto& pvec = st.cell_points[c];\n            int sz = pvec.size();\n            if (sz < d + 1) continue;\n            for (int attempt = 0; attempt < 20; ++attempt) {\n                uniform_int_distribution<int> dir(-2000, 2000);\n                int dx = dir(rng);\n                int dy = dir(rng);\n                if (dx == 0 && dy == 0) continue;\n                vector<long long> proj(sz);\n                for (int i = 0; i < sz; ++i) {\n                    const Point& p = pts[pvec[i]];\n                    proj[i] = (long long)dx * p.x + (long long)dy * p.y;\n                }\n                vector<int> idx(sz);\n                iota(idx.begin(), idx.end(), 0);\n                sort(idx.begin(), idx.end(), [&](int a, int b) { return proj[a] < proj[b]; });\n                if (d >= 1 && d < sz) {\n                    int i = d - 1;\n                    long long proj1 = proj[idx[i]];\n                    long long proj2 = proj[idx[i+1]];\n                    if (proj1 == proj2) continue;\n                    long long sum = proj1 + proj2;\n                    long long dx2 = dx * 2LL;\n                    long long dy2 = dy * 2LL;\n                    Line L;\n                    if (dx2 == 0) {\n                        if (dy2 == 0) continue;\n                        int y = (int)(sum / dy2);\n                        L = {0, y, 10000, y};\n                    } else if (dy2 == 0) {\n                        int x = (int)(sum / dx2);\n                        L = {x, 0, x, 10000};\n                    } else {\n                        int y0 = (int)(sum / dy2);\n                        int y1 = (int)((sum - dx2 * 10000) / dy2);\n                        L = {0, y0, 10000, y1};\n                    }\n                    if (!line_intersects_circle(L)) continue;\n                    return L;\n                }\n            }\n        }\n    }\n    return random_line_through_cake(rng);\n}\n\n// ---------- greedy addition ----------\nvoid greedy_add_lines(State& st, vector<Line>& lines, mt19937& rng,\n                      double time_limit, int candidates) {\n    auto start = chrono::steady_clock::now();\n    auto remain = [&]() -> bool {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count() < time_limit;\n    };\n    while ((int)lines.size() < K && st.real_score < total_attendees && remain()) {\n        long long best_h = -1;\n        Line best_line;\n        vector<int> best_new_count, best_bits;\n        for (int t = 0; t < candidates && remain(); ++t) {\n            Line cand;\n            int type = uniform_int_distribution<int>(0, 15)(rng);\n            if (type < 2)      cand = random_boundary_line(rng);\n            else if (type < 4) cand = random_line_through_cake(rng);\n            else if (type < 6) cand = random_cell_split_line(st, rng);\n            else if (type < 8) cand = random_separating_line(rng);\n            else if (type < 10) cand = perturb_existing_line(lines, rng);\n            else if (type < 12) cand = targeted_candidate(st, rng);\n            else if (type < 14) cand = targeted_projection_candidate(st, rng);\n            else {\n                // random parallel shift of an existing line\n                if (!lines.empty()) {\n                    uniform_int_distribution<int> id(0, lines.size()-1);\n                    uniform_int_distribution<int> shift(-50, 50);\n                    cand = shifted_parallel_line(lines[id(rng)], shift(rng), rng);\n                } else cand = random_line_through_cake(rng);\n            }\n            if (!line_intersects_circle(cand)) continue;\n            auto [nc, bits, h] = simulate(st, cand);\n            if (h == -1) continue;\n            if (h > best_h) {\n                best_h = h;\n                best_line = cand;\n                best_new_count = std::move(nc);\n                best_bits = std::move(bits);\n            }\n        }\n        if (best_h == -1) {   // fallback\n            while (remain()) {\n                Line cand = random_line_through_cake(rng);\n                if (!line_intersects_circle(cand)) continue;\n                auto [nc, bits, h] = simulate(st, cand);\n                if (h != -1) {\n                    best_line = cand;\n                    best_new_count = std::move(nc);\n                    best_bits = std::move(bits);\n                    break;\n                }\n            }\n        }\n        if (!remain()) break;\n        apply_line(st, best_new_count, best_bits);\n        lines.push_back(best_line);\n    }\n}\n\n// ---------- fine tuning ----------\nvoid fine_tune_lines(vector<Line>& lines, double time_limit) {\n    auto start = chrono::steady_clock::now();\n    auto remain = [&]() -> bool {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count() < time_limit;\n    };\n    if (lines.empty()) return;\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    State st = build_initial_state();\n    for (const Line& L : lines) {\n        auto [nc, bits, h] = simulate(st, L);\n        if (h == -1) return;\n        apply_line(st, nc, bits);\n    }\n    const int delta_range = 25;\n    while (remain()) {\n        bool improved = false;\n        vector<int> order(lines.size());\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n        for (int idx : order) {\n            if (!remain()) break;\n            Line old = lines[idx];\n            long long best_h = st.heuristic;\n            Line best_line = old;\n\n            // try small endpoint perturbations\n            for (int sign = 0; sign < 2; ++sign) {\n                for (int d = -delta_range; d <= delta_range; ++d) {\n                    if (d == 0) continue;\n                    if (!remain()) break;\n                    Line cand = old;\n                    int delta = sign ? -d : d;\n                    int coord = uniform_int_distribution<int>(0, 3)(rng);\n                    if (coord == 0) cand.p1x += delta;\n                    else if (coord == 1) cand.p1y += delta;\n                    else if (coord == 2) cand.p2x += delta;\n                    else cand.p2y += delta;\n                    if (cand.p1x == cand.p2x && cand.p1y == cand.p2y) continue;\n                    if (!line_intersects_circle(cand)) continue;\n                    auto [nc, bits, h] = simulate(st, cand);\n                    if (h == -1) continue;\n                    if (h > best_h) {\n                        best_h = h;\n                        best_line = cand;\n                    }\n                }\n            }\n\n            // try parallel shift\n            for (int s = -20; s <= 20; s += 4) {\n                if (s == 0) continue;\n                if (!remain()) break;\n                Line cand = shifted_parallel_line(old, s, rng);\n                if (cand.p1x == cand.p2x && cand.p1y == cand.p2y) continue;\n                if (!line_intersects_circle(cand)) continue;\n                auto [nc, bits, h] = simulate(st, cand);\n                if (h == -1) continue;\n                if (h > best_h) {\n                    best_h = h;\n                    best_line = cand;\n                }\n            }\n\n            if (best_line.p1x != old.p1x || best_line.p1y != old.p1y ||\n                best_line.p2x != old.p2x || best_line.p2y != old.p2y) {\n                auto [nc, bits, h] = simulate(st, best_line);\n                if (h != -1) {\n                    apply_line(st, nc, bits);\n                    lines[idx] = best_line;\n                    improved = true;\n                }\n            }\n        }\n        if (!improved) break;\n    }\n}\n\n// ---------- local search ----------\nvoid local_search_improve(vector<Line>& lines, double time_limit,\n                          int candidates_per_line) {\n    auto start = chrono::steady_clock::now();\n    auto remain = [&]() -> bool {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count() < time_limit;\n    };\n    if (lines.empty()) return;\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    State st = build_initial_state();\n    for (const Line& L : lines) {\n        auto [nc, bits, h] = simulate(st, L);\n        if (h == -1) return;\n        apply_line(st, nc, bits);\n    }\n\n    while (remain() && st.real_score < total_attendees) {\n        bool improved = false;\n\n        // removal pass\n        for (int idx = lines.size() - 1; idx >= 0; --idx) {\n            if (!remain()) break;\n            if (lines.size() <= 1) break;\n            Line old = lines[idx];\n            State curr = build_initial_state();\n            for (int j = 0; j < (int)lines.size(); ++j) {\n                if (j == idx) continue;\n                auto [nc, bits, h] = simulate(curr, lines[j]);\n                if (h == -1) { curr.heuristic = -1; break; }\n                apply_line(curr, nc, bits);\n            }\n            if (curr.heuristic == -1) continue;\n            if (curr.heuristic >= st.heuristic) {\n                lines.erase(lines.begin() + idx);\n                st = std::move(curr);\n                improved = true;\n            }\n        }\n\n        // replacement pass\n        vector<int> order(lines.size());\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n        for (int idx : order) {\n            if (!remain()) break;\n            Line old = lines[idx];\n            State curr = build_initial_state();\n            for (int j = 0; j < (int)lines.size(); ++j) {\n                if (j == idx) continue;\n                auto [nc, bits, h] = simulate(curr, lines[j]);\n                if (h == -1) { curr.heuristic = -1; break; }\n                apply_line(curr, nc, bits);\n            }\n            if (curr.heuristic == -1) continue;\n            long long best_h = curr.heuristic;\n            Line best_line;\n            vector<int> best_nc, best_bits;\n            for (int t = 0; t < candidates_per_line && remain(); ++t) {\n                Line cand;\n                int type = uniform_int_distribution<int>(0, 15)(rng);\n                if (type < 2)      cand = random_boundary_line(rng);\n                else if (type < 4) cand = random_line_through_cake(rng);\n                else if (type < 6) cand = random_cell_split_line(curr, rng);\n                else if (type < 8) cand = random_separating_line(rng);\n                else if (type < 10) cand = perturb_existing_line(lines, rng);\n                else if (type < 12) cand = targeted_candidate(curr, rng);\n                else if (type < 14) cand = targeted_projection_candidate(curr, rng);\n                else {\n                    if (!lines.empty()) {\n                        uniform_int_distribution<int> id(0, lines.size()-1);\n                        uniform_int_distribution<int> shift(-50, 50);\n                        cand = shifted_parallel_line(lines[id(rng)], shift(rng), rng);\n                    } else cand = random_line_through_cake(rng);\n                }\n                if (!line_intersects_circle(cand)) continue;\n                auto [nc, bits, h] = simulate(curr, cand);\n                if (h == -1) continue;\n                if (h > best_h) {\n                    best_h = h;\n                    best_line = cand;\n                    best_nc = std::move(nc);\n                    best_bits = std::move(bits);\n                }\n            }\n            if (best_h > curr.heuristic) {\n                lines[idx] = best_line;\n                improved = true;\n            } else {\n                lines[idx] = old;\n            }\n        }\n\n        if (!improved) break;\n\n        // rebuild global state\n        st = build_initial_state();\n        for (const Line& L : lines) {\n            auto [nc, bits, h] = simulate(st, L);\n            if (h == -1) return;\n            apply_line(st, nc, bits);\n        }\n    }\n\n    double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    if (!remain()) return;\n\n    // fill remaining cuts\n    mt19937 rng2(chrono::steady_clock::now().time_since_epoch().count());\n    greedy_add_lines(st, lines, rng2, time_limit - elapsed, 200);\n\n    // final fine tuning\n    elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    if (remain()) fine_tune_lines(lines, time_limit - elapsed);\n}\n\n// ---------- one full attempt ----------\nvector<Line> run_attempt(mt19937& rng, double time_limit,\n                         int greed_candidates, int local_candidates) {\n    auto start = chrono::steady_clock::now();\n    auto remain = [&]() -> bool {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count() < time_limit;\n    };\n\n    State st = build_initial_state();\n    vector<Line> lines;\n    lines.reserve(K);\n\n    greedy_add_lines(st, lines, rng, time_limit * 0.75, greed_candidates);\n\n    double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    double local_time = time_limit - elapsed;\n    if (local_time > 0.05) {\n        local_search_improve(lines, local_time * 0.95, local_candidates);\n    }\n    return lines;\n}\n\nint compute_real_score(const vector<Line>& lines) {\n    State st = build_initial_state();\n    for (const Line& L : lines) {\n        auto [nc, bits, h] = simulate(st, L);\n        if (h == -1) return -1;\n        apply_line(st, nc, bits);\n    }\n    return st.real_score;\n}\n\n// ---------- main ----------\nint main() {\n    ios::sync_with_stdio(false); cin.tie(0);\n    prog_start = chrono::steady_clock::now();\n\n    cin >> N >> K;\n    for (int d = 1; d <= 10; ++d) {\n        cin >> a[d];\n        total_attendees += a[d];\n    }\n    pts.resize(N);\n    for (int i = 0; i < N; ++i) cin >> pts[i].x >> pts[i].y;\n\n    const double TOTAL_TIME = 2.95;\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - prog_start).count();\n    };\n\n    mt19937 base_rng(chrono::steady_clock::now().time_since_epoch().count());\n    vector<Line> best_lines;\n    int best_real = -1;\n\n    // Phase 1: thorough attempt (2.4 s)\n    {\n        double t1 = min(2.4, TOTAL_TIME - elapsed());\n        mt19937 rng1(base_rng());\n        auto lines = run_attempt(rng1, t1, 400, 250);\n        if (!lines.empty()) {\n            int real = compute_real_score(lines);\n            if (real > best_real) {\n                best_real = real;\n                best_lines = std::move(lines);\n            }\n        }\n    }\n\n    // Phase 2: shorter trials until near time limit\n    int trial = 1;\n    while (elapsed() < TOTAL_TIME - 0.15) {\n        double remaining = TOTAL_TIME - elapsed();\n        double t2 = min(remaining, 0.35);\n        mt19937 rng2(base_rng() + trial * 12345);\n        auto lines = run_attempt(rng2, t2, 150, 120);\n        if (!lines.empty()) {\n            int real = compute_real_score(lines);\n            if (real > best_real) {\n                best_real = real;\n                best_lines = std::move(lines);\n            }\n        }\n        trial++;\n        if (best_real == total_attendees) break;\n    }\n\n    // Phase 3: final polish on best solution\n    if (!best_lines.empty() && best_real < total_attendees) {\n        double remaining = TOTAL_TIME - elapsed();\n        if (remaining > 0.03) {\n            local_search_improve(best_lines, remaining * 0.7, 200);\n            fine_tune_lines(best_lines, 0.05);\n        }\n    } else if (best_lines.empty()) {\n        mt19937 rng_fallback(chrono::steady_clock::now().time_since_epoch().count());\n        best_lines.push_back(random_line_through_cake(rng_fallback));\n    }\n\n    cout << best_lines.size() << \"\\n\";\n    for (const Line& L : best_lines) {\n        cout << L.p1x << \" \" << L.p1y << \" \" << L.p2x << \" \" << L.p2y << \"\\n\";\n    }\n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <array>\n#include <algorithm>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nstruct Pt { int x, y; };\n\nint main() {\n    auto global_start = chrono::steady_clock::now();\n    auto elapsed = [&]() { return chrono::duration<double>(chrono::steady_clock::now() - global_start).count(); };\n\n    int N, M;\n    cin >> N >> M;\n    vector<Pt> initial_dots(M);\n    for (int i = 0; i < M; ++i) cin >> initial_dots[i].x >> initial_dots[i].y;\n\n    int c = (N - 1) / 2;\n    vector<vector<int>> weight(N, vector<int>(N));\n    long long S = 0, initial_sum = 0;\n    for (int x = 0; x < N; ++x) for (int y = 0; y < N; ++y) {\n        weight[x][y] = (x - c) * (x - c) + (y - c) * (y - c) + 1;\n        S += weight[x][y];\n    }\n    for (auto& p : initial_dots) initial_sum += weight[p.x][p.y];\n\n    auto run_sim = [&](uint64_t seed) {\n        mt19937 rng(static_cast<unsigned int>(seed));\n\n        vector<vector<bool>> dot(N, vector<bool>(N, false));\n        vector<vector<bool>> used_h(N - 1, vector<bool>(N, false));\n        vector<vector<bool>> used_v(N, vector<bool>(N - 1, false));\n        vector<vector<bool>> used_d1(N - 1, vector<bool>(N - 1, false));\n        vector<vector<bool>> used_d2(N - 1, vector<bool>(N, false));\n        vector<vector<int>> row_dots(N), col_dots(N);\n        int diag_offs = N - 1;\n        vector<vector<int>> diag1(2 * N - 1), diag2(2 * N - 1);\n\n        for (auto& p : initial_dots) {\n            int x = p.x, y = p.y;\n            dot[x][y] = true;\n            row_dots[y].push_back(x);\n            col_dots[x].push_back(y);\n            int enc = y * N + x;\n            diag1[x - y + diag_offs].push_back(enc);\n            diag2[x + y].push_back(enc);\n        }\n        long long cur_sum = initial_sum;\n        vector<array<Pt, 4>> history;\n\n        auto segment_check = [&](Pt a, Pt b, bool check_only) -> bool {\n            int dx = b.x - a.x, dy = b.y - a.y;\n            int steps = max(abs(dx), abs(dy));\n            int sx = (dx == 0 ? 0 : (dx > 0 ? 1 : -1));\n            int sy = (dy == 0 ? 0 : (dy > 0 ? 1 : -1));\n            int cx = a.x, cy = a.y;\n            for (int s = 1; s <= steps; ++s) {\n                int nx = cx + sx, ny = cy + sy;\n                if (s < steps && dot[nx][ny]) return false;\n                if (sx != 0 && sy == 0) {\n                    int x = min(cx, nx), y = cy;\n                    if (check_only) { if (used_h[x][y]) return false; }\n                    else used_h[x][y] = true;\n                } else if (sx == 0 && sy != 0) {\n                    int x = cx, y = min(cy, ny);\n                    if (check_only) { if (used_v[x][y]) return false; }\n                    else used_v[x][y] = true;\n                } else if (sx == 1 && sy == 1) {\n                    if (check_only) { if (used_d1[cx][cy]) return false; }\n                    else used_d1[cx][cy] = true;\n                } else if (sx == -1 && sy == -1) {\n                    if (check_only) { if (used_d1[nx][ny]) return false; }\n                    else used_d1[nx][ny] = true;\n                } else if (sx == 1 && sy == -1) {\n                    if (check_only) { if (used_d2[cx][cy]) return false; }\n                    else used_d2[cx][cy] = true;\n                } else if (sx == -1 && sy == 1) {\n                    if (check_only) { if (used_d2[nx][ny]) return false; }\n                    else used_d2[nx][ny] = true;\n                } else return false;\n                cx = nx; cy = ny;\n            }\n            return true;\n        };\n\n        auto is_valid = [&](const array<Pt, 4>& p) {\n            if (dot[p[0].x][p[0].y]) return false;\n            if (!dot[p[1].x][p[1].y] || !dot[p[2].x][p[2].y] || !dot[p[3].x][p[3].y]) return false;\n            for (int i = 0; i < 4; ++i)\n                if (!segment_check(p[i], p[(i + 1) % 4], true)) return false;\n            return true;\n        };\n\n        auto apply_move = [&](const array<Pt, 4>& p) {\n            int x0 = p[0].x, y0 = p[0].y;\n            dot[x0][y0] = true;\n            row_dots[y0].push_back(x0);\n            col_dots[x0].push_back(y0);\n            int enc = y0 * N + x0;\n            diag1[x0 - y0 + diag_offs].push_back(enc);\n            diag2[x0 + y0].push_back(enc);\n            cur_sum += weight[x0][y0];\n            for (int i = 0; i < 4; ++i)\n                segment_check(p[i], p[(i + 1) % 4], false);\n        };\n\n        auto add_axis_small = [&](int x, int y, vector<array<Pt, 4>>& cands) {\n            if (x + 1 < N && y + 1 < N) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x + 1, y}, Pt{x + 1, y + 1}, Pt{x, y + 1}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n            if (x > 0 && y + 1 < N) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x, y + 1}, Pt{x - 1, y + 1}, Pt{x - 1, y}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n            if (x > 0 && y > 0) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x - 1, y}, Pt{x - 1, y - 1}, Pt{x, y - 1}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n            if (x + 1 < N && y > 0) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x, y - 1}, Pt{x + 1, y - 1}, Pt{x + 1, y}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n        };\n\n        auto add_diamond_small = [&](int x, int y, vector<array<Pt, 4>>& cands) {\n            if (x + 2 < N && y >= 1 && y + 1 < N) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x + 1, y + 1}, Pt{x + 2, y}, Pt{x + 1, y - 1}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n            if (x >= 1 && x + 1 < N && y >= 2) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x + 1, y - 1}, Pt{x, y - 2}, Pt{x - 1, y - 1}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n            if (x >= 2 && y >= 1 && y + 1 < N) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x - 1, y - 1}, Pt{x - 2, y}, Pt{x - 1, y + 1}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n            if (x >= 1 && x + 1 < N && y + 2 < N) {\n                array<Pt, 4> p = {Pt{x, y}, Pt{x - 1, y + 1}, Pt{x, y + 2}, Pt{x + 1, y + 1}};\n                if (is_valid(p)) cands.push_back(p);\n            }\n        };\n\n        auto add_axis_large = [&](int x1, int y1, vector<array<Pt, 4>>& cands) {\n            for (int x2 : row_dots[y1]) {\n                if (x2 == x1) continue;\n                for (int y2 : col_dots[x1]) {\n                    if (y2 == y1) continue;\n                    if (!dot[x2][y2]) continue;\n                    array<Pt, 4> p = {Pt{x1, y1}, Pt{x2, y1}, Pt{x2, y2}, Pt{x1, y2}};\n                    if (is_valid(p)) cands.push_back(p);\n                }\n            }\n        };\n\n        auto add_general_diamond = [&](int x1, int y1, vector<array<Pt, 4>>& cands) {\n            int d1 = x1 - y1 + diag_offs;\n            int d2 = x1 + y1;\n            const auto& list1 = diag1[d1];\n            const auto& list2 = diag2[d2];\n            for (int enc2 : list1) {\n                int x2 = enc2 % N, y2 = enc2 / N;\n                if (x2 == x1 && y2 == y1) continue;\n                for (int enc4 : list2) {\n                    int x4 = enc4 % N, y4 = enc4 / N;\n                    if (x4 == x1 && y4 == y1) continue;\n                    int x3 = x2 + x4 - x1;\n                    int y3 = y2 + y4 - y1;\n                    if (x3 < 0 || x3 >= N || y3 < 0 || y3 >= N) continue;\n                    if (!dot[x3][y3]) continue;\n                    array<Pt, 4> p = {Pt{x1, y1}, Pt{x2, y2}, Pt{x3, y3}, Pt{x4, y4}};\n                    if (is_valid(p)) cands.push_back(p);\n                }\n            }\n        };\n\n        while (true) {\n            // Time check: stop this simulation if total time is nearly exhausted\n            if (elapsed() > 4.85) break;\n\n            vector<array<Pt, 4>> cands;\n            // collect all small moves (axis\u2011aligned and diamond unit squares)\n            for (int x = 0; x < N; ++x)\n                for (int y = 0; y < N; ++y) {\n                    if (dot[x][y]) continue;\n                    add_axis_small(x, y, cands);\n                    add_diamond_small(x, y, cands);\n                }\n\n            // if no small move exists, generate larger moves from the highest\u2011weight empty cells\n            if (cands.empty()) {\n                vector<int> empty_idx;\n                for (int x = 0; x < N; ++x)\n                    for (int y = 0; y < N; ++y)\n                        if (!dot[x][y])\n                            empty_idx.push_back(y * N + x);\n\n                sort(empty_idx.begin(), empty_idx.end(), [&](int a, int b) {\n                    return weight[a % N][a / N] > weight[b % N][b / N];\n                });\n\n                const int MAX_LARGE_CANDS = 50;   // collect at most this many large candidates\n                for (int enc : empty_idx) {\n                    if ((int)cands.size() >= MAX_LARGE_CANDS) break;\n                    int x = enc % N, y = enc / N;\n                    add_axis_large(x, y, cands);\n                    if ((int)cands.size() >= MAX_LARGE_CANDS) break;\n                    add_general_diamond(x, y, cands);\n                }\n                if (cands.empty()) break;   // no moves left at all\n            }\n\n            // evaluate candidates\n            vector<int> w(cands.size());\n            for (size_t i = 0; i < cands.size(); ++i)\n                w[i] = weight[cands[i][0].x][cands[i][0].y];\n\n            int max_w = *max_element(w.begin(), w.end());\n            vector<int> best_idx;\n            for (size_t i = 0; i < cands.size(); ++i)\n                if (w[i] == max_w) best_idx.push_back(static_cast<int>(i));\n\n            int pick;\n            // 80% chance to pick among the best, 20% random\n            if (best_idx.size() == cands.size() || (rng() % 100) < 80) {\n                pick = best_idx[rng() % best_idx.size()];\n            } else {\n                pick = rng() % cands.size();\n            }\n\n            apply_move(cands[pick]);\n            history.push_back(cands[pick]);\n        }\n        return make_pair(cur_sum, history);\n    };\n\n    long long best_sum = -1;\n    vector<array<Pt, 4>> best_hist;\n    int sim = 0;\n    while (true) {\n        if (elapsed() > 4.85) break;\n        uint64_t seed = chrono::steady_clock::now().time_since_epoch().count() + sim * 12345;\n        auto [sum, hist] = run_sim(seed);\n        if (sum > best_sum) {\n            best_sum = sum;\n            best_hist = move(hist);\n        }\n        ++sim;\n    }\n\n    cout << best_hist.size() << \"\\n\";\n    for (auto& p : best_hist) {\n        cout << p[0].x << \" \" << p[0].y << \" \"\n             << p[1].x << \" \" << p[1].y << \" \"\n             << p[2].x << \" \" << p[2].y << \" \"\n             << p[3].x << \" \" << p[3].y << \"\\n\";\n    }\n    return 0;\n}","ahc015":"#include <iostream>\n#include <cstring>\n#include <algorithm>\nusing namespace std;\n\nconst char DIR[4] = {'F', 'B', 'L', 'R'};\n\n// ---------- fast xorshift RNG ----------\nstatic unsigned rng_state = 123456789u;\ninline int xrand() {\n    rng_state ^= rng_state << 13;\n    rng_state ^= rng_state >> 17;\n    rng_state ^= rng_state << 5;\n    return rng_state & 0x7fffffff;\n}\n\n// ---------- BFS for connected components ----------\nstatic int q[100];\nstatic int vis[100];\nstatic int vis_ver = 0;\n\nstatic int comp_id_buf[100];\nstatic int comp_size_buf[100];\nstatic int comp_count_buf;\n\ninline int bfs_with_components(const int* b) {\n    ++vis_ver;\n    comp_count_buf = 0;\n    int tot = 0;\n    for (int i = 0; i < 100; ++i) {\n        if (b[i] && vis[i] != vis_ver) {\n            int f = b[i];\n            int head = 0, tail = 0;\n            q[tail++] = i;\n            vis[i] = vis_ver;\n            int sz = 0;\n            while (head < tail) {\n                int idx = q[head++];\n                ++sz;\n                comp_id_buf[idx] = comp_count_buf;\n                int r = idx / 10, c = idx % 10;\n                if (r > 0) {\n                    int ni = idx - 10;\n                    if (b[ni] == f && vis[ni] != vis_ver) {\n                        vis[ni] = vis_ver; q[tail++] = ni;\n                    }\n                }\n                if (r < 9) {\n                    int ni = idx + 10;\n                    if (b[ni] == f && vis[ni] != vis_ver) {\n                        vis[ni] = vis_ver; q[tail++] = ni;\n                    }\n                }\n                if (c > 0) {\n                    int ni = idx - 1;\n                    if (b[ni] == f && vis[ni] != vis_ver) {\n                        vis[ni] = vis_ver; q[tail++] = ni;\n                    }\n                }\n                if (c < 9) {\n                    int ni = idx + 1;\n                    if (b[ni] == f && vis[ni] != vis_ver) {\n                        vis[ni] = vis_ver; q[tail++] = ni;\n                    }\n                }\n            }\n            comp_size_buf[comp_count_buf] = sz;\n            ++comp_count_buf;\n            tot += sz * sz;\n        }\n    }\n    return tot;\n}\n\n// ---------- tilt operation ----------\ninline void tilt(const int* src, int dir, int* dst) {\n    if (dir == 0) {  // Forward\n        for (int c = 0; c < 10; ++c) {\n            int d = 0;\n            for (int r = 0; r < 10; ++r) {\n                int v = src[r * 10 + c];\n                if (v) dst[d++ * 10 + c] = v;\n            }\n            for (; d < 10; ++d) dst[d * 10 + c] = 0;\n        }\n    } else if (dir == 1) {  // Backward\n        for (int c = 0; c < 10; ++c) {\n            int d = 9;\n            for (int r = 9; r >= 0; --r) {\n                int v = src[r * 10 + c];\n                if (v) dst[d-- * 10 + c] = v;\n            }\n            for (; d >= 0; --d) dst[d * 10 + c] = 0;\n        }\n    } else if (dir == 2) {  // Left\n        for (int r = 0; r < 10; ++r) {\n            int base = r * 10, d = 0;\n            for (int c = 0; c < 10; ++c) {\n                int v = src[base + c];\n                if (v) dst[base + d++] = v;\n            }\n            for (; d < 10; ++d) dst[base + d] = 0;\n        }\n    } else {  // Right\n        for (int r = 0; r < 10; ++r) {\n            int base = r * 10, d = 9;\n            for (int c = 9; c >= 0; --c) {\n                int v = src[base + c];\n                if (v) dst[base + d--] = v;\n            }\n            for (; d >= 0; --d) dst[base + d] = 0;\n        }\n    }\n}\n\n// ---------- global flavors and suffix counts ----------\nint flavors[100];\nint suff_counts[101][3];   // suff_counts[i][f] = count of flavor f+1 in [i, 99]\n\n// ---------- static future potential (no further tilts after current state) ----------\nstatic int cluster_seen[100];\nstatic int cluster_token = 0;\n\ndouble static_future(const int* board, int start_idx,\n                     const int* comp_id, const int* comp_size, int comp_count) {\n    int rem = 100 - start_idx;\n    if (rem == 0) return 0.0;\n    const int* remain_f = suff_counts[start_idx];\n\n    long long pot = 0;\n    ++cluster_token;\n    for (int i = 0; i < 100; ++i) {\n        if (board[i] == 0) {\n            int adj_sum[3] = {0, 0, 0};\n            int adj_sq[3] = {0, 0, 0};\n            int r = i / 10, c = i % 10;\n            // up\n            if (r > 0) {\n                int nb = i - 10;\n                if (board[nb]) {\n                    int cid = comp_id[nb];\n                    int f = board[nb] - 1;\n                    if (cluster_seen[cid] != cluster_token) {\n                        cluster_seen[cid] = cluster_token;\n                        int sz = comp_size[cid];\n                        adj_sum[f] += sz;\n                        adj_sq[f] += sz * sz;\n                    }\n                }\n            }\n            // down\n            if (r < 9) {\n                int nb = i + 10;\n                if (board[nb]) {\n                    int cid = comp_id[nb];\n                    int f = board[nb] - 1;\n                    if (cluster_seen[cid] != cluster_token) {\n                        cluster_seen[cid] = cluster_token;\n                        int sz = comp_size[cid];\n                        adj_sum[f] += sz;\n                        adj_sq[f] += sz * sz;\n                    }\n                }\n            }\n            // left\n            if (c > 0) {\n                int nb = i - 1;\n                if (board[nb]) {\n                    int cid = comp_id[nb];\n                    int f = board[nb] - 1;\n                    if (cluster_seen[cid] != cluster_token) {\n                        cluster_seen[cid] = cluster_token;\n                        int sz = comp_size[cid];\n                        adj_sum[f] += sz;\n                        adj_sq[f] += sz * sz;\n                    }\n                }\n            }\n            // right\n            if (c < 9) {\n                int nb = i + 1;\n                if (board[nb]) {\n                    int cid = comp_id[nb];\n                    int f = board[nb] - 1;\n                    if (cluster_seen[cid] != cluster_token) {\n                        cluster_seen[cid] = cluster_token;\n                        int sz = comp_size[cid];\n                        adj_sum[f] += sz;\n                        adj_sq[f] += sz * sz;\n                    }\n                }\n            }\n            for (int f = 0; f < 3; ++f) {\n                if (remain_f[f] > 0) {\n                    int inc = (adj_sum[f] > 0) ?\n                              (adj_sum[f] + 1) * (adj_sum[f] + 1) - adj_sq[f] : 1;\n                    pot += 1LL * inc * remain_f[f];\n                }\n            }\n        }\n    }\n    return (double)pot / rem;\n}\n\n// ---------- evaluate board b2 (after placing candy t+1 and tilting d1) ----------\ndouble evaluate_b2(int* b2, int t) {\n    int start_next = t + 2;         // first candy still to place on b2\n    int rem = 100 - start_next;\n    if (rem == 0) {\n        return (double) bfs_with_components(b2);\n    }\n    if (rem == 1) {\n        // exactly one candy left: place it, try all tilts, return max sum_sq\n        int e2 = -1;\n        for (int i = 0; i < 100; ++i) if (b2[i] == 0) { e2 = i; break; }\n        b2[e2] = flavors[start_next];\n        double best = -1e18;\n        for (int d2 = 0; d2 < 4; ++d2) {\n            int b3[100];\n            tilt(b2, d2, b3);\n            double v = bfs_with_components(b3);\n            if (v > best) best = v;\n        }\n        b2[e2] = 0;\n        return best;\n    }\n\n    // collect empty cells of b2\n    int empty2[100];\n    int n_empty2 = 0;\n    for (int i = 0; i < 100; ++i)\n        if (b2[i] == 0) empty2[n_empty2++] = i;\n\n    int K = min(3, n_empty2);       // sample at most 3 cells for candy t+2\n    double avg_max = 0.0;\n    int sampled[3] = {-1, -1, -1};\n\n    for (int s = 0; s < K; ++s) {\n        int idx;\n        do {\n            idx = xrand() % n_empty2;\n        } while ((s > 0 && idx == sampled[0]) ||\n                 (s > 1 && idx == sampled[1]));\n        sampled[s] = idx;\n        int e2 = empty2[idx];\n\n        b2[e2] = flavors[start_next];   // place candy t+2\n\n        double best_d2_val = -1e18;\n        for (int d2 = 0; d2 < 4; ++d2) {\n            int b3[100];\n            tilt(b2, d2, b3);\n\n            int b3_sq = bfs_with_components(b3);   // fills global comp_id_buf etc.\n            double future = static_future(b3, start_next + 1,\n                                          comp_id_buf, comp_size_buf, comp_count_buf);\n            double val = (double)b3_sq + future;\n            if (val > best_d2_val) best_d2_val = val;\n        }\n\n        avg_max += best_d2_val;\n        b2[e2] = 0;   // restore empty cell\n    }\n    return avg_max / K;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    // read flavors\n    for (int i = 0; i < 100; ++i) cin >> flavors[i];\n\n    // precompute suffix counts\n    for (int f = 0; f < 3; ++f) suff_counts[100][f] = 0;\n    for (int i = 99; i >= 0; --i) {\n        for (int f = 0; f < 3; ++f) suff_counts[i][f] = suff_counts[i+1][f];\n        suff_counts[i][flavors[i] - 1]++;\n    }\n\n    int board[100] = {0};\n\n    const int SAMPLE1_LIMIT = 16;   // max empty cells to sample for candy t+1\n\n    for (int t = 0; t < 100; ++t) {\n        int p;\n        cin >> p;\n\n        // place the candy in the p-th empty cell (1-indexed, front-to-back, left-to-right)\n        int pos = -1, empty_cnt = 0;\n        for (int i = 0; i < 100; ++i) {\n            if (board[i] == 0) {\n                ++empty_cnt;\n                if (empty_cnt == p) { pos = i; break; }\n            }\n        }\n        board[pos] = flavors[t];\n\n        if (t == 99) {   // last move, output anything and finish\n            cout << \"F\\n\" << flush;\n            break;\n        }\n\n        int next_f = flavors[t + 1];\n        int best_dir = 0;\n        double best_val = -1e18;\n\n        for (int d0 = 0; d0 < 4; ++d0) {\n            int b1[100];\n            tilt(board, d0, b1);\n\n            // collect empty cells in b1\n            int empty1[100];\n            int n_empty1 = 0;\n            for (int i = 0; i < 100; ++i)\n                if (b1[i] == 0) empty1[n_empty1++] = i;\n\n            double val = 0.0;\n            if (n_empty1 == 0) {\n                val = (double) bfs_with_components(b1);\n            } else {\n                int sample_cnt = min(n_empty1, SAMPLE1_LIMIT);\n                int sampled_empty[16];\n                if (sample_cnt == n_empty1) {\n                    for (int i = 0; i < n_empty1; ++i) sampled_empty[i] = i;\n                } else {\n                    int used[100] = {0};\n                    for (int i = 0; i < sample_cnt; ++i) {\n                        int idx;\n                        do {\n                            idx = xrand() % n_empty1;\n                        } while (used[idx]);\n                        used[idx] = 1;\n                        sampled_empty[i] = idx;\n                    }\n                }\n\n                for (int i = 0; i < sample_cnt; ++i) {\n                    int e1 = empty1[sampled_empty[i]];\n                    b1[e1] = next_f;   // temporarily place next candy\n\n                    double best_d1_val = -1e18;\n                    for (int d1 = 0; d1 < 4; ++d1) {\n                        int b2[100];\n                        tilt(b1, d1, b2);\n                        double v = evaluate_b2(b2, t);\n                        if (v > best_d1_val) best_d1_val = v;\n                    }\n\n                    val += best_d1_val;\n                    b1[e1] = 0;   // restore\n                }\n                val /= sample_cnt;\n            }\n\n            if (val > best_val) {\n                best_val = val;\n                best_dir = d0;\n            }\n        }\n\n        cout << DIR[best_dir] << '\\n' << flush;\n\n        // apply the chosen tilt to the real board\n        int nb[100];\n        tilt(board, best_dir, nb);\n        memcpy(board, nb, sizeof(board));\n    }\n\n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <numeric>\n#include <map>\n\nusing namespace std;\nusing namespace chrono;\n\n// ---------- Threshold graph utilities ----------\nvector<int> threshold_degrees(const vector<int>& c) {\n    int N = (int)c.size();\n    vector<int> deg(N, 0);\n    int suffix = 0;\n    for (int i = N - 1; i >= 0; --i) {\n        if (c[i]) {\n            deg[i] = i + suffix;\n            suffix++;\n        } else {\n            deg[i] = suffix;\n        }\n    }\n    sort(deg.begin(), deg.end(), greater<int>());\n    return deg;\n}\n\nstring threshold_adj_string(const vector<int>& c) {\n    int N = (int)c.size();\n    int L = N * (N - 1) / 2;\n    string adj(L, '0');\n    int pos = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = i + 1; j < N; ++j) {\n            if (c[j] == 1) adj[pos] = '1';\n            ++pos;\n        }\n    return adj;\n}\n\nvector<vector<bool>> threshold_adj_matrix(const vector<int>& c) {\n    int N = (int)c.size();\n    vector<vector<bool>> mat(N, vector<bool>(N, false));\n    for (int i = 0; i < N; ++i)\n        for (int j = i + 1; j < N; ++j)\n            if (c[j] == 1)\n                mat[i][j] = mat[j][i] = true;\n    return mat;\n}\n\nint l1_dist(const vector<int>& a, const vector<int>& b) {\n    int d = 0;\n    for (size_t i = 0; i < a.size(); ++i)\n        d += abs(a[i] - b[i]);\n    return d;\n}\n\n// ---------- Greedy selection with minimum distance ----------\nbool greedy_select(const vector<vector<int>>& pool_deg, int M, int D_min,\n                   vector<int>& selected_idx, mt19937& rng) {\n    int P = (int)pool_deg.size();\n    vector<int> order(P);\n    iota(order.begin(), order.end(), 0);\n    for (int attempt = 0; attempt < 5; ++attempt) {\n        shuffle(order.begin(), order.end(), rng);\n        selected_idx.clear();\n        for (int idx : order) {\n            bool ok = true;\n            for (int sel : selected_idx) {\n                if (l1_dist(pool_deg[idx], pool_deg[sel]) < D_min) {\n                    ok = false;\n                    break;\n                }\n            }\n            if (ok) {\n                selected_idx.push_back(idx);\n                if ((int)selected_idx.size() == M) return true;\n            }\n        }\n    }\n    return false;\n}\n\n// ---------- Max-min diversification (fallback) ----------\nvector<int> maxmin_select(const vector<vector<int>>& pool_deg, int M, mt19937& rng) {\n    int P = (int)pool_deg.size();\n    vector<int> dist(P, 1e9);\n    vector<int> selected;\n    selected.reserve(M);\n    int first = uniform_int_distribution<int>(0, P - 1)(rng);\n    selected.push_back(first);\n    for (int i = 0; i < P; ++i)\n        if (i != first) dist[i] = l1_dist(pool_deg[first], pool_deg[i]);\n    for (int k = 1; k < M; ++k) {\n        int best = 0;\n        for (int i = 1; i < P; ++i)\n            if (dist[i] > dist[best]) best = i;\n        selected.push_back(best);\n        for (int i = 0; i < P; ++i) {\n            int d = l1_dist(pool_deg[best], pool_deg[i]);\n            if (d < dist[i]) dist[i] = d;\n        }\n    }\n    return selected;\n}\n\n// ---------- Simulation ----------\nint simulate(const vector<vector<int>>& target_degs,\n             const vector<vector<vector<bool>>>& mats,\n             int N, double eps, int trials, mt19937& rng) {\n    int M = (int)target_degs.size();\n    uniform_real_distribution<double> flip_dist(0.0, 1.0);\n    uniform_int_distribution<int> s_dist(0, M - 1);\n    int errors = 0;\n    for (int q = 0; q < trials; ++q) {\n        int s = s_dist(rng);\n        auto noisy = mats[s];\n        // noise\n        for (int i = 0; i < N; ++i)\n            for (int j = i + 1; j < N; ++j)\n                if (flip_dist(rng) < eps) {\n                    noisy[i][j] = !noisy[i][j];\n                    noisy[j][i] = noisy[i][j];\n                }\n        // compute degree sequence (permutation irrelevant)\n        vector<int> deg(N, 0);\n        for (int i = 0; i < N; ++i)\n            for (int j = i + 1; j < N; ++j)\n                if (noisy[i][j]) {\n                    ++deg[i];\n                    ++deg[j];\n                }\n        sort(deg.begin(), deg.end(), greater<int>());\n        // nearest neighbour\n        int best = 0, best_d = 1e9;\n        for (int t = 0; t < M; ++t) {\n            int d = l1_dist(deg, target_degs[t]);\n            if (d < best_d) {\n                best_d = d;\n                best = t;\n            }\n        }\n        if (best != s) ++errors;\n    }\n    return errors;\n}\n\n// ---------- Main ----------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    double eps;\n    cin >> M >> eps;\n\n    // special case M == 1\n    if (M == 1) {\n        cout << 4 << \"\\n\";\n        cout << \"000000\\n\";\n        cout.flush();\n        for (int q = 0; q < 100; ++q) {\n            string H;\n            cin >> H;\n            cout << 0 << \"\\n\";\n            cout.flush();\n        }\n        return 0;\n    }\n\n    mt19937 base_rng(random_device{}());\n    auto start_time = steady_clock::now();\n    const auto deadline = start_time + milliseconds(4600);\n\n    double best_score = -1.0;\n    int best_N = 0;\n    vector<vector<int>> best_c;\n    vector<vector<int>> best_degs;\n    vector<string> best_adj;\n\n    // candidate N sorted by maximum possible score (1e9 / N) descending\n    vector<int> N_cand;\n    for (int N = 4; N <= 100; ++N) N_cand.push_back(N);\n    sort(N_cand.begin(), N_cand.end(),\n         [](int a, int b) { return (1e9 / a) > (1e9 / b); });\n\n    for (int N : N_cand) {\n        auto now = steady_clock::now();\n        if (now > deadline) break;\n        double max_potential = 1e9 / N;\n        if (best_score >= 0 && max_potential <= best_score)\n            break;   // no larger score achievable\n\n        int L = N * (N - 1) / 2;\n        double sigma = 2.0 * sqrt(L * eps * (1.0 - eps) + 1e-12);\n\n        // ----- Build pool of distinct threshold degree sequences -----\n        vector<vector<int>> unique_deg;\n        vector<vector<int>> unique_c;\n        if (N <= 14) {   // full enumeration\n            int total = 1 << (N - 1);\n            map<vector<int>, int> seen;\n            for (int mask = 0; mask < total; ++mask) {\n                vector<int> c(N, 0);\n                for (int j = 1; j < N; ++j)\n                    if (mask & (1 << (j - 1))) c[j] = 1;\n                vector<int> deg = threshold_degrees(c);\n                if (seen.emplace(deg, (int)unique_c.size()).second) {\n                    unique_deg.push_back(move(deg));\n                    unique_c.push_back(move(c));\n                }\n            }\n        } else {\n            int pool_size = min(25000, 10000 + M * 50);\n            map<vector<int>, int> seen;\n            for (int i = 0; i < pool_size; ++i) {\n                vector<int> c(N, 0);\n                for (int j = 1; j < N; ++j)\n                    c[j] = uniform_int_distribution<int>(0, 1)(base_rng);\n                vector<int> deg = threshold_degrees(c);\n                if (seen.emplace(deg, (int)unique_c.size()).second) {\n                    unique_deg.push_back(move(deg));\n                    unique_c.push_back(move(c));\n                }\n            }\n        }\n        if ((int)unique_deg.size() < M) continue;\n\n        // ----- Try to select M graphs with required minimum distance -----\n        vector<vector<int>> c_vecs;\n        vector<vector<int>> target_degs;\n        bool found = false;\n        for (int mult = 20; mult >= 2; --mult) {\n            int D_min = max(1, (int)ceil(mult * sigma));\n            vector<int> selected_idx;\n            if (greedy_select(unique_deg, M, D_min, selected_idx, base_rng)) {\n                c_vecs.resize(M);\n                target_degs.resize(M);\n                for (int i = 0; i < M; ++i) {\n                    c_vecs[i] = unique_c[selected_idx[i]];\n                    target_degs[i] = unique_deg[selected_idx[i]];\n                }\n                found = true;\n                break;\n            }\n        }\n        if (!found) {\n            // fallback to max-min\n            vector<int> idx = maxmin_select(unique_deg, M, base_rng);\n            c_vecs.resize(M);\n            target_degs.resize(M);\n            for (int i = 0; i < M; ++i) {\n                c_vecs[i] = unique_c[idx[i]];\n                target_degs[i] = unique_deg[idx[i]];\n            }\n        }\n\n        // ----- Compute minimum distance and quick score estimate -----\n        int d_min = 1e9;\n        for (int i = 0; i < M; ++i)\n            for (int j = i + 1; j < M; ++j)\n                d_min = min(d_min, l1_dist(target_degs[i], target_degs[j]));\n\n        double var_est = 16.0 * L * eps * (1.0 - eps) + 1e-9;\n        double p_err = exp(-(double)(d_min * d_min) / var_est);\n        double est_E = min(100.0, 100.0 * M * p_err);\n        double score_est = round(1e9 * pow(0.9, est_E) / N);\n\n        if (score_est <= best_score) continue;   // unlikely to beat best\n\n        // ----- Quick simulation -----\n        vector<vector<vector<bool>>> mats(M);\n        for (int i = 0; i < M; ++i)\n            mats[i] = threshold_adj_matrix(c_vecs[i]);\n\n        auto time_left = deadline - steady_clock::now();\n        int sim_q = min(50, max(5, (int)(time_left.count() / 1'500'000)));\n        if (sim_q < 3) sim_q = 3;\n        int errors = simulate(target_degs, mats, N, eps, sim_q, base_rng);\n        double sim_E = (double)errors * 100.0 / sim_q;\n        double score = round(1e9 * pow(0.9, sim_E) / N);\n\n        if (score > best_score) {\n            best_score = score;\n            best_N = N;\n            best_c = move(c_vecs);\n            best_degs = move(target_degs);\n            best_adj.resize(M);\n            for (int i = 0; i < M; ++i)\n                best_adj[i] = threshold_adj_string(best_c[i]);\n        }\n    }\n\n    // fallback (should not happen)\n    if (best_c.empty()) {\n        best_N = 20;\n        best_c.resize(M, vector<int>(best_N, 0));\n        for (int k = 0; k < M; ++k)\n            for (int i = 1; i < best_N; ++i)\n                best_c[k][i] = (k >> (i % 7)) & 1;\n        best_degs.resize(M);\n        best_adj.resize(M);\n        for (int i = 0; i < M; ++i) {\n            best_degs[i] = threshold_degrees(best_c[i]);\n            best_adj[i] = threshold_adj_string(best_c[i]);\n        }\n    }\n\n    // ----- Output chosen graphs -----\n    cout << best_N << \"\\n\";\n    for (const auto& s : best_adj)\n        cout << s << \"\\n\";\n    cout.flush();\n\n    // ----- Answer 100 queries -----\n    for (int q = 0; q < 100; ++q) {\n        string H_str;\n        cin >> H_str;\n        if (H_str.empty()) break;\n\n        vector<int> h_deg(best_N, 0);\n        int pos = 0;\n        for (int i = 0; i < best_N; ++i)\n            for (int j = i + 1; j < best_N; ++j) {\n                if (H_str[pos] == '1') {\n                    ++h_deg[i];\n                    ++h_deg[j];\n                }\n                ++pos;\n            }\n        sort(h_deg.begin(), h_deg.end(), greater<int>());\n\n        int best_t = 0, best_d = 1e9;\n        for (int t = 0; t < M; ++t) {\n            int d = l1_dist(h_deg, best_degs[t]);\n            if (d < best_d) {\n                best_d = d;\n                best_t = t;\n            }\n        }\n        cout << best_t << \"\\n\";\n        cout.flush();\n    }\n\n    return 0;\n}","ahc017":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <chrono>\n#include <limits>\n#include <tuple>\nusing namespace std;\nusing ll = long long;\n\nconst int INF = 1'000'000'000;\n\nint main() {\n    auto start_time = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count();\n    };\n    \n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n    vector<int> U(M), V(M), W(M);\n    vector<vector<tuple<int,int,int>>> orig_adj(N); // to, weight, edge_id\n    vector<int> edge_idx(N*N, -1);\n    for (int i = 0; i < M; ++i) {\n        cin >> U[i] >> V[i] >> W[i];\n        --U[i]; --V[i];\n        orig_adj[U[i]].emplace_back(V[i], W[i], i);\n        orig_adj[V[i]].emplace_back(U[i], W[i], i);\n        edge_idx[U[i]*N + V[i]] = i;\n        edge_idx[V[i]*N + U[i]] = i;\n    }\n    // read and ignore coordinates\n    int dummy;\n    for (int i = 0; i < N; ++i) cin >> dummy >> dummy;\n    \n    // Compute original all-pairs shortest paths and edge centralities\n    vector<int> orig(N*N, INF);\n    vector<ll> cnt(M, 0);\n    vector<int> dist(N);\n    priority_queue<pair<int,int>, vector<pair<int,int>>, greater<>> pq;\n    \n    for (int s = 0; s < N; ++s) {\n        fill(dist.begin(), dist.end(), INF);\n        vector<int> parent_node(N, -1);\n        vector<int> parent_edge(N, -1);\n        dist[s] = 0;\n        pq.push({0, s});\n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop();\n            if (d != dist[u]) continue;\n            for (auto &edge : orig_adj[u]) {\n                int v = get<0>(edge), w = get<1>(edge), eid = get<2>(edge);\n                if (dist[v] > d + w) {\n                    dist[v] = d + w;\n                    parent_node[v] = u;\n                    parent_edge[v] = eid;\n                    pq.push({dist[v], v});\n                }\n            }\n        }\n        for (int t = 0; t < N; ++t) {\n            orig[s*N + t] = dist[t];\n        }\n        // compute subtree sizes for centrality\n        vector<int> sub(N, 1);\n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) { return dist[a] > dist[b]; });\n        for (int v : order) {\n            if (v == s) continue;\n            int p = parent_node[v];\n            if (p != -1) {\n                sub[p] += sub[v];\n                if (parent_edge[v] != -1) {\n                    cnt[parent_edge[v]] += sub[v];\n                }\n            }\n        }\n    }\n    \n    // Greedy assignment based on cnt\n    vector<int> assign(M, -1);\n    vector<int> day_cnt(D, 0);\n    vector<ll> day_sum_cnt(D, 0);\n    vector<int> sorted_edges(M);\n    iota(sorted_edges.begin(), sorted_edges.end(), 0);\n    sort(sorted_edges.begin(), sorted_edges.end(), [&](int a, int b) { return cnt[a] > cnt[b]; });\n    for (int e : sorted_edges) {\n        int best_d = -1;\n        ll best_sum = numeric_limits<ll>::max();\n        for (int d = 0; d < D; ++d) {\n            if (day_cnt[d] < K && day_sum_cnt[d] < best_sum) {\n                best_sum = day_sum_cnt[d];\n                best_d = d;\n            }\n        }\n        assign[e] = best_d;\n        day_cnt[best_d]++;\n        day_sum_cnt[best_d] += cnt[e];\n    }\n    \n    // Store day edges\n    vector<vector<int>> day_edges(D);\n    for (int e = 0; e < M; ++e) {\n        day_edges[assign[e]].push_back(e);\n    }\n    \n    // Exact evaluation helper\n    vector<bool> removed(M);\n    auto compute_day_dist = [&](const vector<int>& removed_edges, vector<int>& out_dist, ll& out_diff) {\n        fill(removed.begin(), removed.end(), false);\n        for (int e : removed_edges) removed[e] = true;\n        out_dist.assign(N*N, INF);\n        out_diff = 0;\n        for (int s = 0; s < N; ++s) {\n            fill(dist.begin(), dist.end(), INF);\n            dist[s] = 0;\n            pq.push({0, s});\n            while (!pq.empty()) {\n                auto [d, u] = pq.top(); pq.pop();\n                if (d != dist[u]) continue;\n                for (auto &edge : orig_adj[u]) {\n                    int v = get<0>(edge), w = get<1>(edge), eid = get<2>(edge);\n                    if (removed[eid]) continue;\n                    if (dist[v] > d + w) {\n                        dist[v] = d + w;\n                        pq.push({dist[v], v});\n                    }\n                }\n            }\n            int base = s * N;\n            for (int t = 0; t < N; ++t) {\n                out_dist[base + t] = dist[t];\n            }\n            for (int t = s+1; t < N; ++t) {\n                out_diff += dist[t] - orig[base + t];\n            }\n        }\n    };\n    \n    // Initial exact evaluation\n    vector<vector<int>> day_dist(D);\n    vector<ll> day_diff(D, 0);\n    ll total_diff = 0;\n    for (int d = 0; d < D; ++d) {\n        compute_day_dist(day_edges[d], day_dist[d], day_diff[d]);\n        total_diff += day_diff[d];\n    }\n    ll best_total_diff = total_diff;\n    vector<int> best_assign = assign;\n    \n    // Local search\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> real_dist(0.0, 1.0);\n    \n    const int TIME_LIMIT_MS = 5800;\n    while (elapsed() < TIME_LIMIT_MS) {\n        // Pick a day A weighted by day_diff\n        ll sum_weights = accumulate(day_diff.begin(), day_diff.end(), 0LL);\n        int A;\n        if (sum_weights > 0) {\n            discrete_distribution<int> day_sel(day_diff.begin(), day_diff.end());\n            A = day_sel(rng);\n        } else {\n            uniform_int_distribution<int> unif(0, D-1);\n            A = unif(rng);\n        }\n        if (day_edges[A].empty()) continue;\n        \n        // Pick a random edge in A\n        uniform_int_distribution<int> edge_sel_A(0, (int)day_edges[A].size() - 1);\n        int e = day_edges[A][edge_sel_A(rng)];\n        \n        // Pick a random B != A with capacity\n        vector<int> candidates;\n        for (int d = 0; d < D; ++d) {\n            if (d != A && day_cnt[d] < K) candidates.push_back(d);\n        }\n        if (candidates.empty()) continue;\n        uniform_int_distribution<int> cand_sel(0, (int)candidates.size() - 1);\n        int B = candidates[cand_sel(rng)];\n        \n        // Evaluate move: remove e from A, add e to B\n        vector<int> new_A_edges = day_edges[A];\n        new_A_edges.erase(remove(new_A_edges.begin(), new_A_edges.end(), e), new_A_edges.end());\n        vector<int> new_dA;\n        ll new_diffA;\n        compute_day_dist(new_A_edges, new_dA, new_diffA);\n        \n        // New B: S_B U {e} (incremental update)\n        vector<int> oldB = day_dist[B];\n        vector<int> new_dB = oldB;\n        int u = U[e], v = V[e], w = W[e];\n        for (int i = 0; i < N; ++i) {\n            int iu = oldB[i*N + u];\n            int iv = oldB[i*N + v];\n            int base_i = i * N;\n            for (int j = 0; j < N; ++j) {\n                int idx = base_i + j;\n                int via_u = iu + w + oldB[v*N + j];\n                int via_v = iv + w + oldB[u*N + j];\n                if (via_u < new_dB[idx]) new_dB[idx] = via_u;\n                if (via_v < new_dB[idx]) new_dB[idx] = via_v;\n            }\n        }\n        ll new_diffB = 0;\n        for (int i = 0; i < N; ++i) {\n            int base = i * N;\n            for (int j = i+1; j < N; ++j) {\n                new_diffB += new_dB[base + j] - orig[base + j];\n            }\n        }\n        \n        ll new_total_diff = total_diff - day_diff[A] - day_diff[B] + new_diffA + new_diffB;\n        if (new_total_diff < total_diff) {\n            // Accept move\n            assign[e] = B;\n            day_cnt[A]--;\n            day_cnt[B]++;\n            auto &vecA = day_edges[A];\n            vecA.erase(remove(vecA.begin(), vecA.end(), e), vecA.end());\n            day_edges[B].push_back(e);\n            day_dist[A] = move(new_dA);\n            day_dist[B] = move(new_dB);\n            day_diff[A] = new_diffA;\n            day_diff[B] = new_diffB;\n            total_diff = new_total_diff;\n            if (total_diff < best_total_diff) {\n                best_total_diff = total_diff;\n                best_assign = assign;\n            }\n        }\n    }\n    \n    // Output best assignment\n    for (int i = 0; i < M; ++i) {\n        if (i) cout << \" \";\n        cout << best_assign[i] + 1;\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc019":"#include <iostream>\n#include <vector>\n#include <string>\n#include <tuple>\n#include <algorithm>\n\nusing namespace std;\n\nconst int perms[6][3] = {{0,1,2},{0,2,1},{1,0,2},{1,2,0},{2,0,1},{2,1,0}};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D;\n    cin >> D;\n    vector<string> f[2], r[2];\n    for (int i = 0; i < 2; i++) {\n        f[i].resize(D);\n        for (int k = 0; k < D; k++) cin >> f[i][k];\n        r[i].resize(D);\n        for (int k = 0; k < D; k++) cin >> r[i][k];\n    }\n\n    int total = D * D * D;\n    vector<bool> allowed[2], used[2];\n    vector<vector<bool>> uncov_f[2], uncov_r[2];\n    vector<int> bid[2];\n\n    for (int i = 0; i < 2; i++) {\n        allowed[i].assign(total, false);\n        used[i].assign(total, false);\n        uncov_f[i].assign(D, vector<bool>(D, false));\n        uncov_r[i].assign(D, vector<bool>(D, false));\n        bid[i].assign(total, 0);\n    }\n\n    auto idx = [&](int x, int y, int z) {\n        return x * D * D + y * D + z;\n    };\n\n    // Initialize allowed and uncovered\n    for (int i = 0; i < 2; i++) {\n        for (int z = 0; z < D; z++) {\n            for (int x = 0; x < D; x++) {\n                if (f[i][z][x] == '1') uncov_f[i][z][x] = true;\n            }\n            for (int y = 0; y < D; y++) {\n                if (r[i][z][y] == '1') uncov_r[i][z][y] = true;\n            }\n        }\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                for (int z = 0; z < D; z++) {\n                    if (f[i][z][x] == '1' && r[i][z][y] == '1') {\n                        allowed[i][idx(x, y, z)] = true;\n                    }\n                }\n            }\n        }\n    }\n\n    auto can_place = [&](int i, int x0, int y0, int z0, int dx, int dy, int dz) {\n        for (int x = x0; x < x0 + dx; x++)\n            for (int y = y0; y < y0 + dy; y++)\n                for (int z = z0; z < z0 + dz; z++)\n                    if (!allowed[i][idx(x, y, z)] || used[i][idx(x, y, z)])\n                        return false;\n        return true;\n    };\n\n    auto count_covered = [&](int i, int x0, int y0, int z0, int dx, int dy, int dz) {\n        bool fc[14][14] = {false}, rc[14][14] = {false};\n        for (int x = x0; x < x0 + dx; x++)\n            for (int y = y0; y < y0 + dy; y++)\n                for (int z = z0; z < z0 + dz; z++) {\n                    if (uncov_f[i][z][x]) fc[z][x] = true;\n                    if (uncov_r[i][z][y]) rc[z][y] = true;\n                }\n        int cnt = 0;\n        for (int z = 0; z < D; z++) for (int x = 0; x < D; x++) if (fc[z][x]) cnt++;\n        for (int z = 0; z < D; z++) for (int y = 0; y < D; y++) if (rc[z][y]) cnt++;\n        return cnt;\n    };\n\n    auto apply_placement = [&](int i, int x0, int y0, int z0, int dx, int dy, int dz, int b_id) {\n        for (int x = x0; x < x0 + dx; x++)\n            for (int y = y0; y < y0 + dy; y++)\n                for (int z = z0; z < z0 + dz; z++) {\n                    int id = idx(x, y, z);\n                    used[i][id] = true;\n                    bid[i][id] = b_id;\n                    uncov_f[i][z][x] = false;\n                    uncov_r[i][z][y] = false;\n                }\n    };\n\n    // Expand a box greedily in all directions (maximal)\n    auto compute_maximal_box = [&](int i, int sx, int sy, int sz,\n                                   int &x0, int &y0, int &z0, int &dx, int &dy, int &dz) {\n        x0 = sx; y0 = sy; z0 = sz;\n        int x1 = sx, y1 = sy, z1 = sz;\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            // -x\n            while (x0 > 0) {\n                bool ok = true;\n                for (int y = y0; y <= y1 && ok; y++)\n                    for (int z = z0; z <= z1 && ok; z++)\n                        if (!allowed[i][idx(x0-1, y, z)] || used[i][idx(x0-1, y, z)]) ok = false;\n                if (ok) { x0--; changed = true; } else break;\n            }\n            // +x\n            while (x1 < D-1) {\n                bool ok = true;\n                for (int y = y0; y <= y1 && ok; y++)\n                    for (int z = z0; z <= z1 && ok; z++)\n                        if (!allowed[i][idx(x1+1, y, z)] || used[i][idx(x1+1, y, z)]) ok = false;\n                if (ok) { x1++; changed = true; } else break;\n            }\n            // -y\n            while (y0 > 0) {\n                bool ok = true;\n                for (int x = x0; x <= x1 && ok; x++)\n                    for (int z = z0; z <= z1 && ok; z++)\n                        if (!allowed[i][idx(x, y0-1, z)] || used[i][idx(x, y0-1, z)]) ok = false;\n                if (ok) { y0--; changed = true; } else break;\n            }\n            // +y\n            while (y1 < D-1) {\n                bool ok = true;\n                for (int x = x0; x <= x1 && ok; x++)\n                    for (int z = z0; z <= z1 && ok; z++)\n                        if (!allowed[i][idx(x, y1+1, z)] || used[i][idx(x, y1+1, z)]) ok = false;\n                if (ok) { y1++; changed = true; } else break;\n            }\n            // -z\n            while (z0 > 0) {\n                bool ok = true;\n                for (int x = x0; x <= x1 && ok; x++)\n                    for (int y = y0; y <= y1 && ok; y++)\n                        if (!allowed[i][idx(x, y, z0-1)] || used[i][idx(x, y, z0-1)]) ok = false;\n                if (ok) { z0--; changed = true; } else break;\n            }\n            // +z\n            while (z1 < D-1) {\n                bool ok = true;\n                for (int x = x0; x <= x1 && ok; x++)\n                    for (int y = y0; y <= y1 && ok; y++)\n                        if (!allowed[i][idx(x, y, z1+1)] || used[i][idx(x, y, z1+1)]) ok = false;\n                if (ok) { z1++; changed = true; } else break;\n            }\n        }\n        dx = x1 - x0 + 1;\n        dy = y1 - y0 + 1;\n        dz = z1 - z0 + 1;\n    };\n\n    auto find_placement_any = [&](int i, int dx0, int dy0, int dz0,\n                                  int &bx0, int &by0, int &bz0, int &bdx, int &bdy, int &bdz) {\n        int dims[3] = {dx0, dy0, dz0};\n        for (auto &p : perms) {\n            int gdx = dims[p[0]], gdy = dims[p[1]], gdz = dims[p[2]];\n            for (int x0 = 0; x0 <= D - gdx; x0++) {\n                for (int y0 = 0; y0 <= D - gdy; y0++) {\n                    for (int z0 = 0; z0 <= D - gdz; z0++) {\n                        if (can_place(i, x0, y0, z0, gdx, gdy, gdz)) {\n                            bx0 = x0; by0 = y0; bz0 = z0;\n                            bdx = gdx; bdy = gdy; bdz = gdz;\n                            return true;\n                        }\n                    }\n                }\n            }\n        }\n        return false;\n    };\n\n    auto find_best_placement = [&](int i, int dx0, int dy0, int dz0,\n                                   int &bx0, int &by0, int &bz0, int &bdx, int &bdy, int &bdz,\n                                   int &best_cc) {\n        best_cc = -1;\n        bool found = false;\n        int dims[3] = {dx0, dy0, dz0};\n        for (auto &p : perms) {\n            int gdx = dims[p[0]], gdy = dims[p[1]], gdz = dims[p[2]];\n            for (int x0 = 0; x0 <= D - gdx; x0++) {\n                for (int y0 = 0; y0 <= D - gdy; y0++) {\n                    for (int z0 = 0; z0 <= D - gdz; z0++) {\n                        if (can_place(i, x0, y0, z0, gdx, gdy, gdz)) {\n                            int cc = count_covered(i, x0, y0, z0, gdx, gdy, gdz);\n                            if (cc > best_cc) {\n                                best_cc = cc;\n                                bx0 = x0; by0 = y0; bz0 = z0;\n                                bdx = gdx; bdy = gdy; bdz = gdz;\n                                found = true;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        return found;\n    };\n\n    struct Block { int dx, dy, dz; };\n    vector<Block> blocks;\n\n    // Phase 1: place shared blocks greedily\n    while (true) {\n        int uncov_cnt[2] = {0, 0};\n        for (int i = 0; i < 2; i++) {\n            for (int z = 0; z < D; z++) {\n                for (int x = 0; x < D; x++) if (uncov_f[i][z][x]) uncov_cnt[i]++;\n                for (int y = 0; y < D; y++) if (uncov_r[i][z][y]) uncov_cnt[i]++;\n            }\n        }\n        if (uncov_cnt[0] == 0 && uncov_cnt[1] == 0) break;\n\n        struct Seed {\n            int i, sx, sy, sz;\n            int x0, y0, z0, dx, dy, dz;\n            int cci;\n        };\n        vector<Seed> seeds;\n\n        for (int i = 0; i < 2; i++) {\n            if (uncov_cnt[i] == 0) continue;\n            // collect one seed per uncovered column\n            for (int z = 0; z < D; z++) {\n                for (int x = 0; x < D; x++) {\n                    if (uncov_f[i][z][x]) {\n                        for (int y = 0; y < D; y++) {\n                            if (allowed[i][idx(x, y, z)] && !used[i][idx(x, y, z)]) {\n                                int x0, y0, z0, dx, dy, dz;\n                                compute_maximal_box(i, x, y, z, x0, y0, z0, dx, dy, dz);\n                                int cci = count_covered(i, x0, y0, z0, dx, dy, dz);\n                                if (cci > 0)\n                                    seeds.push_back({i, x, y, z, x0, y0, z0, dx, dy, dz, cci});\n                                break;\n                            }\n                        }\n                    }\n                }\n            }\n            for (int z = 0; z < D; z++) {\n                for (int y = 0; y < D; y++) {\n                    if (uncov_r[i][z][y]) {\n                        for (int x = 0; x < D; x++) {\n                            if (allowed[i][idx(x, y, z)] && !used[i][idx(x, y, z)]) {\n                                int x0, y0, z0, dx, dy, dz;\n                                compute_maximal_box(i, x, y, z, x0, y0, z0, dx, dy, dz);\n                                int cci = count_covered(i, x0, y0, z0, dx, dy, dz);\n                                if (cci > 0)\n                                    seeds.push_back({i, x, y, z, x0, y0, z0, dx, dy, dz, cci});\n                                break;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        struct Candidate {\n            int i, j;\n            int x0, y0, z0, dx, dy, dz;\n            int jx0, jy0, jz0, jdx, jdy, jdz;\n            int cci, ccj;\n            int vol;\n            int score;  // higher better\n        };\n        vector<Candidate> matchable;\n\n        Seed best_local_seed;\n        int best_local_score = -1e9;\n        for (auto &seed : seeds) {\n            int i = seed.i, j = 1 - i;\n            int vol = seed.dx * seed.dy * seed.dz;\n            int local_score = seed.cci * 10000 - vol;\n            if (local_score > best_local_score) {\n                best_local_score = local_score;\n                best_local_seed = seed;\n            }\n            int jx0, jy0, jz0, jdx, jdy, jdz, ccj;\n            if (find_best_placement(j, seed.dx, seed.dy, seed.dz, jx0, jy0, jz0, jdx, jdy, jdz, ccj) && ccj > 0) {\n                int score = (seed.cci + ccj) * 10000 - vol;\n                matchable.push_back({i, j, seed.x0, seed.y0, seed.z0, seed.dx, seed.dy, seed.dz,\n                                     jx0, jy0, jz0, jdx, jdy, jdz,\n                                     seed.cci, ccj, vol, score});\n            }\n        }\n\n        if (!matchable.empty()) {\n            // pick best matchable\n            int best_idx = 0;\n            for (int k = 1; k < (int)matchable.size(); k++) {\n                if (matchable[k].score > matchable[best_idx].score ||\n                    (matchable[k].score == matchable[best_idx].score && matchable[k].vol < matchable[best_idx].vol))\n                    best_idx = k;\n            }\n            auto &c = matchable[best_idx];\n            int id = (int)blocks.size() + 1;\n            apply_placement(c.i, c.x0, c.y0, c.z0, c.dx, c.dy, c.dz, id);\n            apply_placement(c.j, c.jx0, c.jy0, c.jz0, c.jdx, c.jdy, c.jdz, id);\n            blocks.push_back({c.dx, c.dy, c.dz});\n            continue;\n        }\n\n        // No direct matchable \u2192 try sub\u2011boxes of the best local seed\n        if (seeds.empty()) break;\n\n        int i = best_local_seed.i, j = 1 - i;\n        int bx0 = best_local_seed.x0, by0 = best_local_seed.y0, bz0 = best_local_seed.z0;\n        int bdx = best_local_seed.dx, bdy = best_local_seed.dy, bdz = best_local_seed.dz;\n        int sx = best_local_seed.sx, sy = best_local_seed.sy, sz = best_local_seed.sz;\n\n        struct SubBox { int x0, y0, z0, dx, dy, dz, vol; };\n        vector<SubBox> subs;\n        for (int x0 = bx0; x0 <= sx; x0++) {\n            for (int x1 = sx; x1 < bx0 + bdx; x1++) {\n                int dx_sub = x1 - x0 + 1;\n                for (int y0 = by0; y0 <= sy; y0++) {\n                    for (int y1 = sy; y1 < by0 + bdy; y1++) {\n                        int dy_sub = y1 - y0 + 1;\n                        for (int z0 = bz0; z0 <= sz; z0++) {\n                            for (int z1 = sz; z1 < bz0 + bdz; z1++) {\n                                int dz_sub = z1 - z0 + 1;\n                                subs.push_back({x0, y0, z0, dx_sub, dy_sub, dz_sub, dx_sub * dy_sub * dz_sub});\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        sort(subs.begin(), subs.end(), [](const SubBox &a, const SubBox &b) {\n            return a.vol > b.vol;\n        });\n\n        bool placed_sub = false;\n        int best_sub_score = -1e9;\n        int best_sub_jx0, best_sub_jy0, best_sub_jz0, best_sub_jdx, best_sub_jdy, best_sub_jdz;\n        int best_sub_x0, best_sub_y0, best_sub_z0, best_sub_dx, best_sub_dy, best_sub_dz;\n\n        for (auto &sub : subs) {\n            int jx0, jy0, jz0, jdx, jdy, jdz, ccj;\n            if (find_best_placement(j, sub.dx, sub.dy, sub.dz, jx0, jy0, jz0, jdx, jdy, jdz, ccj) && ccj > 0) {\n                int cci_sub = count_covered(i, sub.x0, sub.y0, sub.z0, sub.dx, sub.dy, sub.dz);\n                int score = (cci_sub + ccj) * 10000 - sub.vol;\n                if (score > best_sub_score) {\n                    best_sub_score = score;\n                    best_sub_x0 = sub.x0; best_sub_y0 = sub.y0; best_sub_z0 = sub.z0;\n                    best_sub_dx = sub.dx; best_sub_dy = sub.dy; best_sub_dz = sub.dz;\n                    best_sub_jx0 = jx0; best_sub_jy0 = jy0; best_sub_jz0 = jz0;\n                    best_sub_jdx = jdx; best_sub_jdy = jdy; best_sub_jdz = jdz;\n                    placed_sub = true;\n                }\n            }\n        }\n\n        if (placed_sub) {\n            int id = (int)blocks.size() + 1;\n            apply_placement(i, best_sub_x0, best_sub_y0, best_sub_z0, best_sub_dx, best_sub_dy, best_sub_dz, id);\n            apply_placement(j, best_sub_jx0, best_sub_jy0, best_sub_jz0, best_sub_jdx, best_sub_jdy, best_sub_jdz, id);\n            blocks.push_back({best_sub_dx, best_sub_dy, best_sub_dz});\n            continue;\n        }\n\n        // No shared block can be placed anymore \u2013 proceed to 1x1 fill\n        break;\n    }\n\n    // Phase 2: fill remaining uncovered cells with 1\u00d71\u00d71 blocks (used only locally)\n    for (int i = 0; i < 2; i++) {\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            for (int z = 0; z < D && !changed; z++) {\n                for (int x = 0; x < D && !changed; x++) {\n                    if (uncov_f[i][z][x]) {\n                        for (int y = 0; y < D; y++) {\n                            if (allowed[i][idx(x, y, z)] && !used[i][idx(x, y, z)]) {\n                                int id = (int)blocks.size() + 1;\n                                apply_placement(i, x, y, z, 1, 1, 1, id);\n                                blocks.push_back({1, 1, 1});\n                                changed = true;\n                                break;\n                            }\n                        }\n                    }\n                }\n            }\n            for (int z = 0; z < D && !changed; z++) {\n                for (int y = 0; y < D && !changed; y++) {\n                    if (uncov_r[i][z][y]) {\n                        for (int x = 0; x < D; x++) {\n                            if (allowed[i][idx(x, y, z)] && !used[i][idx(x, y, z)]) {\n                                int id = (int)blocks.size() + 1;\n                                apply_placement(i, x, y, z, 1, 1, 1, id);\n                                blocks.push_back({1, 1, 1});\n                                changed = true;\n                                break;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    // Phase 3: try to use blocks that are only in one silhouette also in the other\n    int n = (int)blocks.size();\n    vector<bool> in0(n + 1, false), in1(n + 1, false);\n    for (int x = 0; x < D; x++)\n        for (int y = 0; y < D; y++)\n            for (int z = 0; z < D; z++) {\n                int id = bid[0][idx(x, y, z)];\n                if (id > 0) in0[id] = true;\n            }\n    for (int x = 0; x < D; x++)\n        for (int y = 0; y < D; y++)\n            for (int z = 0; z < D; z++) {\n                int id = bid[1][idx(x, y, z)];\n                if (id > 0) in1[id] = true;\n            }\n\n    vector<int> order(n);\n    for (int k = 0; k < n; k++) order[k] = k + 1;\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        int va = blocks[a - 1].dx * blocks[a - 1].dy * blocks[a - 1].dz;\n        int vb = blocks[b - 1].dx * blocks[b - 1].dy * blocks[b - 1].dz;\n        return va > vb;\n    });\n\n    for (int k : order) {\n        if (!in0[k]) {\n            int a = blocks[k - 1].dx, b = blocks[k - 1].dy, c = blocks[k - 1].dz;\n            int x0, y0, z0, dx, dy, dz;\n            if (find_placement_any(0, a, b, c, x0, y0, z0, dx, dy, dz)) {\n                apply_placement(0, x0, y0, z0, dx, dy, dz, k);\n                in0[k] = true;\n            }\n        }\n        if (!in1[k]) {\n            int a = blocks[k - 1].dx, b = blocks[k - 1].dy, c = blocks[k - 1].dz;\n            int x0, y0, z0, dx, dy, dz;\n            if (find_placement_any(1, a, b, c, x0, y0, z0, dx, dy, dz)) {\n                apply_placement(1, x0, y0, z0, dx, dy, dz, k);\n                in1[k] = true;\n            }\n        }\n    }\n\n    // Output\n    cout << n << \"\\n\";\n    for (int i = 0; i < 2; i++) {\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 (x != 0 || y != 0 || z != 0) cout << \" \";\n                    cout << bid[i][idx(x, y, z)];\n                }\n            }\n        }\n        cout << \"\\n\";\n    }\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\nusing int64 = long long;\n\ninline int64 ceil_sqrt(int64 x) {\n    if (x <= 0) return 0;\n    int64 r = (int64)sqrt((long double)x);\n    while (r * r < x) ++r;\n    while (r * r > x) --r;\n    if (r * r < x) ++r;\n    return r;\n}\n\nstruct State {\n    int N, K;\n    const vector<vector<int>>* station_res;\n    const vector<vector<int>>* res_stations;\n    const vector<vector<int64>>* dsq;\n    vector<bool> active;\n    vector<int> assign;          // K\n    vector<vector<int>> station_assign; // N\n    vector<int64> max_dsq;       // N\n    int uncovered;\n\n    State() = default;\n    void init(int n, int k, const vector<bool>& init_active,\n              const vector<vector<int>>* sr, const vector<vector<int>>* rs, const vector<vector<int64>>* dq) {\n        N = n; K = k;\n        station_res = sr; res_stations = rs; dsq = dq;\n        active = init_active;\n        assign.assign(K, -1);\n        station_assign.assign(N, {});\n        max_dsq.assign(N, 0);\n        uncovered = K;\n        for (int i = 0; i < N; ++i) if (active[i]) {\n            for (int kk : (*station_res)[i]) {\n                int64 d = (*dsq)[i][kk];\n                if (assign[kk] == -1) {\n                    assign[kk] = i;\n                    station_assign[i].push_back(kk);\n                    if (d > max_dsq[i]) max_dsq[i] = d;\n                    --uncovered;\n                } else {\n                    int cur = assign[kk];\n                    if (d < (*dsq)[cur][kk]) {\n                        auto& vcur = station_assign[cur];\n                        vcur.erase(find(vcur.begin(), vcur.end(), kk));\n                        int64 newmax = 0;\n                        for (int kk2 : vcur) if ((*dsq)[cur][kk2] > newmax) newmax = (*dsq)[cur][kk2];\n                        max_dsq[cur] = newmax;\n                        assign[kk] = i;\n                        station_assign[i].push_back(kk);\n                        if (d > max_dsq[i]) max_dsq[i] = d;\n                    }\n                }\n            }\n        }\n    }\n\n    void apply_add(int i) {\n        if (active[i]) return;\n        active[i] = true;\n        for (int kk : (*station_res)[i]) {\n            int64 d = (*dsq)[i][kk];\n            if (assign[kk] == -1) {\n                assign[kk] = i;\n                station_assign[i].push_back(kk);\n                if (d > max_dsq[i]) max_dsq[i] = d;\n                --uncovered;\n            } else {\n                int cur = assign[kk];\n                if (d < (*dsq)[cur][kk]) {\n                    auto& vcur = station_assign[cur];\n                    vcur.erase(find(vcur.begin(), vcur.end(), kk));\n                    int64 newmax = 0;\n                    for (int kk2 : vcur) if ((*dsq)[cur][kk2] > newmax) newmax = (*dsq)[cur][kk2];\n                    max_dsq[cur] = newmax;\n                    assign[kk] = i;\n                    station_assign[i].push_back(kk);\n                    if (d > max_dsq[i]) max_dsq[i] = d;\n                }\n            }\n        }\n    }\n\n    void apply_del(int i) {\n        if (!active[i]) return;\n        active[i] = false;\n        vector<int> affected = std::move(station_assign[i]);\n        station_assign[i].clear();\n        max_dsq[i] = 0;\n        for (int kk : affected) {\n            int best = -1;\n            int64 best_d = numeric_limits<int64>::max();\n            for (int j : (*res_stations)[kk]) {\n                if (active[j]) {\n                    int64 d = (*dsq)[j][kk];\n                    if (d < best_d) { best_d = d; best = j; }\n                    break;\n                }\n            }\n            if (best != -1) {\n                assign[kk] = best;\n                station_assign[best].push_back(kk);\n                if (best_d > max_dsq[best]) max_dsq[best] = best_d;\n            } else {\n                assign[kk] = -1;\n                ++uncovered;\n            }\n        }\n    }\n\n    int64 power_cost() const {\n        int64 total = 0;\n        for (int i = 0; i < N; ++i) if (max_dsq[i] > 0) {\n            int64 P = ceil_sqrt(max_dsq[i]);\n            if (P > 5000) P = 5000;\n            total += P * P;\n        }\n        return total;\n    }\n\n    State(const State&) = default;\n    State& operator=(const State&) = default;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start_time = chrono::steady_clock::now();\n    auto elapsed = [&]() { return chrono::duration<double>(chrono::steady_clock::now() - start_time).count(); };\n\n    int N, M, K;\n    cin >> N >> M >> K;\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; ++i) cin >> x[i] >> y[i];\n    vector<tuple<int, int, int>> edges(M);\n    vector<vector<pair<int, int>>> adj(N);\n    vector<vector<int>> edge_idx(N, vector<int>(N, -1));\n    for (int j = 0; j < M; ++j) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        --u; --v;\n        edges[j] = {u, v, w};\n        adj[u].push_back({v, w});\n        adj[v].push_back({u, w});\n        edge_idx[u][v] = edge_idx[v][u] = j;\n    }\n    vector<int> a(K), b(K);\n    for (int k = 0; k < K; ++k) cin >> a[k] >> b[k];\n\n    // all-pairs shortest paths\n    vector<vector<int64>> dist(N, vector<int64>(N));\n    vector<vector<int>> nxt(N, vector<int>(N, -1));\n    for (int s = 0; s < N; ++s) {\n        priority_queue<pair<int64, int>, vector<pair<int64, int>>, greater<>> pq;\n        vector<int64> d(N, numeric_limits<int64>::max());\n        d[s] = 0;\n        nxt[s][s] = s;\n        pq.push({0, s});\n        while (!pq.empty()) {\n            auto [du, u] = pq.top(); pq.pop();\n            if (du != d[u]) continue;\n            for (auto &[v, w] : adj[u]) {\n                if (d[u] + w < d[v]) {\n                    d[v] = d[u] + w;\n                    nxt[s][v] = u;\n                    pq.push({d[v], v});\n                }\n            }\n        }\n        dist[s] = d;\n    }\n\n    vector<vector<vector<int>>> path_edges(N, vector<vector<int>>(N));\n    for (int s = 0; s < N; ++s)\n        for (int t = 0; t < N; ++t) {\n            if (s == t) continue;\n            vector<int> eids;\n            int cur = t;\n            while (cur != s) {\n                int p = nxt[s][cur];\n                int eid = edge_idx[cur][p];\n                if (eid != -1) eids.push_back(eid);\n                cur = p;\n            }\n            path_edges[s][t] = eids;\n        }\n\n    const int64 R2 = 25000000LL;\n    vector<vector<int64>> dsq(N, vector<int64>(K));\n    vector<vector<int>> station_res(N);\n    for (int i = 0; i < N; ++i) {\n        for (int k = 0; k < K; ++k) {\n            int64 dx = x[i] - a[k];\n            int64 dy = y[i] - b[k];\n            int64 d2 = dx * dx + dy * dy;\n            dsq[i][k] = d2;\n            if (d2 <= R2) station_res[i].push_back(k);\n        }\n    }\n    vector<vector<int>> res_stations(K);\n    for (int k = 0; k < K; ++k) {\n        vector<pair<int64, int>> tmp;\n        for (int i = 0; i < N; ++i)\n            if (dsq[i][k] <= R2) tmp.push_back({dsq[i][k], i});\n        sort(tmp.begin(), tmp.end());\n        for (auto &p : tmp) res_stations[k].push_back(p.second);\n    }\n\n    vector<pair<int, int>> sorted_edge_indices(M);\n    for (int j = 0; j < M; ++j) sorted_edge_indices[j] = {get<2>(edges[j]), j};\n    sort(sorted_edge_indices.begin(), sorted_edge_indices.end());\n\n    auto compute_cable = [&](const vector<bool>& active) -> int64 {\n        vector<int> T;\n        for (int i = 0; i < N; ++i) if (active[i]) T.push_back(i);\n        int t = T.size();\n        vector<bool> used_edge(M, false);\n        if (t > 1) {\n            vector<bool> inmst(t, false);\n            vector<int64> minw(t, numeric_limits<int64>::max());\n            vector<int> parent(t, -1);\n            minw[0] = 0;\n            for (int i = 0; i < t; ++i) {\n                int u = -1;\n                for (int j = 0; j < t; ++j)\n                    if (!inmst[j] && (u == -1 || minw[j] < minw[u])) u = j;\n                inmst[u] = true;\n                if (parent[u] != -1) {\n                    int src = T[u], dst = T[parent[u]];\n                    for (int eid : path_edges[src][dst]) used_edge[eid] = true;\n                }\n                for (int v = 0; v < t; ++v) {\n                    if (!inmst[v] && dist[T[u]][T[v]] < minw[v]) {\n                        minw[v] = dist[T[u]][T[v]];\n                        parent[v] = u;\n                    }\n                }\n            }\n        }\n        vector<vector<int>> radj(N);\n        for (int j = 0; j < M; ++j) if (used_edge[j]) {\n            auto [u, v, w] = edges[j];\n            radj[u].push_back(v);\n            radj[v].push_back(u);\n        }\n        vector<bool> reachable(N, false);\n        queue<int> q;\n        reachable[0] = true; q.push(0);\n        while (!q.empty()) {\n            int node = q.front(); q.pop();\n            for (int to : radj[node]) {\n                if (!reachable[to]) {\n                    reachable[to] = true;\n                    q.push(to);\n                }\n            }\n        }\n        vector<int> uf(N);\n        iota(uf.begin(), uf.end(), 0);\n        function<int(int)> find = [&](int x) { return uf[x] == x ? x : uf[x] = find(uf[x]); };\n        int comps = count(reachable.begin(), reachable.end(), true);\n        int used_cnt = 0;\n        int64 cable_cost = 0;\n        for (auto &[w, j] : sorted_edge_indices) {\n            auto [u, v, _] = edges[j];\n            if (!reachable[u] || !reachable[v]) continue;\n            int ru = find(u), rv = find(v);\n            if (ru != rv) {\n                uf[ru] = rv;\n                cable_cost += w;\n                if (++used_cnt == comps - 1) break;\n            }\n        }\n        if (used_cnt != comps - 1) return numeric_limits<int64>::max();\n        return cable_cost;\n    };\n\n    auto generate_initial = [&](mt19937_64 &rng) {\n        vector<bool> active(N, false);\n        active[0] = true;\n        vector<int> active_list = {0};\n        vector<int64> best_dist_sq(K, numeric_limits<int64>::max());\n        int uncovered = K;\n        for (int k : station_res[0]) { best_dist_sq[k] = dsq[0][k]; --uncovered; }\n        uniform_real_distribution<double> noise(0.95, 1.05);\n        while (uncovered > 0) {\n            double best_ratio = 1e18;\n            int best_i = -1;\n            for (int i = 1; i < N; ++i) {\n                if (active[i]) continue;\n                int64 connect_cost = numeric_limits<int64>::max();\n                for (int j : active_list) connect_cost = min(connect_cost, dist[j][i]);\n                int64 max_d2 = 0;\n                int new_cov = 0;\n                for (int k : station_res[i]) {\n                    if (best_dist_sq[k] == numeric_limits<int64>::max()) {\n                        new_cov++;\n                        if (dsq[i][k] > max_d2) max_d2 = dsq[i][k];\n                    }\n                }\n                if (new_cov == 0) continue;\n                int64 P = ceil_sqrt(max_d2);\n                int64 power_inc = P * P;\n                double ratio = (double)(connect_cost + power_inc) / new_cov * noise(rng);\n                if (ratio < best_ratio) { best_ratio = ratio; best_i = i; }\n            }\n            if (best_i == -1) {\n                for (int i = 1; i < N && uncovered > 0; ++i) {\n                    if (!active[i]) {\n                        for (int k : station_res[i]) if (best_dist_sq[k] == numeric_limits<int64>::max()) {\n                            best_i = i;\n                            break;\n                        }\n                        if (best_i != -1) break;\n                    }\n                }\n            }\n            if (best_i == -1) break;\n            active[best_i] = true;\n            active_list.push_back(best_i);\n            for (int k : station_res[best_i]) {\n                if (dsq[best_i][k] < best_dist_sq[k]) {\n                    if (best_dist_sq[k] == numeric_limits<int64>::max()) --uncovered;\n                    best_dist_sq[k] = dsq[best_i][k];\n                }\n            }\n        }\n        return active;\n    };\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    vector<bool> best_active(N, false);\n    int64 best_total = numeric_limits<int64>::max();\n    State best_state;\n    best_state.init(N, K, best_active, &station_res, &res_stations, &dsq);\n\n    int num_starts = 2;\n    double time_per_start = 0.8;\n    for (int start = 0; start < num_starts; ++start) {\n        if (elapsed() > 1.95) break;\n        auto cur_active = generate_initial(rng);\n        State cur;\n        cur.init(N, K, cur_active, &station_res, &res_stations, &dsq);\n        int64 cur_cost = compute_cable(cur.active) + cur.power_cost();\n\n        // removal hill-climbing\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            for (int i = 1; i < N; ++i) {\n                if (!cur.active[i]) continue;\n                State nxt = cur;\n                nxt.apply_del(i);\n                if (nxt.uncovered > 0) continue;\n                int64 new_cable = compute_cable(nxt.active);\n                if (new_cable == numeric_limits<int64>::max()) continue;\n                int64 new_cost = new_cable + nxt.power_cost();\n                if (new_cost < cur_cost) {\n                    cur = move(nxt);\n                    cur_cost = new_cost;\n                    improved = true;\n                }\n            }\n        }\n\n        // SA\n        uniform_int_distribution<int> rand_vertex(1, N - 1);\n        uniform_real_distribution<double> rand_double(0.0, 1.0);\n        double T_start = max(1e6, (double)cur_cost * 0.1);\n        double T_end = T_start * 1e-6;\n        double sa_start = elapsed();\n        while (elapsed() < sa_start + time_per_start) {\n            double frac = (elapsed() - sa_start) / time_per_start;\n            double T = T_start * pow(T_end / T_start, frac);\n            if (T < 1e-9) T = 1e-9;\n\n            if (rand_double(rng) < 0.3) { // swap\n                vector<int> act;\n                for (int i = 1; i < N; ++i) if (cur.active[i]) act.push_back(i);\n                if (act.empty()) continue;\n                int j = act[uniform_int_distribution<int>(0, (int)act.size() - 1)(rng)];\n                State nxt = cur;\n                nxt.apply_del(j);\n                if (nxt.uncovered > 0) continue;\n                int i;\n                do { i = rand_vertex(rng); } while (cur.active[i]);\n                nxt.apply_add(i);\n                if (nxt.uncovered > 0) continue;\n                int64 new_cable = compute_cable(nxt.active);\n                if (new_cable == numeric_limits<int64>::max()) continue;\n                int64 new_cost = new_cable + nxt.power_cost();\n                bool accept = (new_cost < cur_cost);\n                if (!accept) {\n                    double delta = (double)(int64)(new_cost - cur_cost);\n                    if (rand_double(rng) < exp(-delta / T)) accept = true;\n                }\n                if (accept) {\n                    cur = move(nxt);\n                    cur_cost = new_cost;\n                    if (new_cost < best_total) { best_total = new_cost; best_active = cur.active; }\n                }\n            } else { // toggle\n                int i = rand_vertex(rng);\n                bool old = cur.active[i];\n                State nxt = cur;\n                if (old) nxt.apply_del(i); else nxt.apply_add(i);\n                if (nxt.uncovered > 0) continue;\n                int64 new_cable = compute_cable(nxt.active);\n                if (new_cable == numeric_limits<int64>::max()) continue;\n                int64 new_cost = new_cable + nxt.power_cost();\n                bool accept = (new_cost < cur_cost);\n                if (!accept) {\n                    double delta = (double)(int64)(new_cost - cur_cost);\n                    if (rand_double(rng) < exp(-delta / T)) accept = true;\n                }\n                if (accept) {\n                    cur = move(nxt);\n                    cur_cost = new_cost;\n                    if (new_cost < best_total) { best_total = new_cost; best_active = cur.active; }\n                }\n            }\n        }\n\n        // final hill-climbing\n        improved = true;\n        int hc_passes = 0;\n        while (improved && elapsed() < 1.96 && hc_passes < 5) {\n            improved = false;\n            ++hc_passes;\n            for (int i = 1; i < N; ++i) {\n                bool old = cur.active[i];\n                State nxt = cur;\n                if (old) nxt.apply_del(i); else nxt.apply_add(i);\n                if (nxt.uncovered > 0) continue;\n                int64 new_cable = compute_cable(nxt.active);\n                if (new_cable == numeric_limits<int64>::max()) continue;\n                int64 new_cost = new_cable + nxt.power_cost();\n                if (new_cost < cur_cost) {\n                    cur = move(nxt);\n                    cur_cost = new_cost;\n                    if (new_cost < best_total) { best_total = new_cost; best_active = cur.active; }\n                    improved = true;\n                }\n            }\n        }\n\n        // ---- per-start post-processing ----\n        // relay addition\n        bool relay_improved = true;\n        int relay_passes = 0;\n        while (relay_improved && elapsed() < 1.97 && relay_passes < 3) {\n            relay_improved = false;\n            ++relay_passes;\n            for (int i = 1; i < N; ++i) {\n                if (cur.active[i]) continue;\n                State nxt = cur;\n                nxt.apply_add(i);\n                if (nxt.uncovered > 0) continue;\n                int64 new_cable = compute_cable(nxt.active);\n                if (new_cable == numeric_limits<int64>::max()) continue;\n                int64 new_cost = new_cable + nxt.power_cost();\n                if (new_cost < cur_cost) {\n                    cur = move(nxt);\n                    cur_cost = new_cost;\n                    relay_improved = true;\n                }\n            }\n        }\n\n        // removal after relay\n        bool del_improved = true;\n        while (del_improved && elapsed() < 1.97) {\n            del_improved = false;\n            for (int i = 1; i < N; ++i) {\n                if (!cur.active[i]) continue;\n                State nxt = cur;\n                nxt.apply_del(i);\n                if (nxt.uncovered > 0) continue;\n                int64 new_cable = compute_cable(nxt.active);\n                if (new_cable == numeric_limits<int64>::max()) continue;\n                int64 new_cost = new_cable + nxt.power_cost();\n                if (new_cost < cur_cost) {\n                    cur = move(nxt);\n                    cur_cost = new_cost;\n                    del_improved = true;\n                }\n            }\n        }\n\n        // power assignment optimization\n        {\n            auto assign = cur.assign;\n            auto station_assign = cur.station_assign;\n            auto max_dsq = cur.max_dsq;\n            bool changed = true;\n            while (changed && elapsed() < 1.98) {\n                changed = false;\n                for (int k = 0; k < K; ++k) {\n                    int old = assign[k];\n                    if (old == -1) continue;\n                    int64 old_d2 = dsq[old][k];\n                    for (int j : res_stations[k]) {\n                        if (!cur.active[j] || j == old) continue;\n                        int64 new_max_old;\n                        if (old_d2 == max_dsq[old]) {\n                            new_max_old = 0;\n                            for (int kk : station_assign[old])\n                                if (kk != k && dsq[old][kk] > new_max_old) new_max_old = dsq[old][kk];\n                        } else new_max_old = max_dsq[old];\n                        int64 new_max_j = max(max_dsq[j], dsq[j][k]);\n                        int64 old_val = (ceil_sqrt(max_dsq[old]) * ceil_sqrt(max_dsq[old])) +\n                                        (ceil_sqrt(max_dsq[j]) * ceil_sqrt(max_dsq[j]));\n                        int64 new_val = (ceil_sqrt(new_max_old) * ceil_sqrt(new_max_old)) +\n                                        (ceil_sqrt(new_max_j) * ceil_sqrt(new_max_j));\n                        if (new_val < old_val) {\n                            auto &vold = station_assign[old];\n                            vold.erase(find(vold.begin(), vold.end(), k));\n                            station_assign[j].push_back(k);\n                            max_dsq[old] = new_max_old;\n                            max_dsq[j] = new_max_j;\n                            assign[k] = j;\n                            changed = true;\n                            break;\n                        }\n                    }\n                }\n            }\n            cur.assign = assign;\n            cur.station_assign = station_assign;\n            cur.max_dsq = max_dsq;\n            cur_cost = compute_cable(cur.active) + cur.power_cost();\n        }\n\n        // removal again after power assignment\n        del_improved = true;\n        while (del_improved && elapsed() < 1.97) {\n            del_improved = false;\n            for (int i = 1; i < N; ++i) {\n                if (!cur.active[i]) continue;\n                State nxt = cur;\n                nxt.apply_del(i);\n                if (nxt.uncovered > 0) continue;\n                int64 new_cable = compute_cable(nxt.active);\n                if (new_cable == numeric_limits<int64>::max()) continue;\n                int64 new_cost = new_cable + nxt.power_cost();\n                if (new_cost < cur_cost) {\n                    cur = move(nxt);\n                    cur_cost = new_cost;\n                    del_improved = true;\n                }\n            }\n        }\n\n        if (cur_cost < best_total) {\n            best_total = cur_cost;\n            best_active = cur.active;\n        }\n    }\n\n    // global best post-processing (safety)\n    best_state.init(N, K, best_active, &station_res, &res_stations, &dsq);\n    {\n        bool improved = true;\n        int passes = 0;\n        while (improved && elapsed() < 1.99 && passes < 2) {\n            improved = false;\n            ++passes;\n            // relay addition\n            for (int i = 1; i < N; ++i) {\n                if (best_state.active[i]) continue;\n                State nxt = best_state;\n                nxt.apply_add(i);\n                if (nxt.uncovered > 0) continue;\n                int64 new_cable = compute_cable(nxt.active);\n                if (new_cable == numeric_limits<int64>::max()) continue;\n                int64 new_cost = new_cable + nxt.power_cost();\n                int64 cur_cost = compute_cable(best_state.active) + best_state.power_cost();\n                if (new_cost < cur_cost) {\n                    best_state = move(nxt);\n                    best_active = best_state.active;\n                    improved = true;\n                }\n            }\n            // removal\n            for (int i = 1; i < N; ++i) {\n                if (!best_state.active[i]) continue;\n                State nxt = best_state;\n                nxt.apply_del(i);\n                if (nxt.uncovered > 0) continue;\n                int64 new_cable = compute_cable(nxt.active);\n                if (new_cable == numeric_limits<int64>::max()) continue;\n                int64 new_cost = new_cable + nxt.power_cost();\n                int64 cur_cost = compute_cable(best_state.active) + best_state.power_cost();\n                if (new_cost < cur_cost) {\n                    best_state = move(nxt);\n                    best_active = best_state.active;\n                    improved = true;\n                }\n            }\n            // power optimization\n            {\n                auto assign = best_state.assign;\n                auto station_assign = best_state.station_assign;\n                auto max_dsq = best_state.max_dsq;\n                bool changed = true;\n                while (changed) {\n                    changed = false;\n                    for (int k = 0; k < K; ++k) {\n                        int old = assign[k];\n                        if (old == -1) continue;\n                        int64 old_d2 = dsq[old][k];\n                        for (int j : res_stations[k]) {\n                            if (!best_active[j] || j == old) continue;\n                            int64 new_max_old;\n                            if (old_d2 == max_dsq[old]) {\n                                new_max_old = 0;\n                                for (int kk : station_assign[old])\n                                    if (kk != k && dsq[old][kk] > new_max_old) new_max_old = dsq[old][kk];\n                            } else new_max_old = max_dsq[old];\n                            int64 new_max_j = max(max_dsq[j], dsq[j][k]);\n                            int64 old_val = (ceil_sqrt(max_dsq[old]) * ceil_sqrt(max_dsq[old])) +\n                                            (ceil_sqrt(max_dsq[j]) * ceil_sqrt(max_dsq[j]));\n                            int64 new_val = (ceil_sqrt(new_max_old) * ceil_sqrt(new_max_old)) +\n                                            (ceil_sqrt(new_max_j) * ceil_sqrt(new_max_j));\n                            if (new_val < old_val) {\n                                auto &vold = station_assign[old];\n                                vold.erase(find(vold.begin(), vold.end(), k));\n                                station_assign[j].push_back(k);\n                                max_dsq[old] = new_max_old;\n                                max_dsq[j] = new_max_j;\n                                assign[k] = j;\n                                changed = true;\n                                break;\n                            }\n                        }\n                    }\n                }\n                best_state.assign = assign;\n                best_state.station_assign = station_assign;\n                best_state.max_dsq = max_dsq;\n            }\n        }\n    }\n\n    // final edges\n    vector<int> final_B(M, 0);\n    {\n        vector<int> T;\n        for (int i = 0; i < N; ++i) if (best_active[i]) T.push_back(i);\n        int t = T.size();\n        vector<bool> used_edge(M, false);\n        if (t > 1) {\n            vector<bool> inmst(t, false);\n            vector<int64> minw(t, numeric_limits<int64>::max());\n            vector<int> parent(t, -1);\n            minw[0] = 0;\n            for (int i = 0; i < t; ++i) {\n                int u = -1;\n                for (int j = 0; j < t; ++j)\n                    if (!inmst[j] && (u == -1 || minw[j] < minw[u])) u = j;\n                inmst[u] = true;\n                if (parent[u] != -1) {\n                    int src = T[u], dst = T[parent[u]];\n                    for (int eid : path_edges[src][dst]) used_edge[eid] = true;\n                }\n                for (int v = 0; v < t; ++v) {\n                    if (!inmst[v] && dist[T[u]][T[v]] < minw[v]) {\n                        minw[v] = dist[T[u]][T[v]];\n                        parent[v] = u;\n                    }\n                }\n            }\n        }\n        vector<vector<int>> radj(N);\n        for (int j = 0; j < M; ++j) if (used_edge[j]) {\n            auto [u, v, w] = edges[j];\n            radj[u].push_back(v);\n            radj[v].push_back(u);\n        }\n        vector<bool> reachable(N, false);\n        queue<int> q;\n        reachable[0] = true; q.push(0);\n        while (!q.empty()) {\n            int node = q.front(); q.pop();\n            for (int to : radj[node]) {\n                if (!reachable[to]) {\n                    reachable[to] = true;\n                    q.push(to);\n                }\n            }\n        }\n        vector<int> uf(N);\n        iota(uf.begin(), uf.end(), 0);\n        function<int(int)> find = [&](int x) { return uf[x] == x ? x : uf[x] = find(uf[x]); };\n        int comps = count(reachable.begin(), reachable.end(), true);\n        int used = 0;\n        for (auto &[w, j] : sorted_edge_indices) {\n            auto [u, v, _] = edges[j];\n            if (!reachable[u] || !reachable[v]) continue;\n            int ru = find(u), rv = find(v);\n            if (ru != rv) {\n                uf[ru] = rv;\n                final_B[j] = 1;\n                if (++used == comps - 1) break;\n            }\n        }\n    }\n\n    vector<int> final_P(N, 0);\n    for (int i = 0; i < N; ++i) {\n        if (best_state.max_dsq[i] > 0) {\n            int64 P = ceil_sqrt(best_state.max_dsq[i]);\n            if (P > 5000) P = 5000;\n            final_P[i] = (int)P;\n        }\n    }\n\n    // output\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << final_P[i];\n    }\n    cout << '\\n';\n    for (int j = 0; j < M; ++j) {\n        if (j) cout << ' ';\n        cout << final_B[j];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <array>\n#include <numeric>\nusing namespace std;\n\nconst int N = 30;\nconst int V = N * (N + 1) / 2;          // 465\n\nint xc[V], yc[V];                      // coordinates\n\nint id(int x, int y) {\n    return x * (x + 1) / 2 + y;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // precompute coordinates\n    for (int x = 0; x < N; ++x)\n        for (int y = 0; y <= x; ++y) {\n            int i = id(x, y);\n            xc[i] = x;\n            yc[i] = y;\n        }\n\n    // read initial configuration\n    vector<int> init_grid(V);\n    for (int x = 0; x < N; ++x)\n        for (int y = 0; y <= x; ++y)\n            cin >> init_grid[id(x, y)];\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto start_time = chrono::steady_clock::now();\n\n    // -------- helpers --------\n    vector<int> grid(V);                     // workspace for simulation\n    vector<array<int, 2>> temp_moves;        // workspace for moves\n    temp_moves.reserve(10000);\n\n    // add a move with immediate cancellation of opposite adjacent swap\n    auto push_move = [&](vector<array<int, 2>>& moves, int a, int b) {\n        if (!moves.empty()) {\n            auto& last = moves.back();\n            if ((last[0] == a && last[1] == b) || (last[0] == b && last[1] == a))\n                moves.pop_back();\n            else\n                moves.push_back({a, b});\n        } else {\n            moves.push_back({a, b});\n        }\n    };\n\n    // evaluate a given column order, returns length and fills moves\n    auto evaluate = [&](const vector<vector<int>>& order, vector<array<int, 2>>& moves) -> int {\n        copy(init_grid.begin(), init_grid.end(), grid.begin());\n        moves.clear();\n        for (int x = N - 2; x >= 0; --x) {\n            for (int y : order[x]) {\n                int cur = id(x, y);\n                while (xc[cur] < N - 1) {\n                    int lc = cur + xc[cur] + 1;   // left child\n                    int rc = lc + 1;               // right child\n                    int left  = grid[lc];\n                    int right = grid[rc];\n                    if (grid[cur] <= min(left, right))\n                        break;\n                    if (left <= right) {\n                        swap(grid[cur], grid[lc]);\n                        push_move(moves, cur, lc);\n                        cur = lc;\n                    } else {\n                        swap(grid[cur], grid[rc]);\n                        push_move(moves, cur, rc);\n                        cur = rc;\n                    }\n                }\n            }\n        }\n        return (int)moves.size();\n    };\n\n    // -------- generate initial orders --------\n    vector<vector<int>> best_order(N - 1);\n    size_t best_len = 10000000;\n    vector<array<int, 2>> best_moves;\n\n    auto try_candidate = [&](vector<vector<int>>& cand_order) {\n        int len = evaluate(cand_order, temp_moves);\n        if ((size_t)len < best_len) {\n            best_len = len;\n            best_moves.swap(temp_moves);\n            best_order = cand_order;\n        }\n    };\n\n    // deterministic orders\n    for (int x = 0; x < N - 1; ++x) {\n        int sz = x + 1;\n        vector<int> cols(sz);\n        iota(cols.begin(), cols.end(), 0);\n        sort(cols.begin(), cols.end(), [&](int a, int b) {\n            return init_grid[id(x, a)] > init_grid[id(x, b)];\n        });\n        best_order[x] = cols;\n    }\n    try_candidate(best_order);\n\n    // random orders\n    {\n        vector<vector<int>> ord(N - 1);\n        for (int t = 0; t < 30; ++t) {\n            for (int x = 0; x < N - 1; ++x) {\n                vector<int> cols(x + 1);\n                iota(cols.begin(), cols.end(), 0);\n                shuffle(cols.begin(), cols.end(), rng);\n                ord[x] = cols;\n            }\n            try_candidate(ord);\n        }\n    }\n\n    // -------- SA on column orders --------\n    double time_limit_sa = 1.90;\n    uniform_real_distribution<double> prob_dist(0.0, 1.0);\n    uniform_int_distribution<int> row_dist(0, N - 2);\n    auto order = best_order;\n    size_t cur_len = best_len;\n    vector<array<int, 2>> cur_moves = best_moves;\n\n    double T_start = 2.0, T_end = 0.01;\n    while (true) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n        if (elapsed > time_limit_sa) break;\n        double T = T_start * pow(T_end / T_start, min(elapsed / time_limit_sa, 1.0));\n\n        int r = row_dist(rng);\n        int sz = (int)order[r].size();\n        if (sz <= 1) continue;\n        uniform_int_distribution<int> col_dist(0, sz - 1);\n        int i = col_dist(rng), j = col_dist(rng);\n        if (i == j) continue;\n        swap(order[r][i], order[r][j]);\n\n        int new_len = evaluate(order, temp_moves);\n        int delta = (int)new_len - (int)cur_len;\n        if (delta <= 0 || prob_dist(rng) < exp(-delta / T)) {\n            cur_len = new_len;\n            cur_moves.swap(temp_moves);\n            if (cur_len < best_len) {\n                best_len = cur_len;\n                best_moves = cur_moves;\n                best_order = order;\n            }\n        } else {\n            swap(order[r][i], order[r][j]);   // revert\n        }\n    }\n\n    // full cancellation on best\n    auto cancel_pairs = [&](vector<array<int, 2>>& mvec) {\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            for (size_t i = 0; i + 1 < mvec.size(); ++i) {\n                auto& a = mvec[i];\n                auto& b = mvec[i + 1];\n                if ((a[0] == b[1] && a[1] == b[0]) || (a[0] == b[0] && a[1] == b[1])) {\n                    mvec.erase(mvec.begin() + i, mvec.begin() + i + 2);\n                    changed = true;\n                    break;\n                }\n            }\n        }\n    };\n    cancel_pairs(best_moves);\n\n    // -------- redundancy removal --------\n    auto try_remove = [&](const vector<array<int, 2>>& mvec, int skip_idx) -> bool {\n        auto g = init_grid;\n        for (int j = 0; j < skip_idx; ++j)\n            swap(g[mvec[j][0]], g[mvec[j][1]]);\n        for (size_t j = skip_idx + 1; j < mvec.size(); ++j)\n            swap(g[mvec[j][0]], g[mvec[j][1]]);\n        for (int x = 0; x < N - 1; ++x) {\n            for (int y = 0; y <= x; ++y) {\n                int idx = id(x, y);\n                int lc = idx + x + 1, rc = lc + 1;\n                if (g[idx] > g[lc] || g[idx] > g[rc])\n                    return false;\n            }\n        }\n        return true;\n    };\n\n    const double limit_total = 1.98;\n    bool changed = true;\n    while (changed) {\n        if (chrono::duration<double>(chrono::steady_clock::now() - start_time).count() > limit_total)\n            break;\n        changed = false;\n        // backward pass\n        for (int i = (int)best_moves.size() - 1; i >= 0; --i) {\n            if (try_remove(best_moves, i)) {\n                best_moves.erase(best_moves.begin() + i);\n                changed = true;\n            }\n        }\n        // forward pass\n        for (int i = 0; i < (int)best_moves.size(); ++i) {\n            if (try_remove(best_moves, i)) {\n                best_moves.erase(best_moves.begin() + i);\n                --i;\n                changed = true;\n            }\n        }\n    }\n\n    cancel_pairs(best_moves);\n\n    // -------- output --------\n    cout << best_moves.size() << '\\n';\n    for (auto m : best_moves) {\n        cout << xc[m[0]] << ' ' << yc[m[0]] << ' '\n             << xc[m[1]] << ' ' << yc[m[1]] << '\\n';\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <functional>\n#include <utility>\n\nusing namespace std;\n\nint main() {\n    // Read initial information\n    int D, N;\n    cin >> D >> N;\n    int ent_r = 0, ent_c = (D - 1) / 2;\n    int start = ent_r * D + ent_c;\n\n    // Mark cells that cannot hold containers (entrance + obstacles)\n    vector<vector<bool>> blocked(D, vector<bool>(D, false));\n    blocked[ent_r][ent_c] = true;  // entrance\n    for (int i = 0; i < N; i++) {\n        int r, c;\n        cin >> r >> c;\n        blocked[r][c] = true;\n    }\n\n    int K = D * D - 1 - N;  // number of containers\n\n    // BFS distances from entrance over free cells\n    vector<int> dist(D * D, -1);\n    queue<int> q;\n    dist[start] = 0;\n    q.push(start);\n    const int dr[4] = {-1, 1, 0, 0};\n    const int dc[4] = {0, 0, -1, 1};\n\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        int r = u / D, c = u % D;\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n            if (blocked[nr][nc]) continue;\n            int v = nr * D + nc;\n            if (dist[v] == -1) {\n                dist[v] = dist[u] + 1;\n                q.push(v);\n            }\n        }\n    }\n\n    // Collect all free cells (non-blocked, non-entrance)\n    vector<int> free_cells;\n    for (int r = 0; r < D; r++) {\n        for (int c = 0; c < D; c++) {\n            if (!blocked[r][c]) {\n                free_cells.push_back(r * D + c);\n            }\n        }\n    }\n\n    // Sort free cells by distance, then by ID (row-major)\n    sort(free_cells.begin(), free_cells.end(), [&](int a, int b) {\n        if (dist[a] != dist[b]) return dist[a] < dist[b];\n        return a < b;\n    });\n\n    // Prepare mapping: order of each cell, and ideal cell for each rank\n    vector<int> ord(D * D, -1);\n    vector<int> ideal(K);\n    for (int i = 0; i < K; i++) {\n        int cell = free_cells[i];\n        ord[cell] = i;\n        ideal[i] = cell;\n    }\n\n    // State of the warehouse\n    vector<bool> occupied(D * D, false);\n    vector<int> rank_at(D * D, -1);\n\n    // Process arrivals\n    for (int d = 0; d < K; d++) {\n        int rank;\n        cin >> rank;\n\n        // Get all empty cells currently reachable from entrance\n        vector<int> reachable;\n        vector<bool> vis(D * D, false);\n        queue<int> bfs;\n        bfs.push(start);\n        vis[start] = true;\n        while (!bfs.empty()) {\n            int u = bfs.front(); bfs.pop();\n            reachable.push_back(u);\n            int r = u / D, c = u % D;\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (blocked[nr][nc]) continue;\n                int v = nr * D + nc;\n                if (occupied[v]) continue;\n                if (!vis[v]) {\n                    vis[v] = true;\n                    bfs.push(v);\n                }\n            }\n        }\n\n        // Build adjacency among reachable cells\n        vector<vector<int>> adj(D * D);\n        for (int u : reachable) {\n            int r = u / D, c = u % D;\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (blocked[nr][nc]) continue;\n                int v = nr * D + nc;\n                if (occupied[v]) continue;\n                if (vis[v]) {\n                    adj[u].push_back(v);\n                }\n            }\n        }\n\n        // Find articulation points (cells that would disconnect the empty area)\n        vector<int> disc(D * D, -1), low(D * D, -1);\n        vector<bool> is_art(D * D, false);\n        int timer = 0;\n        function<void(int, int)> dfs = [&](int u, int parent) {\n            disc[u] = low[u] = timer++;\n            int children = 0;\n            for (int v : adj[u]) {\n                if (v == parent) continue;\n                if (disc[v] == -1) {\n                    dfs(v, u);\n                    low[u] = min(low[u], low[v]);\n                    if (parent != -1 && low[v] >= disc[u]) {\n                        is_art[u] = true;\n                    }\n                    children++;\n                } else {\n                    low[u] = min(low[u], disc[v]);\n                }\n            }\n            if (parent == -1 && children > 1) {\n                is_art[u] = true;\n            }\n        };\n        dfs(start, -1);\n\n        // Safe cells = reachable empty cells except entrance and articulation points\n        vector<int> safe;\n        for (int u : reachable) {\n            if (u == start) continue;\n            if (!is_art[u]) {\n                safe.push_back(u);\n            }\n        }\n\n        // Choose placement cell\n        int target = ideal[rank];\n        int chosen = -1;\n        bool target_safe = false;\n        for (int u : safe) if (u == target) { target_safe = true; break; }\n\n        if (target_safe) {\n            chosen = target;\n        } else {\n            int best_diff = 1e9;\n            for (int u : safe) {\n                int diff = abs(ord[u] - rank);\n                if (diff < best_diff) {\n                    best_diff = diff;\n                    chosen = u;\n                } else if (diff == best_diff) {\n                    if (ord[u] < ord[chosen]) {\n                        chosen = u;\n                    }\n                }\n            }\n        }\n\n        // Place the container\n        occupied[chosen] = true;\n        rank_at[chosen] = rank;\n        cout << chosen / D << \" \" << chosen % D << endl;\n    }\n\n    // Removal phase\n    vector<bool> removed(D * D, false);\n    vector<pair<int, int>> removal_seq;\n\n    while (removal_seq.size() < K) {\n        queue<int> bfs;\n        vector<bool> vis(D * D, false);\n        bfs.push(start);\n        vis[start] = true;\n        vector<int> candidates;\n\n        while (!bfs.empty()) {\n            int u = bfs.front(); bfs.pop();\n            int r = u / D, c = u % D;\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (blocked[nr][nc]) continue;\n                int v = nr * D + nc;\n                if (vis[v]) continue;\n                if (removed[v] || v == start) {\n                    vis[v] = true;\n                    bfs.push(v);\n                } else if (occupied[v] && !removed[v]) {\n                    candidates.push_back(v);\n                }\n            }\n        }\n\n        sort(candidates.begin(), candidates.end());\n        candidates.erase(unique(candidates.begin(), candidates.end()), candidates.end());\n\n        int best = -1, best_rank = 1e9;\n        for (int v : candidates) {\n            if (rank_at[v] < best_rank) {\n                best_rank = rank_at[v];\n                best = v;\n            }\n        }\n\n        removed[best] = true;\n        removal_seq.emplace_back(best / D, best % D);\n    }\n\n    for (auto [r, c] : removal_seq) {\n        cout << r << \" \" << c << endl;\n    }\n\n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <chrono>\n#include <cmath>\n#include <cstring>\nusing namespace std;\nusing namespace chrono;\n\nconstexpr int N = 50, N2 = N * N, MAXC = 101; // colors 0..100\n\nint N4[N2][4];\nvector<int> boundary;\nbool req_adj[MAXC][MAXC];\n\nint vis[N2], vis_token, bfs_q[N2];\n\n// xorshift64\nuint64_t rng_state = 123456789;\nuint64_t rng_next() {\n    rng_state = rng_state * 6364136223846793005ULL + 1442695040888963407ULL;\n    return rng_state >> 33;\n}\nint rng_int(int n) { return rng_next() % n; }\ndouble rng_double() { return (rng_next() & 0xFFFFFFFF) / 4294967296.0; }\n\n// ---------------------------------------------------------------------\n// Full evaluation (used by SA)\nvoid eval(const int* g, int m, int& e, int& vc, int& va) {\n    ++vis_token;\n    e = 0; vc = 0; va = 0;\n    int comps[MAXC] = {0}, ccnt[MAXC] = {0};\n\n    for (int i = 0; i < N2; ++i) {\n        int c = g[i];\n        if (c == 0) { ++e; continue; }\n        ccnt[c]++;\n        if (vis[i] != vis_token) {\n            comps[c]++;\n            int head = 0, tail = 0;\n            bfs_q[tail++] = i; vis[i] = vis_token;\n            while (head < tail) {\n                int v = bfs_q[head++];\n                for (int k = 0; k < 4; ++k) {\n                    int u = N4[v][k];\n                    if (u != -1 && g[u] == c && vis[u] != vis_token) {\n                        vis[u] = vis_token;\n                        bfs_q[tail++] = u;\n                    }\n                }\n            }\n        }\n    }\n    for (int c = 1; c <= m; ++c) {\n        if (ccnt[c] == 0) vc += 1;\n        else if (comps[c] != 1) vc += comps[c] - 1;\n    }\n\n    // 0\u2011connectivity (must be connected to outside)\n    for (int idx : boundary) {\n        if (g[idx] == 0 && vis[idx] != vis_token) {\n            int head = 0, tail = 0;\n            bfs_q[tail++] = idx; vis[idx] = vis_token;\n            while (head < tail) {\n                int v = bfs_q[head++];\n                for (int k = 0; k < 4; ++k) {\n                    int u = N4[v][k];\n                    if (u != -1 && g[u] == 0 && vis[u] != vis_token) {\n                        vis[u] = vis_token;\n                        bfs_q[tail++] = u;\n                    }\n                }\n            }\n        }\n    }\n    int iso = 0;\n    for (int i = 0; i < N2; ++i) if (g[i] == 0 && vis[i] != vis_token) ++iso;\n    vc += iso;\n\n    // adjacency\n    int adj[MAXC][MAXC] = {0};\n    for (int i = 0; i < N2; ++i) {\n        int c1 = g[i];\n        if (i % N < N - 1) {\n            int c2 = g[i + 1];\n            if (c1 != c2) { adj[c1][c2]++; adj[c2][c1]++; }\n        }\n        if (i / N < N - 1) {\n            int c2 = g[i + N];\n            if (c1 != c2) { adj[c1][c2]++; adj[c2][c1]++; }\n        }\n    }\n    for (int idx : boundary) {\n        int c = g[idx];\n        if (c != 0) { adj[c][0]++; adj[0][c]++; }\n    }\n    for (int a = 0; a <= m; ++a)\n        for (int b = a + 1; b <= m; ++b) {\n            if (req_adj[a][b]) {\n                if (adj[a][b] == 0) va++;\n            } else {\n                va += adj[a][b];\n            }\n        }\n}\n\n// ---------------------------------------------------------------------\n// Greedy safe removal \u2013 works on a valid grid, returns number of zeros\nint greedy_erode(int* g, int m) {\n    int cnt[MAXC] = {0};\n    int curadj[MAXC][MAXC] = {0};\n\n    for (int i = 0; i < N2; ++i) if (g[i] != 0) cnt[g[i]]++;\n    for (int i = 0; i < N2; ++i) {\n        int c1 = g[i];\n        if (i % N < N - 1) {\n            int c2 = g[i + 1];\n            if (c1 != c2) { curadj[c1][c2]++; curadj[c2][c1]++; }\n        }\n        if (i / N < N - 1) {\n            int c2 = g[i + N];\n            if (c1 != c2) { curadj[c1][c2]++; curadj[c2][c1]++; }\n        }\n    }\n    for (int idx : boundary) {\n        int c = g[idx];\n        if (c != 0) { curadj[c][0]++; curadj[0][c]++; }\n    }\n\n    int order[N2];\n    for (int i = 0; i < N2; ++i) order[i] = i;\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        for (int i = N2 - 1; i > 0; --i) swap(order[i], order[rng_int(i + 1)]);\n        for (int ii = 0; ii < N2; ++ii) {\n            int idx = order[ii];\n            if (g[idx] == 0) continue;\n            bool has0 = false;\n            for (int k = 0; k < 4; ++k) {\n                int u = N4[idx][k];\n                if (u == -1 || g[u] == 0) { has0 = true; break; }\n            }\n            if (!has0) continue;\n\n            int c = g[idx];\n            if (cnt[c] <= 1) continue;\n\n            int lost[MAXC] = {0}, gain[MAXC] = {0};\n            for (int k = 0; k < 4; ++k) {\n                int u = N4[idx][k];\n                int d = (u == -1) ? 0 : g[u];\n                if (d == c) continue;\n                lost[d]++; if (d != 0) gain[d]++;\n            }\n            bool valid = true;\n            for (int d = 0; d <= m; ++d) {\n                if (req_adj[c][d] && curadj[c][d] - lost[d] < 1) { valid = false; break; }\n                if (d != 0 && !req_adj[0][d] && gain[d] > 0) { valid = false; break; }\n            }\n            if (!valid) continue;\n\n            int start = -1;\n            for (int k = 0; k < 4; ++k) {\n                int u = N4[idx][k];\n                if (u != -1 && g[u] == c) { start = u; break; }\n            }\n            if (start == -1) continue;\n            ++vis_token;\n            int head = 0, tail = 0;\n            bfs_q[tail++] = start; vis[start] = vis_token;\n            while (head < tail) {\n                int v = bfs_q[head++];\n                for (int k = 0; k < 4; ++k) {\n                    int u = N4[v][k];\n                    if (u != -1 && u != idx && g[u] == c && vis[u] != vis_token) {\n                        vis[u] = vis_token;\n                        bfs_q[tail++] = u;\n                    }\n                }\n            }\n            if (tail != cnt[c] - 1) continue;\n\n            for (int k = 0; k < 4; ++k) {\n                int u = N4[idx][k];\n                int d = (u == -1) ? 0 : g[u];\n                if (d == c) continue;\n                curadj[c][d]--; curadj[d][c]--;\n                if (d != 0) { curadj[0][d]++; curadj[d][0]++; }\n            }\n            cnt[c]--;\n            g[idx] = 0;\n            changed = true;\n        }\n    }\n\n    int e = 0;\n    for (int i = 0; i < N2; ++i) if (g[i] == 0) ++e;\n    return e;\n}\n\n// ---------------------------------------------------------------------\nint main() {\n    auto start_time = high_resolution_clock::now();\n    auto ms = [&]() {\n        return duration_cast<milliseconds>(high_resolution_clock::now() - start_time).count();\n    };\n\n    int n, m;\n    cin >> n >> m;\n    vector<vector<int>> orig(n, vector<int>(n));\n    for (int i = 0; i < n; ++i)\n        for (int j = 0; j < n; ++j)\n            cin >> orig[i][j];\n\n    // ----- precompute neighbours and boundary -----\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int idx = i * N + j;\n            N4[idx][0] = (i > 0) ? idx - N : -1;\n            N4[idx][1] = (i < n - 1) ? idx + N : -1;\n            N4[idx][2] = (j > 0) ? idx - 1 : -1;\n            N4[idx][3] = (j < n - 1) ? idx + 1 : -1;\n            if (i == 0 || i == n - 1 || j == 0 || j == n - 1)\n                boundary.push_back(idx);\n        }\n    }\n\n    // ----- required adjacency from original -----\n    memset(req_adj, 0, sizeof(req_adj));\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c1 = orig[i][j];\n            if (j + 1 < n) {\n                int c2 = orig[i][j + 1];\n                if (c1 != c2) req_adj[c1][c2] = req_adj[c2][c1] = true;\n            }\n            if (i + 1 < n) {\n                int c2 = orig[i + 1][j];\n                if (c1 != c2) req_adj[c1][c2] = req_adj[c2][c1] = true;\n            }\n            if (i == 0 || i == n - 1 || j == 0 || j == n - 1)\n                req_adj[c1][0] = req_adj[0][c1] = true;\n        }\n    }\n\n    int orig1d[N2];\n    for (int i = 0; i < n; ++i)\n        for (int j = 0; j < n; ++j)\n            orig1d[i * N + j] = orig[i][j];\n\n    // ----- multiple initial greedy erosions -----\n    int cur[N2];\n    int bestE = -1;\n    int best[N2];\n    while (ms() < 250) {\n        memcpy(cur, orig1d, sizeof(cur));\n        int e = greedy_erode(cur, m);\n        if (e > bestE) {\n            bestE = e;\n            memcpy(best, cur, sizeof(cur));\n        }\n    }\n    // fallback if somehow no valid found (should not happen)\n    if (bestE < 0) {\n        memcpy(best, orig1d, sizeof(orig1d));\n        bestE = 0;\n    }\n\n    memcpy(cur, best, sizeof(best));\n    int curE = bestE, curVc = 0, curVa = 0;\n    double cur_energy = -curE;\n\n    // ----- simulated annealing -----\n    const double T_start = 500000.0, T_end = 0.01;\n    const int W = 5000;\n    const double sa_end = 1950.0;\n    int stuck = 0;\n    const int STUCK_LIMIT = 8000;\n\n    while (ms() < sa_end) {\n        double progress = max(0.0, (ms() - 200.0) / (sa_end - 200.0));\n        double T = T_start * pow(T_end / T_start, progress);\n        if (T < 0.01) T = 0.01;\n\n        int idx = rng_int(N2);\n        int old_c = cur[idx];\n        double r = rng_double();\n        int new_c;\n\n        if (r < 0.03) {  // swap two adjacent cells\n            int nidx = N4[idx][rng_int(4)];\n            if (nidx != -1 && cur[idx] != cur[nidx]) {\n                int old2 = cur[nidx];\n                cur[idx] = old2; cur[nidx] = old_c;\n                eval(cur, m, curE, curVc, curVa);\n                double ne = -curE + W * (curVc + curVa);\n                double delta = ne - cur_energy;\n                if (delta <= 0 || rng_double() < exp(-delta / T)) {\n                    cur_energy = ne;\n                    if (curVc == 0 && curVa == 0 && curE > bestE) {\n                        bestE = curE; memcpy(best, cur, sizeof(cur));\n                        stuck = 0;\n                    }\n                } else {\n                    cur[idx] = old_c; cur[nidx] = old2;\n                }\n            }\n            continue;\n        }\n\n        if (r < 0.40) {                     // set to zero\n            new_c = 0;\n        } else if (r < 0.70) {              // recolor to neighbour's colour\n            int neigh[4], nc = 0;\n            for (int k = 0; k < 4; ++k) {\n                int u = N4[idx][k];\n                int d = (u == -1) ? 0 : cur[u];\n                if (d != old_c) {\n                    bool dup = false;\n                    for (int t = 0; t < nc; ++t) if (neigh[t] == d) { dup = true; break; }\n                    if (!dup) neigh[nc++] = d;\n                }\n            }\n            new_c = nc ? neigh[rng_int(nc)] : old_c;\n        } else {                             // random colour (1..m)\n            new_c = rng_int(m) + 1;\n        }\n        if (new_c == old_c) continue;\n\n        cur[idx] = new_c;\n        eval(cur, m, curE, curVc, curVa);\n        double ne = -curE + W * (curVc + curVa);\n        double delta = ne - cur_energy;\n        if (delta <= 0 || rng_double() < exp(-delta / T)) {\n            cur_energy = ne;\n            if (curVc == 0 && curVa == 0 && curE > bestE) {\n                bestE = curE;\n                memcpy(best, cur, sizeof(cur));\n                stuck = 0;\n            }\n        } else {\n            cur[idx] = old_c;\n        }\n\n        // periodic greedy refinement on best valid\n        if (rng_int(2500) == 0) {\n            int tmp[N2];\n            memcpy(tmp, best, sizeof(best));\n            int newE = greedy_erode(tmp, m);\n            if (newE > bestE) {\n                bestE = newE;\n                memcpy(best, tmp, sizeof(tmp));\n            }\n        }\n\n        ++stuck;\n        if (stuck > STUCK_LIMIT) {\n            // restart from best with small perturbations\n            memcpy(cur, best, sizeof(best));\n            for (int t = 0; t < 60; ++t) {\n                int i2 = rng_int(N2);\n                if (cur[i2] != 0) cur[i2] = rng_int(m) + 1;\n            }\n            eval(cur, m, curE, curVc, curVa);\n            cur_energy = -curE + W * (curVc + curVa);\n            stuck = 0;\n        }\n    }\n\n    // ----- final greedy erosion on best valid -----\n    memcpy(cur, best, sizeof(best));\n    // run several passes with different orders\n    for (int pass = 0; pass < 5 && ms() < 1990; ++pass) {\n        int newE = greedy_erode(cur, m);\n        if (newE > bestE) {\n            bestE = newE;\n            memcpy(best, cur, sizeof(cur));\n        }\n    }\n\n    // safety fallback\n    {\n        int e, vc, va;\n        eval(best, m, e, vc, va);\n        if (vc || va) {\n            memcpy(best, orig1d, sizeof(orig1d));\n        }\n    }\n\n    // ----- output -----\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (j) cout << ' ';\n            cout << best[i * N + j];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <cmath>\n\nusing namespace std;\n\nint N, D, Q_total;\nint used_queries = 0;\n\nchar ask(const vector<int>& L, const vector<int>& R) {\n    cout << L.size() << \" \" << R.size();\n    for (int x : L) cout << \" \" << x;\n    for (int x : R) cout << \" \" << x;\n    cout << endl;\n    char res; cin >> res;\n    used_queries++;\n    return res;\n}\n\nchar compare_items(int a, int b) {\n    return ask({a}, {b});\n}\n\n// ---------- Tournament tree ----------\nstruct TournamentTree {\n    int N;\n    int size;\n    vector<int> tree;         // 2*size, leaves indices\n    vector<int> leaf_pos;     // mapping item -> leaf index\n    vector<int> sorted;       // extracted in descending order\n    int height;\n    int extracted = 0;\n\n    TournamentTree(int n) : N(n) {\n        size = 1;\n        height = 0;\n        while (size < N) size <<= 1, height++;\n        tree.assign(2 * size, -1);\n        leaf_pos.resize(N);\n        for (int i = 0; i < N; ++i) {\n            int leaf = size + i;\n            tree[leaf] = i;\n            leaf_pos[i] = leaf;\n        }\n        // bottom\u2011up build\n        for (int i = size - 1; i >= 1; --i) {\n            int l = tree[2*i], r = tree[2*i+1];\n            if (l == -1) tree[i] = r;\n            else if (r == -1) tree[i] = l;\n            else {\n                if (used_queries >= Q_total) break;\n                char res = compare_items(l, r);\n                if (res == '>') tree[i] = l;\n                else if (res == '<') tree[i] = r;\n                else tree[i] = l;\n            }\n        }\n    }\n\n    // extract as many items as possible, leave only small leftover queries\n    void extract_all_possible() {\n        while (extracted < N && used_queries < Q_total) {\n            // need at least <height> comparisons for one full extraction\n            if (used_queries + height > Q_total) break;\n            int winner = tree[1];\n            if (winner == -1) break;\n            int leaf = leaf_pos[winner];\n            tree[leaf] = -1;\n            int node = leaf / 2;\n            while (node >= 1) {\n                int l = tree[2*node], r = tree[2*node+1];\n                if (l == -1) tree[node] = r;\n                else if (r == -1) tree[node] = l;\n                else {\n                    char res = compare_items(l, r);\n                    if (res == '>') tree[node] = l;\n                    else if (res == '<') tree[node] = r;\n                    else tree[node] = l;\n                }\n                node /= 2;\n            }\n            sorted.push_back(winner);\n            extracted++;\n        }\n    }\n\n    // return remaining items in heap BFS order\n    vector<int> get_remaining_order() {\n        vector<int> ord;\n        vector<bool> seen(N, false);\n        for (int i = 1; i < 2*size; ++i) {\n            int it = tree[i];\n            if (it != -1 && !seen[it]) {\n                seen[it] = true;\n                ord.push_back(it);\n            }\n        }\n        return ord;\n    }\n};\n\n// ---------- enforce known order ----------\nvoid enforce_order(vector<double>& w,\n                   const vector<int>& sorted,\n                   const vector<int>& remaining_order,\n                   int K) {\n    // among sorted items\n    for (int i = 0; i + 1 < K; ++i) {\n        int a = sorted[i], b = sorted[i+1];\n        if (w[a] < w[b]) {\n            double avg = (w[a] + w[b]) / 2.0;\n            w[a] = avg + 0.5;\n            w[b] = avg - 0.5;\n        }\n    }\n    // remaining <= smallest sorted\n    if (K > 0) {\n        int last = sorted[K-1];\n        for (int r : remaining_order) {\n            if (w[last] < w[r]) {\n                double avg = (w[last] + w[r]) / 2.0;\n                w[last] = avg + 0.5;\n                w[r] = avg - 0.5;\n            }\n        }\n    }\n    // clip\n    for (int i = 0; i < N; ++i) if (w[i] < 1.0) w[i] = 1.0;\n}\n\n// ---------- greedy partition ----------\nvector<int> greedy_partition(const vector<double>& w) {\n    vector<pair<double,int>> items(N);\n    for (int i = 0; i < N; ++i) items[i] = {w[i], i};\n    sort(items.begin(), items.end(),\n         [](auto& a, auto& b) { return a.first > b.first; });\n    vector<int> P(N, 0);\n    vector<double> bin_sum(D, 0.0);\n    for (auto& p : items) {\n        int idx = p.second;\n        int best = 0;\n        for (int b = 1; b < D; ++b)\n            if (bin_sum[b] < bin_sum[best]) best = b;\n        P[idx] = best;\n        bin_sum[best] += p.first;\n    }\n    return P;\n}\n\n// ---------- main ----------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    cin >> N >> D >> Q_total;\n    used_queries = 0;\n\n    // expected order statistics (exponential \u03bb=1e\u20115)\n    vector<double> H(N + 1, 0.0);\n    for (int i = 1; i <= N; ++i) H[i] = H[i-1] + 1.0 / i;\n    vector<double> exp_w(N);\n    for (int r = 0; r < N; ++r) {\n        exp_w[r] = 100000.0 * (H[N] - H[r]);\n    }\n\n    // Phase 1 : tournament sorting\n    TournamentTree tt(N);\n    tt.extract_all_possible();\n    vector<int>& sorted = tt.sorted;\n    int K = sorted.size();\n    vector<int> remaining_order = tt.get_remaining_order();\n\n    // initial weights\n    vector<double> w(N, 1.0);\n    for (int i = 0; i < K; ++i) w[sorted[i]] = exp_w[i];\n    for (int j = 0; j < (int)remaining_order.size(); ++j)\n        w[remaining_order[j]] = exp_w[K + j];\n    enforce_order(w, sorted, remaining_order, K);\n\n    // Phase 2 : use leftover queries for whole\u2011bin comparisons\n    struct BinQuery { vector<int> L, R; char res; };\n    vector<BinQuery> bin_queries;\n\n    vector<int> P = greedy_partition(w);\n\n    while (used_queries < Q_total) {\n        // current bin sums\n        vector<double> bin_sum(D, 0.0);\n        for (int i = 0; i < N; ++i) bin_sum[P[i]] += w[i];\n\n        // pick two non\u2011empty bins with closest sums\n        int b1 = -1, b2 = -1;\n        double min_diff = 1e30;\n        for (int i = 0; i < D; ++i) {\n            if (bin_sum[i] == 0) continue;\n            for (int j = i + 1; j < D; ++j) {\n                if (bin_sum[j] == 0) continue;\n                double diff = fabs(bin_sum[i] - bin_sum[j]);\n                if (diff < min_diff) { min_diff = diff; b1 = i; b2 = j; }\n            }\n        }\n        if (b1 == -1) { b1 = 0; b2 = 1 % D; }\n\n        vector<int> L, R;\n        for (int i = 0; i < N; ++i) {\n            if (P[i] == b1) L.push_back(i);\n            else if (P[i] == b2) R.push_back(i);\n        }\n\n        char res = ask(L, R);\n        bin_queries.push_back({L, R, res});\n\n        // online weight update\n        double sL = 0.0, sR = 0.0;\n        for (int i : L) sL += w[i];\n        for (int i : R) sR += w[i];\n        double margin = 0.0;\n        if (res == '<' && sL >= sR - margin) {\n            double error = sL - sR + margin;\n            double adj = 0.5 * error / (L.size() + R.size());\n            for (int i : L) w[i] -= adj;\n            for (int i : R) w[i] += adj;\n        } else if (res == '>' && sL <= sR + margin) {\n            double error = sR - sL + margin;\n            double adj = 0.5 * error / (L.size() + R.size());\n            for (int i : L) w[i] += adj;\n            for (int i : R) w[i] -= adj;\n        } else if (res == '=' && fabs(sL - sR) > margin) {\n            double diff = sL - sR;\n            double adj = 0.5 * diff / (L.size() + R.size());\n            for (int i : L) w[i] -= adj;\n            for (int i : R) w[i] += adj;\n        }\n        for (int i : L) w[i] = max(w[i], 1.0);\n        for (int i : R) w[i] = max(w[i], 1.0);\n        enforce_order(w, sorted, remaining_order, K);\n\n        if (used_queries % 5 == 0)\n            P = greedy_partition(w);\n    }\n\n    // Phase 3 : post\u2011process weight refinement on all bin queries\n    if (!bin_queries.empty()) {\n        int iterations = min(2000, (int)bin_queries.size() * 5);\n        double step = 0.3;\n        for (int it = 0; it < iterations; ++it) {\n            for (auto& q : bin_queries) {\n                double sL = 0.0, sR = 0.0;\n                for (int i : q.L) sL += w[i];\n                for (int i : q.R) sR += w[i];\n                if (q.res == '<' && sL >= sR) {\n                    double error = sL - sR + 1.0;\n                    double adj = step * error / (q.L.size() + q.R.size());\n                    for (int i : q.L) w[i] -= adj;\n                    for (int i : q.R) w[i] += adj;\n                } else if (q.res == '>' && sL <= sR) {\n                    double error = sR - sL + 1.0;\n                    double adj = step * error / (q.L.size() + q.R.size());\n                    for (int i : q.L) w[i] += adj;\n                    for (int i : q.R) w[i] -= adj;\n                } else if (q.res == '=' && fabs(sL - sR) > 0.5) {\n                    double diff = sL - sR;\n                    double adj = step * diff / (q.L.size() + q.R.size());\n                    for (int i : q.L) w[i] -= adj;\n                    for (int i : q.R) w[i] += adj;\n                }\n                for (int i : q.L) w[i] = max(w[i], 1.0);\n                for (int i : q.R) w[i] = max(w[i], 1.0);\n            }\n            enforce_order(w, sorted, remaining_order, K);\n            step *= 0.999;\n            if (step < 0.01) step = 0.01;\n        }\n    }\n\n    // Phase 4 : final refinement via Simulated Annealing\n    vector<int> bestP = greedy_partition(w);\n    vector<double> bin_sum(D, 0.0);\n    for (int i = 0; i < N; ++i) bin_sum[bestP[i]] += w[i];\n    double mean = accumulate(bin_sum.begin(), bin_sum.end(), 0.0) / D;\n    double best_var = 0.0;\n    for (double s : bin_sum) best_var += (s - mean) * (s - mean);\n    best_var /= D;\n\n    mt19937 rng(12345);\n    uniform_int_distribution<int> dist_item(0, N - 1);\n    uniform_int_distribution<int> dist_bin(0, D - 2);\n    uniform_real_distribution<double> uni(0.0, 1.0);\n\n    const int SA_ITERS = 300000;\n    double T = 1.0;\n    vector<int> curP = bestP;\n    vector<double> cur_bin_sum = bin_sum;\n    double cur_var = best_var;\n\n    for (int it = 0; it < SA_ITERS; ++it) {\n        int i = dist_item(rng);\n        int old_b = curP[i];\n        int new_b = dist_bin(rng);\n        if (new_b >= old_b) new_b++;\n        if (new_b == old_b) continue;\n\n        double new_old = cur_bin_sum[old_b] - w[i];\n        double new_new = cur_bin_sum[new_b] + w[i];\n        double delta = ((new_old - mean) * (new_old - mean) +\n                        (new_new - mean) * (new_new - mean)\n                        - (cur_bin_sum[old_b] - mean) * (cur_bin_sum[old_b] - mean)\n                        - (cur_bin_sum[new_b] - mean) * (cur_bin_sum[new_b] - mean)) / D;\n        if (delta < 0 || uni(rng) < exp(-delta / T)) {\n            curP[i] = new_b;\n            cur_bin_sum[old_b] = new_old;\n            cur_bin_sum[new_b] = new_new;\n            cur_var += delta;\n            if (cur_var < best_var) {\n                best_var = cur_var;\n                bestP = curP;\n            }\n        }\n        T *= 0.9999;\n        if (T < 0.001) T = 0.001;\n    }\n\n    // output\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << \" \";\n        cout << bestP[i];\n    }\n    cout << endl;\n\n    return 0;\n}","ahc026":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <climits>\n#include <utility>\n\nusing namespace std;\n\nstruct State {\n    int n, m;\n    vector<vector<int>> stacks;\n    vector<pair<int,int>> pos;     // pos[box] = {stack, index}\n    vector<int> min_val;           // minimum value in each stack, INT_MAX if empty\n\n    State(const vector<vector<int>>& init, int n_, int m_) : n(n_), m(m_) {\n        stacks = init;\n        pos.assign(n + 1, {-1, -1});\n        min_val.assign(m, INT_MAX);\n        for (int i = 0; i < m; ++i) {\n            for (int j = 0; j < (int)stacks[i].size(); ++j) {\n                int box = stacks[i][j];\n                pos[box] = {i, j};\n            }\n            if (!stacks[i].empty())\n                min_val[i] = *min_element(stacks[i].begin(), stacks[i].end());\n        }\n    }\n\n    // Move boxes [idx .. end] from stack s to stack t.\n    void move_block(int s, int idx, int t) {\n        vector<int> block(stacks[s].begin() + idx, stacks[s].end());\n        stacks[s].erase(stacks[s].begin() + idx, stacks[s].end());\n        int min_moved = INT_MAX;\n        for (int val : block) {\n            stacks[t].push_back(val);\n            pos[val] = {t, (int)stacks[t].size() - 1};\n            if (val < min_moved) min_moved = val;\n        }\n        // update min_val for s\n        if (stacks[s].empty()) min_val[s] = INT_MAX;\n        else min_val[s] = *min_element(stacks[s].begin(), stacks[s].end());\n        // update min_val for t\n        if (stacks[t].empty()) min_val[t] = min_moved;\n        else min_val[t] = min(min_val[t], min_moved);\n    }\n\n    // Remove the top box of stack s (the current target box).\n    void carry_out(int s) {\n        int v = stacks[s].back();\n        stacks[s].pop_back();\n        pos[v] = {-1, -1};\n        if (stacks[s].empty()) {\n            min_val[s] = INT_MAX;\n        } else if (v == min_val[s]) {\n            min_val[s] = *min_element(stacks[s].begin(), stacks[s].end());\n        }\n    }\n};\n\n// Scoring for destination stack. Returns a numeric score (higher = better).\nlong long target_score(const State& st, int s, int t, int max_block) {\n    if (st.stacks[t].empty()) {\n        return 1LL * INT_MAX + 0;       // empty: priority 1\n    } else {\n        int min_t = st.min_val[t];\n        if (min_t > max_block) {        // ideal\n            return 2LL * INT_MAX + min_t;\n        } else {                        // violation\n            return 0LL * INT_MAX + min_t;\n        }\n    }\n}\n\n// Greedy choice of a destination stack (used in simulations).\nint choose_target(const State& st, int s, int p) {\n    int max_block = -1;\n    for (int i = p + 1; i < (int)st.stacks[s].size(); ++i)\n        max_block = max(max_block, st.stacks[s][i]);\n    long long best_score = -1;\n    int best_t = -1;\n    for (int t = 0; t < st.m; ++t) {\n        if (t == s) continue;\n        long long sc = target_score(st, s, t, max_block);\n        if (sc > best_score) {\n            best_score = sc;\n            best_t = t;\n        }\n    }\n    return best_t;\n}\n\n// Greedy simulation from box start_v to the end.\nint greedy_cost(State state, int start_v) {\n    int total = 0;\n    for (int v = start_v; v <= state.n; ++v) {\n        auto [s, p] = state.pos[v];\n        while (p != (int)state.stacks[s].size() - 1) {\n            int idx = p + 1;\n            int k = state.stacks[s].size() - idx;\n            int t = choose_target(state, s, p);\n            state.move_block(s, idx, t);\n            total += k + 1;\n        }\n        state.carry_out(s);\n    }\n    return total;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int n, m;\n    cin >> n >> m;\n    vector<vector<int>> init_stacks(m, vector<int>(n / m));\n    for (int i = 0; i < m; ++i)\n        for (int j = 0; j < n / m; ++j)\n            cin >> init_stacks[i][j];\n\n    State init_state(init_stacks, n, m);\n\n    struct HistoryNode {\n        State state;\n        int parent;\n        int cost_so_far;\n        bool is_move;\n        int v_op;            // box chosen for move (valid if is_move)\n        int dest_t;          // destination stack (1\u2011based)\n        int v_carry;         // box carried out (always the current v)\n    };\n\n    vector<HistoryNode> history;\n    history.push_back({init_state, -1, 0, false, 0, 0, 0});\n    vector<int> beam = {0};\n\n    const int BEAM_WIDTH = 200;\n    const int TOP_DESTS = 3;   // number of top destination stacks to consider per parent\n\n    for (int v = 1; v <= n; ++v) {\n        vector<HistoryNode> candidates;\n        candidates.reserve(beam.size() * m);\n\n        for (int idx : beam) {\n            HistoryNode& cur = history[idx];\n            int s = cur.state.pos[v].first;\n            int p = cur.state.pos[v].second;\n\n            if (p == (int)cur.state.stacks[s].size() - 1) {\n                // v is already on top \u2013 carry it out directly\n                State new_st = cur.state;\n                new_st.carry_out(s);\n                candidates.push_back({move(new_st), idx, cur.cost_so_far, false, 0, 0, v});\n            } else {\n                // Compute max block above v once\n                int max_block = -1;\n                for (int i = p + 1; i < (int)cur.state.stacks[s].size(); ++i)\n                    max_block = max(max_block, cur.state.stacks[s][i]);\n\n                // Score all possible destinations and keep up to TOP_DESTS best\n                vector<pair<long long, int>> scored_t;\n                for (int t = 0; t < m; ++t) {\n                    if (t == s) continue;\n                    long long sc = target_score(cur.state, s, t, max_block);\n                    scored_t.push_back({sc, t});\n                }\n                // partial sort: we need only the best TOP_DESTS\n                if ((int)scored_t.size() > TOP_DESTS) {\n                    nth_element(scored_t.begin(), scored_t.begin() + TOP_DESTS, scored_t.end(),\n                                [](const pair<long long,int>& a, const pair<long long,int>& b) {\n                                    return a.first > b.first;\n                                });\n                    scored_t.resize(TOP_DESTS);\n                }\n\n                int idx_block = p + 1;\n                int k = cur.state.stacks[s].size() - idx_block;\n                for (auto &[sc, t] : scored_t) {\n                    State new_st = cur.state;\n                    new_st.move_block(s, idx_block, t);\n                    new_st.carry_out(s);\n                    int u = cur.state.stacks[s][idx_block]; // box moved together with the block\n                    candidates.push_back({move(new_st), idx, cur.cost_so_far + (k + 1), true, u, t + 1, v});\n                }\n            }\n        }\n\n        // Prune to beam width using full greedy simulation\n        if ((int)candidates.size() > BEAM_WIDTH) {\n            vector<pair<int,int>> scored;\n            scored.reserve(candidates.size());\n            for (int i = 0; i < (int)candidates.size(); ++i) {\n                int est = candidates[i].cost_so_far + greedy_cost(candidates[i].state, v + 1);\n                scored.push_back({est, i});\n            }\n            sort(scored.begin(), scored.end());\n            vector<HistoryNode> kept;\n            kept.reserve(BEAM_WIDTH);\n            for (int i = 0; i < BEAM_WIDTH; ++i) {\n                kept.push_back(move(candidates[scored[i].second]));\n            }\n            candidates.swap(kept);\n        }\n\n        beam.clear();\n        for (auto& cand : candidates) {\n            beam.push_back((int)history.size());\n            history.push_back(move(cand));\n        }\n    }\n\n    // Pick the best final state (lowest total energy)\n    int best_idx = beam[0];\n    int best_cost = history[best_idx].cost_so_far;\n    for (int idx : beam) {\n        if (history[idx].cost_so_far < best_cost) {\n            best_cost = history[idx].cost_so_far;\n            best_idx = idx;\n        }\n    }\n\n    // Reconstruct operations\n    vector<pair<int,int>> ops;\n    int cur_idx = best_idx;\n    while (history[cur_idx].parent != -1) {\n        const HistoryNode& node = history[cur_idx];\n        if (node.is_move) {\n            // Walking backward: we first carried out, then moved.\n            // Chronological order: move then carry.\n            ops.push_back({node.v_carry, 0});\n            ops.push_back({node.v_op, node.dest_t});\n        } else {\n            ops.push_back({node.v_carry, 0});\n        }\n        cur_idx = node.parent;\n    }\n    reverse(ops.begin(), ops.end());\n\n    for (auto &op : ops)\n        cout << op.first << \" \" << op.second << \"\\n\";\n\n    return 0;\n}","ahc027":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <functional>\n#include <stack>\n#include <numeric>\n#include <cassert>\n\nusing namespace std;\n\n// ---------- Dinic max flow ----------\nstruct Dinic {\n    struct Edge {\n        int to, rev, cap, init;\n        Edge() {}\n        Edge(int to, int rev, int cap, int init) : to(to), rev(rev), cap(cap), init(init) {}\n    };\n    vector<vector<Edge>> g;\n    vector<int> level, iter;\n    Dinic(int n) : g(n) {}\n    void add_edge(int from, int to, int cap) {\n        g[from].push_back(Edge(to, (int)g[to].size(), cap, cap));\n        g[to].push_back(Edge(from, (int)g[from].size() - 1, 0, 0));\n    }\n    void bfs(int s) {\n        fill(level.begin(), level.end(), -1);\n        queue<int> q;\n        level[s] = 0;\n        q.push(s);\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (auto &e : g[v]) {\n                if (e.cap > 0 && level[e.to] < 0) {\n                    level[e.to] = level[v] + 1;\n                    q.push(e.to);\n                }\n            }\n        }\n    }\n    int dfs(int v, int t, int f) {\n        if (v == t) return f;\n        for (int &i = iter[v]; i < (int)g[v].size(); ++i) {\n            Edge &e = g[v][i];\n            if (e.cap > 0 && level[v] < level[e.to]) {\n                int d = dfs(e.to, t, min(f, e.cap));\n                if (d > 0) {\n                    e.cap -= d;\n                    g[e.to][e.rev].cap += d;\n                    return d;\n                }\n            }\n        }\n        return 0;\n    }\n    int max_flow(int s, int t) {\n        int flow = 0;\n        level.resize(g.size());\n        iter.resize(g.size());\n        while (true) {\n            bfs(s);\n            if (level[t] < 0) break;\n            fill(iter.begin(), iter.end(), 0);\n            int f;\n            while ((f = dfs(s, t, 1e9)) > 0) flow += f;\n        }\n        return flow;\n    }\n};\n\n// ---------- helper for average dirtiness ----------\nint64_t calc_sum_sq(const vector<int>& times, int L) {\n    if (times.empty()) return 0;\n    int k = times.size();\n    int64_t res = 0;\n    for (int i = 0; i < k - 1; ++i) {\n        int64_t diff = times[i + 1] - times[i];\n        res += diff * diff;\n    }\n    int64_t diff = times[0] + L - times.back();\n    res += diff * diff;\n    return res;\n}\n\n// ---------- Greedy Eulerian circuit ----------\nvector<int> greedy_euler(const vector<vector<int>>& mult_adj, const vector<int>& d,\n                         mt19937_64& rng, double noise_scale) {\n    int V = mult_adj.size();\n    vector<vector<int>> adj = mult_adj;\n    vector<int> res;\n    stack<int> st;\n    st.push(0);\n    int step = 0;\n    vector<int> last_visit(V, 0);\n    uniform_real_distribution<double> noise(0.0, noise_scale);\n\n    while (!st.empty()) {\n        int u = st.top();\n        if (adj[u].empty()) {\n            res.push_back(u);\n            st.pop();\n            if (!st.empty()) step++;\n        } else {\n            int best_idx = 0;\n            double best_score = -1e18;\n            for (int i = 0; i < (int)adj[u].size(); ++i) {\n                int v = adj[u][i];\n                int gap = step + 1 - last_visit[v];\n                double score = d[v] * (double)gap * gap + noise(rng);\n                if (score > best_score) {\n                    best_score = score;\n                    best_idx = i;\n                }\n            }\n            int v = adj[u][best_idx];\n            // remove edge\n            adj[u][best_idx] = adj[u].back();\n            adj[u].pop_back();\n            auto &vadj = adj[v];\n            for (int i = 0; i < (int)vadj.size(); ++i) {\n                if (vadj[i] == u) {\n                    vadj[i] = vadj.back();\n                    vadj.pop_back();\n                    break;\n                }\n            }\n            st.push(v);\n            step++;\n            last_visit[v] = step;\n        }\n    }\n    reverse(res.begin(), res.end());\n    return res;\n}\n\n// ---------- fallback : original greedy + SA ----------\nstring fallback_solution(int N, int V, const vector<int>& d,\n                         const vector<vector<int>>& adj,\n                         const vector<vector<bool>>& adjmat) {\n    vector<int> base_seq;\n    vector<bool> visited(V, false);\n    vector<int> stk = {0};\n    vector<int> edge_idx(V, 0);\n    visited[0] = true;\n    while (!stk.empty()) {\n        int u = stk.back();\n        if (edge_idx[u] < (int)adj[u].size()) {\n            int w = adj[u][edge_idx[u]++];\n            if (!visited[w]) {\n                visited[w] = true;\n                base_seq.push_back(w);\n                stk.push_back(w);\n            }\n        } else {\n            stk.pop_back();\n            if (!stk.empty()) base_seq.push_back(stk.back());\n        }\n    }\n\n    int L0 = base_seq.size();\n    vector<int> cur_k(V, 0);\n    for (int c : base_seq) cur_k[c]++;\n\n    int L_target = 100000;\n    vector<int> seq = base_seq;\n    int L = L0;\n\n    double sum_sqrt = 0;\n    for (int i = 0; i < V; ++i) sum_sqrt += sqrt(d[i]);\n    vector<double> target_k(V);\n    for (int i = 0; i < V; ++i) target_k[i] = L_target * sqrt(d[i]) / sum_sqrt;\n\n    vector<int> parent(V, -1);\n    queue<int> q;\n    q.push(0);\n    parent[0] = -2;\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (int w : adj[u]) {\n            if (parent[w] == -1) {\n                parent[w] = u;\n                q.push(w);\n            }\n        }\n    }\n\n    while (L < L_target) {\n        int best = -1;\n        double best_score = -1;\n        for (int i = 0; i < V; ++i) {\n            double deficit = target_k[i] - cur_k[i];\n            if (deficit > 0) {\n                double score = d[i] * deficit;\n                if (score > best_score) {\n                    best_score = score;\n                    best = i;\n                }\n            }\n        }\n        if (best == -1) break;\n        int dest = best;\n        vector<int> path;\n        for (int u = dest; u != 0; u = parent[u]) path.push_back(u);\n        reverse(path.begin(), path.end());\n        int cycle_len = 2 * (int)path.size();\n        if (L + cycle_len > L_target) break;\n\n        for (int c : path) seq.push_back(c);\n        for (int i = (int)path.size() - 2; i >= 0; --i) seq.push_back(path[i]);\n        seq.push_back(0);\n\n        for (int i = 0; i < (int)path.size(); ++i) {\n            int c = path[i];\n            if (i == (int)path.size() - 1) cur_k[c] += 1;\n            else cur_k[c] += 2;\n        }\n        cur_k[0] += 1;\n        L += cycle_len;\n    }\n\n    vector<vector<int>> times(V);\n    for (int t = 0; t < L; ++t) times[seq[t]].push_back(t);\n    vector<int64_t> sq(V);\n    int64_t total_O = 0;\n    for (int i = 0; i < V; ++i) {\n        sq[i] = calc_sum_sq(times[i], L);\n        total_O += d[i] * sq[i];\n    }\n    vector<int> best_seq = seq;\n    int64_t best_O = total_O;\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> uni01(0.0, 1.0);\n\n    double T_start = max(1e7, (double)total_O / 1000.0);\n    double T_end = 1e2;\n    auto start_time = chrono::steady_clock::now();\n    double total_time = 1.95;\n\n    vector<int> affected;\n    vector<bool> is_aff(V, false);\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed >= total_time) break;\n        double ratio = elapsed / total_time;\n        if (ratio > 1.0) ratio = 1.0;\n        double T = T_start * pow(T_end / T_start, ratio);\n\n        for (int c : affected) is_aff[c] = false;\n        affected.clear();\n\n        if (L < 3) break;\n        int max_len = min(5000, L - 2);\n        if (max_len < 1) continue;\n        uniform_int_distribution<int> l_dist(1, L - 3);\n        int l = l_dist(rng);\n        int max_r = min(L - 2, l + max_len - 1);\n        if (max_r < l) continue;\n        uniform_int_distribution<int> r_dist(l, max_r);\n        int r = r_dist(rng);\n\n        int u1 = seq[l - 1], v1 = seq[r];\n        int u2 = seq[l], v2 = seq[r + 1];\n        if (!adjmat[u1][v1] || !adjmat[u2][v2]) continue;\n\n        for (int p = l; p <= r; ++p) {\n            int c = seq[p];\n            if (!is_aff[c]) {\n                is_aff[c] = true;\n                affected.push_back(c);\n            }\n        }\n\n        int64_t delta = 0;\n        vector<pair<int, vector<int>>> updates;\n        vector<int64_t> new_sq(affected.size());\n        for (int idx = 0; idx < (int)affected.size(); ++idx) {\n            int c = affected[idx];\n            const vector<int>& old_times = times[c];\n            int n = old_times.size();\n            int start_idx = lower_bound(old_times.begin(), old_times.end(), l) - old_times.begin();\n            int end_idx = upper_bound(old_times.begin() + start_idx, old_times.end(), r) - old_times.begin();\n\n            vector<int> new_times;\n            new_times.reserve(n);\n            for (int i = 0; i < start_idx; ++i) new_times.push_back(old_times[i]);\n            for (int i = end_idx - 1; i >= start_idx; --i) new_times.push_back(l + r - old_times[i]);\n            for (int i = end_idx; i < n; ++i) new_times.push_back(old_times[i]);\n\n            int64_t old_sq = sq[c];\n            int64_t n_sq = calc_sum_sq(new_times, L);\n            delta += d[c] * (n_sq - old_sq);\n            updates.emplace_back(c, std::move(new_times));\n            new_sq[idx] = n_sq;\n        }\n\n        if (delta <= 0 || uni01(rng) < exp(-delta / T)) {\n            reverse(seq.begin() + l, seq.begin() + r + 1);\n            for (int idx = 0; idx < (int)affected.size(); ++idx) {\n                int c = affected[idx];\n                times[c] = std::move(updates[idx].second);\n                sq[c] = new_sq[idx];\n            }\n            total_O += delta;\n            if (total_O < best_O) {\n                best_O = total_O;\n                best_seq = seq;\n            }\n        }\n    }\n\n    string ans;\n    int cur = 0;\n    for (int nxt : best_seq) {\n        int ci = cur / N, cj = cur % N;\n        int ni = nxt / N, nj = nxt % N;\n        if (ni == ci - 1) ans += 'U';\n        else if (ni == ci + 1) ans += 'D';\n        else if (nj == cj - 1) ans += 'L';\n        else if (nj == cj + 1) ans += 'R';\n        else ans += 'U';\n        cur = nxt;\n    }\n    return ans;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int N;\n    cin >> N;\n    int V = N * N;\n    vector<string> h(N - 1), v(N);\n    for (int i = 0; i < N - 1; ++i) cin >> h[i];\n    for (int i = 0; i < N; ++i) cin >> v[i];\n    vector<int> d(V);\n    for (int i = 0; i < V; ++i) cin >> d[i];\n\n    auto id = [&](int i, int j) { return i * N + j; };\n\n    vector<vector<pair<int,int>>> adj(V);\n    vector<pair<int,int>> edge_uv;\n    int E = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = id(i, j);\n            if (j + 1 < N && v[i][j] == '0') {\n                int w = id(i, j + 1);\n                adj[u].emplace_back(w, E);\n                adj[w].emplace_back(u, E);\n                edge_uv.emplace_back(u, w);\n                E++;\n            }\n            if (i + 1 < N && h[i][j] == '0') {\n                int w = id(i + 1, j);\n                adj[u].emplace_back(w, E);\n                adj[w].emplace_back(u, E);\n                edge_uv.emplace_back(u, w);\n                E++;\n            }\n        }\n    }\n\n    vector<vector<int>> simple_adj(V);\n    vector<vector<bool>> adjmat(V, vector<bool>(V, false));\n    for (int i = 0; i < V; ++i)\n        for (auto [w, _] : adj[i]) {\n            simple_adj[i].push_back(w);\n            adjmat[i][w] = true;\n        }\n\n    // Spanning tree\n    vector<int> parent(V, -1);\n    vector<int> deg_T(V, 0);\n    vector<int> tree_edge(E, 0);\n    queue<int> q;\n    q.push(0);\n    parent[0] = -2;\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (auto [w, eid] : adj[u]) {\n            if (parent[w] == -1) {\n                parent[w] = u;\n                deg_T[u]++;\n                deg_T[w]++;\n                tree_edge[eid] = 1;\n                q.push(w);\n            }\n        }\n    }\n\n    // bipartition\n    vector<bool> left(V, false);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            left[id(i,j)] = ((i + j) % 2 == 0);\n\n    int L_target = 100000;\n    int L_half = L_target / 2;\n\n    vector<int> min_f(V);\n    for (int i = 0; i < V; ++i)\n        min_f[i] = max(1, (deg_T[i] + 1) / 2);\n\n    int min_left = 0, min_right = 0;\n    for (int i = 0; i < V; ++i) {\n        if (left[i]) min_left += min_f[i];\n        else min_right += min_f[i];\n    }\n\n    if (min_left > L_half || min_right > L_half) {\n        cout << fallback_solution(N, V, d, simple_adj, adjmat) << endl;\n        return 0;\n    }\n\n    vector<int> f(V, 0);\n\n    auto allocate_side_greedy = [&](bool is_left, int total, int sum_min) {\n        vector<int> idx;\n        for (int i = 0; i < V; ++i) if (left[i] == is_left) idx.push_back(i);\n        int n = idx.size();\n        if (n == 0) return;\n        vector<int> cur_f(n);\n        for (int i = 0; i < n; ++i) cur_f[i] = min_f[idx[i]];\n        int cur_sum = sum_min;\n\n        struct Item {\n            double gain;\n            int id;\n            bool operator<(const Item& o) const { return gain < o.gain; }\n        };\n        priority_queue<Item> pq;\n        for (int i = 0; i < n; ++i) {\n            int fi = cur_f[i];\n            double gain = (double)d[idx[i]] / ((int64_t)fi * (fi + 1));\n            pq.push({gain, i});\n        }\n\n        while (cur_sum < total) {\n            Item it = pq.top(); pq.pop();\n            int i = it.id;\n            cur_f[i]++;\n            cur_sum++;\n            int fi = cur_f[i];\n            double new_gain = (double)d[idx[i]] / ((int64_t)fi * (fi + 1));\n            pq.push({new_gain, i});\n        }\n\n        for (int i = 0; i < n; ++i) f[idx[i]] = cur_f[i];\n    };\n\n    allocate_side_greedy(true, L_half, min_left);\n    allocate_side_greedy(false, L_half, min_right);\n\n    if (accumulate(f.begin(), f.end(), 0) != L_target) {\n        cout << fallback_solution(N, V, d, simple_adj, adjmat) << endl;\n        return 0;\n    }\n\n    vector<int> b(V), rem(V);\n    int rem_left_sum = 0;\n    for (int i = 0; i < V; ++i) {\n        b[i] = 2 * f[i];\n        rem[i] = b[i] - deg_T[i];\n        if (left[i]) rem_left_sum += rem[i];\n    }\n\n    int S = V, T = V + 1;\n    Dinic dinic(V + 2);\n    vector<int> flow_fwd_idx(E, -1);\n\n    for (int eid = 0; eid < E; ++eid) {\n        int u = edge_uv[eid].first, v = edge_uv[eid].second;\n        if (!left[u]) swap(u, v);\n        int idx = (int)dinic.g[u].size();\n        dinic.add_edge(u, v, 1000000);\n        flow_fwd_idx[eid] = idx;\n    }\n\n    for (int i = 0; i < V; ++i) {\n        if (left[i]) dinic.add_edge(S, i, rem[i]);\n        else dinic.add_edge(i, T, rem[i]);\n    }\n\n    int flow_val = dinic.max_flow(S, T);\n    if (flow_val != rem_left_sum) {\n        cout << fallback_solution(N, V, d, simple_adj, adjmat) << endl;\n        return 0;\n    }\n\n    vector<int> mult(E, 0);\n    for (int eid = 0; eid < E; ++eid) {\n        int base = tree_edge[eid];\n        int u = edge_uv[eid].first, v = edge_uv[eid].second;\n        if (!left[u]) swap(u, v);\n        int fwd_idx = flow_fwd_idx[eid];\n        int fe = dinic.g[u][fwd_idx].init - dinic.g[u][fwd_idx].cap;\n        mult[eid] = base + fe;\n    }\n\n    vector<vector<int>> mult_adj(V);\n    for (int eid = 0; eid < E; ++eid) {\n        int m = mult[eid];\n        int u = edge_uv[eid].first, v = edge_uv[eid].second;\n        for (int k = 0; k < m; ++k) {\n            mult_adj[u].push_back(v);\n            mult_adj[v].push_back(u);\n        }\n    }\n\n    auto start_time = chrono::steady_clock::now();\n    const double time_for_initial = 0.85;\n    const double total_time_limit = 1.95;\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    // Generate many greedy Eulerian circuits, keep best\n    int64_t best_initial_O = 1e18;\n    vector<int> best_initial_seq;\n\n    int trials = 200;\n    for (int trial = 0; trial < trials; ++trial) {\n        if (chrono::duration<double>(chrono::steady_clock::now() - start_time).count() > time_for_initial) break;\n        double noise_scale = (trial < 10 ? 0.0 : (trial < 50 ? 5.0 : (trial < 100 ? 15.0 : 30.0)));\n        vector<int> circuit = greedy_euler(mult_adj, d, rng, noise_scale);\n        int first0 = find(circuit.begin(), circuit.end(), 0) - circuit.begin();\n        vector<int> rot;\n        rot.insert(rot.end(), circuit.begin() + first0, circuit.end());\n        rot.insert(rot.end(), circuit.begin(), circuit.begin() + first0);\n        vector<int> seq(rot.begin() + 1, rot.end());\n        vector<vector<int>> times(V);\n        for (int t = 0; t < (int)seq.size(); ++t) times[seq[t]].push_back(t);\n        int64_t O = 0;\n        for (int i = 0; i < V; ++i) O += d[i] * calc_sum_sq(times[i], (int)seq.size());\n        if (O < best_initial_O) {\n            best_initial_O = O;\n            best_initial_seq = move(seq);\n        }\n    }\n\n    vector<int> seq = best_initial_seq;\n    int L = seq.size();\n\n    vector<vector<int>> times(V);\n    for (int t = 0; t < L; ++t) times[seq[t]].push_back(t);\n    vector<int64_t> sq(V);\n    int64_t total_O = 0;\n    for (int i = 0; i < V; ++i) {\n        sq[i] = calc_sum_sq(times[i], L);\n        total_O += d[i] * sq[i];\n    }\n    vector<int> best_seq = seq;\n    int64_t best_O = total_O;\n\n    uniform_real_distribution<double> uni01(0.0, 1.0);\n\n    // ---------- 2-opt move helper ----------\n    auto try_move = [&](int l, int r, bool forced) -> bool {\n        int u1 = seq[l - 1], v1 = seq[r];\n        int u2 = seq[l], v2 = seq[r + 1];\n        if (!adjmat[u1][v1] || !adjmat[u2][v2]) return false;\n\n        vector<int> affected;\n        vector<bool> is_aff(V, false);\n        for (int p = l; p <= r; ++p) {\n            int c = seq[p];\n            if (!is_aff[c]) {\n                is_aff[c] = true;\n                affected.push_back(c);\n            }\n        }\n\n        int64_t delta = 0;\n        vector<pair<int, vector<int>>> updates;\n        vector<int64_t> new_sq(affected.size());\n        for (int idx = 0; idx < (int)affected.size(); ++idx) {\n            int c = affected[idx];\n            const vector<int>& old_times = times[c];\n            int n = old_times.size();\n            int start_idx = lower_bound(old_times.begin(), old_times.end(), l) - old_times.begin();\n            int end_idx = upper_bound(old_times.begin() + start_idx, old_times.end(), r) - old_times.begin();\n\n            vector<int> new_times;\n            new_times.reserve(n);\n            for (int i = 0; i < start_idx; ++i) new_times.push_back(old_times[i]);\n            for (int i = end_idx - 1; i >= start_idx; --i) new_times.push_back(l + r - old_times[i]);\n            for (int i = end_idx; i < n; ++i) new_times.push_back(old_times[i]);\n\n            int64_t old_sq = sq[c];\n            int64_t n_sq = calc_sum_sq(new_times, L);\n            delta += d[c] * (n_sq - old_sq);\n            updates.emplace_back(c, std::move(new_times));\n            new_sq[idx] = n_sq;\n        }\n\n        if (forced || delta <= 0) {\n            reverse(seq.begin() + l, seq.begin() + r + 1);\n            for (int idx = 0; idx < (int)affected.size(); ++idx) {\n                int c = affected[idx];\n                times[c] = std::move(updates[idx].second);\n                sq[c] = new_sq[idx];\n            }\n            total_O += delta;\n            return true;\n        }\n        return false;\n    };\n\n    // ---------- Hill climbing (greedy improvements) ----------\n    int hill_steps = 30000;\n    for (int step = 0; step < hill_steps; ++step) {\n        if (chrono::duration<double>(chrono::steady_clock::now() - start_time).count() > total_time_limit * 0.5) break;\n        if (L < 3) break;\n        int max_len = min(4000, L - 2);\n        uniform_int_distribution<int> l_dist(1, L - 3);\n        int l = l_dist(rng);\n        int max_r = min(L - 2, l + max_len - 1);\n        if (max_r < l) continue;\n        uniform_int_distribution<int> r_dist(l, max_r);\n        int r = r_dist(rng);\n        if (try_move(l, r, false)) {\n            if (total_O < best_O) {\n                best_O = total_O;\n                best_seq = seq;\n            }\n        }\n    }\n\n    // ---------- Simulated Annealing ----------\n    double T_start = max(1e5, (double)total_O / 10000.0);\n    double T_end = 1e1;\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed >= total_time_limit) break;\n        double ratio = elapsed / total_time_limit;\n        if (ratio > 1.0) ratio = 1.0;\n        double T = T_start * pow(T_end / T_start, ratio);\n        int base_len = 5000;\n        int extra_len = (int)(20000 * (1.0 - ratio));\n        int max_len = min(base_len + extra_len, L - 2);\n\n        if (L < 3) break;\n        uniform_int_distribution<int> l_dist(1, L - 3);\n        int l = l_dist(rng);\n        int max_r = min(L - 2, l + max_len - 1);\n        if (max_r < l) continue;\n        uniform_int_distribution<int> r_dist(l, max_r);\n        int r = r_dist(rng);\n\n        int u1 = seq[l - 1], v1 = seq[r];\n        int u2 = seq[l], v2 = seq[r + 1];\n        if (!adjmat[u1][v1] || !adjmat[u2][v2]) continue;\n\n        vector<int> affected;\n        vector<bool> is_aff(V, false);\n        for (int p = l; p <= r; ++p) {\n            int c = seq[p];\n            if (!is_aff[c]) {\n                is_aff[c] = true;\n                affected.push_back(c);\n            }\n        }\n\n        int64_t delta = 0;\n        vector<pair<int, vector<int>>> updates;\n        vector<int64_t> new_sq(affected.size());\n        for (int idx = 0; idx < (int)affected.size(); ++idx) {\n            int c = affected[idx];\n            const vector<int>& old_times = times[c];\n            int n = old_times.size();\n            int start_idx = lower_bound(old_times.begin(), old_times.end(), l) - old_times.begin();\n            int end_idx = upper_bound(old_times.begin() + start_idx, old_times.end(), r) - old_times.begin();\n\n            vector<int> new_times;\n            new_times.reserve(n);\n            for (int i = 0; i < start_idx; ++i) new_times.push_back(old_times[i]);\n            for (int i = end_idx - 1; i >= start_idx; --i) new_times.push_back(l + r - old_times[i]);\n            for (int i = end_idx; i < n; ++i) new_times.push_back(old_times[i]);\n\n            int64_t old_sq = sq[c];\n            int64_t n_sq = calc_sum_sq(new_times, L);\n            delta += d[c] * (n_sq - old_sq);\n            updates.emplace_back(c, std::move(new_times));\n            new_sq[idx] = n_sq;\n        }\n\n        if (delta <= 0 || uni01(rng) < exp(-delta / T)) {\n            reverse(seq.begin() + l, seq.begin() + r + 1);\n            for (int idx = 0; idx < (int)affected.size(); ++idx) {\n                int c = affected[idx];\n                times[c] = std::move(updates[idx].second);\n                sq[c] = new_sq[idx];\n            }\n            total_O += delta;\n            if (total_O < best_O) {\n                best_O = total_O;\n                best_seq = seq;\n            }\n        }\n    }\n\n    // output\n    string ans;\n    int cur = 0;\n    for (int nxt : best_seq) {\n        int ci = cur / N, cj = cur % N;\n        int ni = nxt / N, nj = nxt % N;\n        if (ni == ci - 1) ans += 'U';\n        else if (ni == ci + 1) ans += 'D';\n        else if (nj == cj - 1) ans += 'L';\n        else if (nj == cj + 1) ans += 'R';\n        else ans += 'U';\n        cur = nxt;\n    }\n    cout << ans << endl;\n    return 0;\n}","ahc028":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <chrono>\n#include <cmath>\n#include <cstdlib>\n#include <limits>\n#include <bitset>\nusing namespace std;\n\nconst int INF = 1e9;\nint N, M;\nint start_i, start_j;\nchar grid[15][15];\nvector<string> t;\nvector<int> pos[26];            // cell indices per letter\nint dist[225][225];             // Manhattan distances between cells\nint start_idx;\n\n// minimum Manhattan distance between any cell of letter a and any of b\nint minDist[26][26];\n// minimum distance from start cell to any cell with letter c\nint minStartDist[26];\n\n// fast random generator\nstruct Xorshift {\n    unsigned int x, y, z, w;\n    Xorshift() {\n        auto seed = chrono::steady_clock::now().time_since_epoch().count();\n        x = seed; y = 362436069; z = 521288629; w = 88675123;\n        for (int i = 0; i < 4; ++i) next();\n    }\n    unsigned int next() {\n        unsigned int t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = w ^ (w >> 19) ^ t ^ (t >> 8);\n    }\n    int nextInt(int n) { return next() % n; }\n    double nextDouble() { return next() * (1.0 / 4294967296.0); }\n};\n\n// exact minimal typing cost for a superstring S (starting from start_idx)\nint compute_DP_cost(const string& S) {\n    if (S.empty()) return 0;\n    int L = S.size();\n    int c0 = S[0] - 'A';\n    const auto& cells0 = pos[c0];\n    vector<int> cur(225, INF);\n    for (int cell : cells0) cur[cell] = 1 + dist[start_idx][cell];\n    for (int k = 1; k < L; ++k) {\n        int pc = S[k-1] - 'A';\n        int nc = S[k] - 'A';\n        const auto& prev_cells = pos[pc];\n        const auto& next_cells = pos[nc];\n        vector<int> nxt(225, INF);\n        for (int j : prev_cells) {\n            int base = cur[j] + 1;\n            if (base >= INF) continue;\n            const int* drow = dist[j];\n            for (int i : next_cells) {\n                int cost = base + drow[i];\n                if (cost < nxt[i]) nxt[i] = cost;\n            }\n        }\n        cur.swap(nxt);\n    }\n    return *min_element(cur.begin(), cur.end());\n}\n\n// lower bound: length + start distance + sum of min letter distances\nint compute_LB(const string& S) {\n    if (S.empty()) return 0;\n    int lb = (int)S.size() + minStartDist[S[0]];\n    for (size_t i = 0; i + 1 < S.size(); ++i) {\n        lb += minDist[S[i]][S[i+1]];\n    }\n    return lb;\n}\n\n// overlap (0..5) between two words\nint word_overlap(const string& a, const string& b) {\n    int lim = min((int)a.size(), (int)b.size());\n    for (int k = lim; k >= 1; --k)\n        if (a.compare(a.size() - k, k, b, 0, k) == 0)\n            return k;\n    return 0;\n}\n\n// append a word to superstring, with possibly random overlap\nvoid append_word(string& S, const string& w, Xorshift& rnd, bool random_overlap) {\n    if (S.empty()) {\n        S = w;\n        return;\n    }\n    int max_ov = word_overlap(S, w);\n    int L = max_ov;\n    if (random_overlap && L > 0 && rnd.nextDouble() < 0.3) {\n        L = rnd.nextInt(L + 1);\n    }\n    S += w.substr(L);\n}\n\n// build lucky string from a permutation, ensuring all words appear\nstring build_S(const vector<int>& perm, Xorshift& rnd, bool random_overlap) {\n    if (perm.empty()) return \"\";\n    vector<bool> used(M, false);\n    string S;\n    S.reserve(5000);\n    for (int w : perm) {\n        if (used[w]) continue;\n        used[w] = true;\n        append_word(S, t[w], rnd, random_overlap);\n    }\n    for (int i = 0; i < M; ++i) {\n        if (!used[i]) {\n            append_word(S, t[i], rnd, false);\n            used[i] = true;\n        }\n    }\n    return S;\n}\n\n// ---- greedy constructions ----\nvoid overlap_greedy(Xorshift& rnd, string& S, vector<int>& perm) {\n    S.clear(); perm.clear();\n    vector<bool> used(M, false);\n    int first = rnd.nextInt(M);\n    used[first] = true;\n    perm.push_back(first);\n    S = t[first];\n    while (perm.size() < M) {\n        int best_ov = -1;\n        vector<int> best;\n        for (int i = 0; i < M; ++i) {\n            if (used[i]) continue;\n            int ov = word_overlap(S, t[i]);\n            if (ov > best_ov) {\n                best_ov = ov;\n                best.clear();\n                best.push_back(i);\n            } else if (ov == best_ov) {\n                best.push_back(i);\n            }\n        }\n        int pick = best[rnd.nextInt(best.size())];\n        used[pick] = true;\n        perm.push_back(pick);\n        append_word(S, t[pick], rnd, false);\n    }\n}\n\nvoid dp_greedy(const vector<int>& init_dp, char init_letter, Xorshift& rnd,\n               string& S_out, vector<int>& perm_out) {\n    vector<int> dp = init_dp;\n    char last_char = init_letter;\n    string S;\n    vector<bool> done(M, false);\n    vector<int> perm;\n    while (true) {\n        for (int i = 0; i < M; ++i)\n            if (!done[i] && S.find(t[i]) != string::npos)\n                done[i] = true;\n        vector<int> cand;\n        for (int i = 0; i < M; ++i) if (!done[i]) cand.push_back(i);\n        if (cand.empty()) break;\n\n        struct Cand { int idx, L, cost; vector<int> ndp; char nl; };\n        vector<Cand> candidates;\n        for (int idx : cand) {\n            const string& w = t[idx];\n            int L = word_overlap(S, w);\n            if (L == 5) { done[idx] = true; continue; }\n            string suffix = w.substr(L);\n            int ci = last_char - 'A';\n            const vector<int>* cur_cells = &pos[ci];\n            vector<int> cur_vals(225, INF);\n            for (int cell : *cur_cells) cur_vals[cell] = dp[cell];\n            for (char ch : suffix) {\n                int nci = ch - 'A';\n                const vector<int>& next_cells = pos[nci];\n                vector<int> nxt(225, INF);\n                for (int j : *cur_cells) {\n                    int base = cur_vals[j] + 1;\n                    if (base >= INF) continue;\n                    const int* drow = dist[j];\n                    for (int i : next_cells) {\n                        int cost = base + drow[i];\n                        if (cost < nxt[i]) nxt[i] = cost;\n                    }\n                }\n                cur_vals = move(nxt);\n                cur_cells = &next_cells;\n            }\n            int cost = INF;\n            for (int cell : *cur_cells) cost = min(cost, cur_vals[cell]);\n            candidates.push_back({idx, L, cost, move(cur_vals), suffix.back()});\n        }\n        if (candidates.empty()) continue;\n        sort(candidates.begin(), candidates.end(),\n             [](const Cand& a, const Cand& b) { return a.cost < b.cost; });\n        int top = min(3, (int)candidates.size());\n        int pick = (rnd.nextDouble() < 0.8) ? 0 : rnd.nextInt(top);\n        Cand& chosen = candidates[pick];\n        S += t[chosen.idx].substr(chosen.L);\n        dp = move(chosen.ndp);\n        last_char = chosen.nl;\n        done[chosen.idx] = true;\n        perm.push_back(chosen.idx);\n    }\n    S_out = S;\n    perm_out = perm;\n}\n\n// ---- final path reconstruction ----\nvoid compute_DP_path(const string& S, vector<int>& path) {\n    int L = S.size();\n    path.resize(L);\n    if (L == 0) return;\n    vector<vector<int>> dp(L, vector<int>(225, INF));\n    vector<vector<int>> prv(L, vector<int>(225, -1));\n    int c0 = S[0] - 'A';\n    for (int cell : pos[c0]) dp[0][cell] = 1 + dist[start_idx][cell];\n    for (int k = 1; k < L; ++k) {\n        int pc = S[k-1] - 'A';\n        int nc = S[k] - 'A';\n        for (int j : pos[pc]) {\n            int base = dp[k-1][j] + 1;\n            if (base >= INF) continue;\n            const int* drow = dist[j];\n            for (int i : pos[nc]) {\n                int cost = base + drow[i];\n                if (cost < dp[k][i]) {\n                    dp[k][i] = cost;\n                    prv[k][i] = j;\n                }\n            }\n        }\n    }\n    int lst = S.back() - 'A';\n    int best = INF, best_cell = -1;\n    for (int cell : pos[lst]) if (dp[L-1][cell] < best) { best = dp[L-1][cell]; best_cell = cell; }\n    for (int k = L-1; k >= 0; --k) {\n        path[k] = best_cell;\n        best_cell = prv[k][best_cell];\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto overall_start = chrono::steady_clock::now();\n    const double time_limit = 1.97;\n\n    // ---- input ----\n    cin >> N >> M;\n    cin >> start_i >> start_j;\n    for (int i = 0; i < N; ++i) {\n        string line; cin >> line;\n        for (int j = 0; j < N; ++j) grid[i][j] = line[j];\n    }\n    t.resize(M);\n    for (int i = 0; i < M; ++i) cin >> t[i];\n\n    // ---- precompute positions ----\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            pos[grid[i][j] - 'A'].push_back(i * N + j);\n    start_idx = start_i * N + start_j;\n\n    // ---- precompute cell distances ----\n    for (int i = 0; i < 225; ++i) {\n        int xi = i / N, yi = i % N;\n        int* drow = dist[i];\n        for (int j = 0; j < 225; ++j) {\n            int xj = j / N, yj = j % N;\n            drow[j] = abs(xi - xj) + abs(yi - yj);\n        }\n    }\n\n    // ---- precompute letter\u2011wise minimum distances ----\n    for (int a = 0; a < 26; ++a) {\n        if (pos[a].empty()) continue;\n        for (int b = 0; b < 26; ++b) {\n            if (pos[b].empty()) { minDist[a][b] = INF; continue; }\n            int best = INF;\n            for (int i : pos[a]) {\n                const int* drow = dist[i];\n                for (int j : pos[b]) {\n                    int d = drow[j];\n                    if (d < best) best = d;\n                }\n            }\n            minDist[a][b] = best;\n        }\n    }\n    for (int c = 0; c < 26; ++c) {\n        if (pos[c].empty()) { minStartDist[c] = INF; continue; }\n        int best = INF;\n        for (int cell : pos[c]) best = min(best, dist[start_idx][cell]);\n        minStartDist[c] = best;\n    }\n\n    // ---- initial DP state ----\n    vector<int> init_dp(225, INF);\n    init_dp[start_idx] = 0;\n    char init_letter = grid[start_i][start_j];\n\n    // ---- random generator ----\n    Xorshift rnd;\n\n    // ---- initial solutions (true DP cost) ----\n    string best_S;\n    int best_true_cost = INF;\n    vector<int> best_perm;\n\n    auto update_best = [&](const string& S, const vector<int>& perm) {\n        int cost = compute_DP_cost(S);\n        if (cost < best_true_cost) {\n            best_true_cost = cost;\n            best_S = S;\n            best_perm = perm;\n        }\n    };\n\n    // Fast overlap greedies (many)\n    for (int i = 0; i < 200; ++i) {\n        string S; vector<int> perm;\n        overlap_greedy(rnd, S, perm);\n        update_best(S, perm);\n    }\n\n    // DP\u2011guided greedies\n    for (int i = 0; i < 40; ++i) {\n        string S; vector<int> perm;\n        dp_greedy(init_dp, init_letter, rnd, S, perm);\n        update_best(S, perm);\n    }\n\n    // ---- Simulated Annealing using lower bound ----\n    vector<int> cur_perm = best_perm;\n    string cur_S = best_S;\n    int cur_LB = compute_LB(cur_S);\n    int best_LB = cur_LB;\n    string best_LB_S = cur_S;\n    vector<int> best_LB_perm = cur_perm;\n\n    // Keep a pool of promising candidates (by LB)\n    vector<pair<int, vector<int>>> lb_candidates; // (LB, perm)\n    lb_candidates.reserve(50);\n    lb_candidates.emplace_back(cur_LB, cur_perm);\n\n    double T0 = 500.0;\n    while (true) {\n        chrono::duration<double> elapsed = chrono::steady_clock::now() - overall_start;\n        if (elapsed.count() >= time_limit) break;\n        double progress = elapsed.count() / time_limit;\n        double T = T0 * exp(-progress * 5.0);\n        if (T < 0.01) T = 0.01;\n\n        for (int batch = 0; batch < 20; ++batch) {\n            vector<int> new_perm = cur_perm;\n            int type = rnd.nextInt(3);\n            if (type == 0) {          // swap two elements\n                int i = rnd.nextInt(M);\n                int j = rnd.nextInt(M);\n                while (i == j) j = rnd.nextInt(M);\n                swap(new_perm[i], new_perm[j]);\n            } else if (type == 1) {   // reverse a segment\n                int l = rnd.nextInt(M);\n                int r = rnd.nextInt(M);\n                if (l > r) swap(l, r);\n                if (l < r) reverse(new_perm.begin() + l, new_perm.begin() + r + 1);\n            } else {                  // move one element\n                int i = rnd.nextInt(M);\n                int j = rnd.nextInt(M);\n                if (i == j) continue;\n                int val = new_perm[i];\n                new_perm.erase(new_perm.begin() + i);\n                new_perm.insert(new_perm.begin() + j, val);\n            }\n            string new_S = build_S(new_perm, rnd, true);\n            int new_LB = compute_LB(new_S);\n            int delta = new_LB - cur_LB;\n            if (delta <= 0 || rnd.nextDouble() < exp(-delta / T)) {\n                cur_perm = new_perm;\n                cur_S = new_S;\n                cur_LB = new_LB;\n                if (cur_LB < best_LB) {\n                    best_LB = cur_LB;\n                    best_LB_S = cur_S;\n                    best_LB_perm = cur_perm;\n                }\n                // insert into pool (keep up to 30 best by LB)\n                if (lb_candidates.size() < 30 || cur_LB < lb_candidates.back().first) {\n                    lb_candidates.emplace_back(cur_LB, cur_perm);\n                    sort(lb_candidates.begin(), lb_candidates.end());\n                    if (lb_candidates.size() > 30) lb_candidates.pop_back();\n                }\n            }\n        }\n    }\n\n    // ---- final evaluation: true DP cost on promising candidates ----\n    // best LB string\n    {\n        int cost = compute_DP_cost(best_LB_S);\n        if (cost < best_true_cost) {\n            best_true_cost = cost;\n            best_S = best_LB_S;\n        }\n    }\n    // other top LB candidates\n    for (auto& p : lb_candidates) {\n        string S = build_S(p.second, rnd, false);\n        int cost = compute_DP_cost(S);\n        if (cost < best_true_cost) {\n            best_true_cost = cost;\n            best_S = S;\n        }\n    }\n\n    // ---- output optimal cell path ----\n    vector<int> path;\n    compute_DP_path(best_S, path);\n    for (int cell : path) {\n        int i = cell / N;\n        int j = cell % N;\n        cout << i << \" \" << j << \"\\n\";\n    }\n\n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <bitset>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\nconstexpr int MAX_N2 = 400;\n\ndouble normal_cdf(double x) {\n    return 0.5 * erfc(-x / sqrt(2.0));\n}\n\nint N, M;\ndouble eps;\nint V_total;\n\nstruct Placement {\n    bitset<MAX_N2> cells;\n    vector<int> q_overlap;     // size = number of queries\n    vector<char> d_contrib;    // size = number of drills (0/1)\n};\n\nvector<Placement> placements;\nvector<vector<int>> field_pl; // field -> list of placement indices\n\nint Q = 0, D = 0;\nvector<bitset<MAX_N2>> query_sets;\nvector<int> query_k;\nvector<int> query_results;\nvector<vector<double>> log_prob; // Q x (V_total+1)\n\nvector<int> drill_cells;\nvector<int> observed;\n\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\ninline int idx(int i, int j) { return i * N + j; }\ninline pair<int,int> unidx(int id) { return {id / N, id % N}; }\n\nvoid read_input() {\n    cin >> N >> M >> eps;\n    field_pl.resize(M);\n    V_total = 0;\n    for (int k = 0; k < M; ++k) {\n        int d; cin >> d;\n        vector<pair<int,int>> shape(d);\n        int max_i = 0, max_j = 0;\n        for (int a = 0; a < d; ++a) {\n            cin >> shape[a].first >> shape[a].second;\n            max_i = max(max_i, shape[a].first);\n            max_j = max(max_j, shape[a].second);\n        }\n        for (int dx = 0; dx <= N - 1 - max_i; ++dx) {\n            for (int dy = 0; dy <= N - 1 - max_j; ++dy) {\n                Placement pl;\n                for (auto &p : shape)\n                    pl.cells.set(idx(dx + p.first, dy + p.second));\n                int pid = placements.size();\n                placements.push_back(pl);\n                field_pl[k].push_back(pid);\n            }\n        }\n        V_total += d;\n        // safety\n        if (field_pl[k].empty()) {\n            Placement pl;\n            int pid = placements.size();\n            placements.push_back(pl);\n            field_pl[k].push_back(pid);\n        }\n    }\n}\n\nvoid send_query(const bitset<MAX_N2> &s) {\n    int k = s.count();\n    cout << \"q \" << k;\n    for (int id = 0; id < N * N; ++id)\n        if (s.test(id)) {\n            auto [r, c] = unidx(id);\n            cout << \" \" << r << \" \" << c;\n        }\n    cout << \"\\n\" << flush;\n}\n\nvoid add_initial_query(const bitset<MAX_N2> &s) {\n    send_query(s);\n    int res; cin >> res;\n    int k = s.count();\n    query_sets.push_back(s);\n    query_k.push_back(k);\n    query_results.push_back(res);\n\n    double sigma = sqrt(k * eps * (1.0 - eps));\n    vector<double> row(V_total + 1);\n    for (int v = 0; v <= V_total; ++v) {\n        double mu = k * eps + v * (1.0 - 2.0 * eps);\n        double prob;\n        if (res == 0) prob = normal_cdf((0.5 - mu) / sigma);\n        else prob = normal_cdf((res + 0.5 - mu) / sigma) - normal_cdf((res - 0.5 - mu) / sigma);\n        if (prob <= 0.0) prob = 1e-300;\n        row[v] = log(prob);\n    }\n    log_prob.push_back(row);\n\n    for (auto &pl : placements)\n        pl.q_overlap.push_back((pl.cells & s).count());\n    ++Q;\n}\n\nvoid drill_cell(int cell_id) {\n    auto [r, c] = unidx(cell_id);\n    cout << \"q 1 \" << r << \" \" << c << \"\\n\" << flush;\n    int val; cin >> val;\n    drill_cells.push_back(cell_id);\n    observed.push_back(val);\n    for (auto &pl : placements)\n        pl.d_contrib.push_back(pl.cells.test(cell_id) ? 1 : 0);\n    ++D;\n}\n\n// --------- SA state ----------\nstruct SAState {\n    vector<int> assign;  // M elements, index in placements\n    vector<int> qover;   // Q elements\n    vector<int> dcnt;    // D elements\n    double energy;\n\n    SAState() : energy(0) {}\n    void calc_energy() {\n        energy = 0;\n        for (int i = 0; i < Q; ++i) {\n            int v = qover[i];\n            if (v < 0) v = 0;\n            if (v > V_total) v = V_total;\n            energy += log_prob[i][v];\n        }\n    }\n};\n\nSAState random_state() {\n    SAState st;\n    st.assign.resize(M);\n    for (int k = 0; k < M; ++k) {\n        int sz = field_pl[k].size();\n        uniform_int_distribution<int> dis(0, sz - 1);\n        st.assign[k] = field_pl[k][dis(rng)];\n    }\n    st.qover.assign(Q, 0);\n    st.dcnt.assign(D, 0);\n    for (int k = 0; k < M; ++k) {\n        int pid = st.assign[k];\n        const auto &pl = placements[pid];\n        for (int i = 0; i < Q; ++i) st.qover[i] += pl.q_overlap[i];\n        for (int d = 0; d < D; ++d) st.dcnt[d] += pl.d_contrib[d];\n    }\n    st.calc_energy();\n    return st;\n}\n\nbool feasible(const SAState &st) {\n    for (int d = 0; d < D; ++d)\n        if (st.dcnt[d] != observed[d]) return false;\n    return true;\n}\n\n// Hard SA (only moves that satisfy drill constraints)\nSAState run_hard_sa(const SAState &init, int steps) {\n    SAState state = init;\n    SAState best = state;\n    uniform_real_distribution<double> real01(0.0, 1.0);\n    uniform_int_distribution<int> field_dis(0, M - 1);\n    const double T_start = 10.0, T_end = 0.01;\n    for (int step = 0; step < steps; ++step) {\n        double T = T_start * pow(T_end / T_start, double(step) / steps);\n        int k = field_dis(rng);\n        int old_pid = state.assign[k];\n        int sz = field_pl[k].size();\n        if (sz <= 1) continue;\n        int idx_new = uniform_int_distribution<int>(0, sz - 1)(rng);\n        int new_pid = field_pl[k][idx_new];\n        if (new_pid == old_pid) continue;\n\n        const auto &old_pl = placements[old_pid];\n        const auto &new_pl = placements[new_pid];\n\n        bool ok = true;\n        for (int d = 0; d < D; ++d) {\n            int nc = state.dcnt[d] - old_pl.d_contrib[d] + new_pl.d_contrib[d];\n            if (nc != observed[d]) { ok = false; break; }\n        }\n        if (!ok) continue;\n\n        double delta = 0;\n        for (int i = 0; i < Q; ++i) {\n            int oldv = state.qover[i];\n            int newv = oldv - old_pl.q_overlap[i] + new_pl.q_overlap[i];\n            if (newv < 0) newv = 0;\n            if (newv > V_total) newv = V_total;\n            if (oldv < 0) oldv = 0;\n            if (oldv > V_total) oldv = V_total;\n            delta += log_prob[i][newv] - log_prob[i][oldv];\n        }\n\n        if (delta >= 0 || real01(rng) < exp(delta / T)) {\n            state.assign[k] = new_pid;\n            for (int i = 0; i < Q; ++i) state.qover[i] += new_pl.q_overlap[i] - old_pl.q_overlap[i];\n            for (int d = 0; d < D; ++d) state.dcnt[d] += new_pl.d_contrib[d] - old_pl.d_contrib[d];\n            state.energy += delta;\n            if (state.energy > best.energy) best = state;\n        }\n    }\n    return best;\n}\n\n// Soft SA with penalty for drill mismatches (helps escape local minima)\nSAState run_soft_sa(const SAState &init, int steps) {\n    SAState state = init;\n    SAState best = state;\n    uniform_real_distribution<double> real01(0.0, 1.0);\n    uniform_int_distribution<int> field_dis(0, M - 1);\n    const double T_start = 10.0, T_end = 0.01;\n    const double penalty_weight = 1e7;\n    for (int step = 0; step < steps; ++step) {\n        double T = T_start * pow(T_end / T_start, double(step) / steps);\n        int k = field_dis(rng);\n        int old_pid = state.assign[k];\n        int sz = field_pl[k].size();\n        if (sz <= 1) continue;\n        int idx_new = uniform_int_distribution<int>(0, sz - 1)(rng);\n        int new_pid = field_pl[k][idx_new];\n        if (new_pid == old_pid) continue;\n\n        const auto &old_pl = placements[old_pid];\n        const auto &new_pl = placements[new_pid];\n\n        double delta = 0;\n        for (int i = 0; i < Q; ++i) {\n            int oldv = state.qover[i];\n            int newv = oldv - old_pl.q_overlap[i] + new_pl.q_overlap[i];\n            if (newv < 0) newv = 0;\n            if (newv > V_total) newv = V_total;\n            if (oldv < 0) oldv = 0;\n            if (oldv > V_total) oldv = V_total;\n            delta += log_prob[i][newv] - log_prob[i][oldv];\n        }\n        double old_pen = 0, new_pen = 0;\n        for (int d = 0; d < D; ++d) {\n            int oldc = state.dcnt[d];\n            int newc = oldc - old_pl.d_contrib[d] + new_pl.d_contrib[d];\n            old_pen -= penalty_weight * (oldc - observed[d]) * (oldc - observed[d]);\n            new_pen -= penalty_weight * (newc - observed[d]) * (newc - observed[d]);\n        }\n        delta += new_pen - old_pen;\n\n        if (delta >= 0 || real01(rng) < exp(delta / T)) {\n            state.assign[k] = new_pid;\n            for (int i = 0; i < Q; ++i) state.qover[i] += new_pl.q_overlap[i] - old_pl.q_overlap[i];\n            for (int d = 0; d < D; ++d) state.dcnt[d] += new_pl.d_contrib[d] - old_pl.d_contrib[d];\n            state.energy += delta;\n            if (state.energy > best.energy) best = state;\n        }\n    }\n    return best;\n}\n\nbitset<MAX_N2> get_mask(const SAState &st) {\n    bitset<MAX_N2> mask;\n    for (int k = 0; k < M; ++k)\n        mask |= placements[st.assign[k]].cells;\n    return mask;\n}\n\nbool guess(const bitset<MAX_N2> &mask) {\n    vector<pair<int,int>> cells;\n    for (int id = 0; id < N * N; ++id)\n        if (mask.test(id))\n            cells.emplace_back(unidx(id));\n    cout << \"a \" << cells.size();\n    for (auto &p : cells) cout << \" \" << p.first << \" \" << p.second;\n    cout << \"\\n\" << flush;\n    int ret; cin >> ret;\n    return ret == 1;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cout << fixed << setprecision(10);\n\n    read_input();\n    int max_ops = 2 * N * N;\n    int ops_used = 0;\n    auto start_time = chrono::steady_clock::now();\n    auto time_left = [&]() { return 2.6 - chrono::duration<double>(chrono::steady_clock::now() - start_time).count(); };\n\n    // ----- Phase 1: initial queries -----\n    int num_init_q = min(80, max_ops - 20);\n    if (num_init_q < 0) num_init_q = 0;\n    vector<int> indices(N * N);\n    iota(indices.begin(), indices.end(), 0);\n    uniform_int_distribution small_k(10, min(30, N * N));\n    uniform_int_distribution large_k(max(2, N * N / 2), N * N);\n    int small_q = num_init_q / 5;\n    for (int i = 0; i < num_init_q && ops_used < max_ops - 5 && time_left() > 0.3; ++i) {\n        int k = (i < small_q) ? max(2, small_k(rng)) : max(2, large_k(rng));\n        shuffle(indices.begin(), indices.end(), rng);\n        bitset<MAX_N2> s;\n        for (int t = 0; t < k; ++t) s.set(indices[t]);\n        add_initial_query(s);\n        ++ops_used;\n    }\n\n    // ----- Phase 2: initial pool -----\n    vector<SAState> pool;\n    const int POOL_SIZE = 8;\n    while ((int)pool.size() < POOL_SIZE && time_left() > 0.5) {\n        SAState st = random_state();\n        st = run_soft_sa(st, 3000);\n        st = run_hard_sa(st, 2000);\n        if (feasible(st)) pool.push_back(st);\n    }\n    if (pool.empty()) {\n        SAState st = random_state();\n        st = run_soft_sa(st, 6000);\n        st = run_hard_sa(st, 4000);\n        if (feasible(st)) pool.push_back(st);\n    }\n\n    bool guessed_correctly = false;\n\n    // ----- Phase 3: iterative drill most uncertain cells -----\n    while (ops_used < max_ops - 3 && !pool.empty() && time_left() > 0.2) {\n        // remove infeasible\n        pool.erase(remove_if(pool.begin(), pool.end(), [](const SAState &st) { return !feasible(st); }), pool.end());\n        if (pool.empty()) break;\n\n        // check consensus\n        bitset<MAX_N2> mask0 = get_mask(pool[0]);\n        bool consensus = true;\n        for (size_t i = 1; i < pool.size(); ++i) {\n            if (get_mask(pool[i]) != mask0) { consensus = false; break; }\n        }\n        if (consensus) {\n            guessed_correctly = guess(mask0);\n            ++ops_used;\n            break;\n        }\n\n        // find most uncertain undrilled cell\n        vector<int> cov(N * N, 0);\n        for (auto &st : pool) {\n            bitset<MAX_N2> m = get_mask(st);\n            for (int id = 0; id < N * N; ++id) if (m.test(id)) cov[id]++;\n        }\n        double best_entropy = -1.0;\n        int best_cell = -1;\n        for (int id = 0; id < N * N; ++id) {\n            if (find(drill_cells.begin(), drill_cells.end(), id) != drill_cells.end()) continue;\n            double frac = (double)cov[id] / pool.size();\n            if (frac <= 0.0 || frac >= 1.0) continue;\n            double entropy = -frac * log(frac) - (1.0 - frac) * log(1.0 - frac);\n            if (entropy > best_entropy) {\n                best_entropy = entropy;\n                best_cell = id;\n            }\n        }\n        if (best_cell == -1) {\n            // all cells certain but masks differ? guess the highest energy mask\n            sort(pool.begin(), pool.end(), [](const SAState &a, const SAState &b) { return a.energy > b.energy; });\n            guessed_correctly = guess(get_mask(pool[0]));\n            ++ops_used;\n            break;\n        }\n\n        drill_cell(best_cell);\n        ++ops_used;\n\n        // update pool states with new drill\n        for (auto &st : pool) {\n            int cnt = 0;\n            for (int k = 0; k < M; ++k)\n                cnt += placements[st.assign[k]].d_contrib.back();\n            st.dcnt.push_back(cnt);\n        }\n        pool.erase(remove_if(pool.begin(), pool.end(), [](const SAState &st) { return !feasible(st); }), pool.end());\n\n        // replenish if needed\n        while ((int)pool.size() < POOL_SIZE && time_left() > 0.3) {\n            SAState st = random_state();\n            st = run_soft_sa(st, 2000);\n            st = run_hard_sa(st, 1500);\n            if (feasible(st)) pool.push_back(st);\n        }\n        // short refinement\n        for (auto &st : pool) st = run_hard_sa(st, 400);\n    }\n\n    // ----- Phase 4: fallback drill all missing cells -----\n    if (!guessed_correctly) {\n        vector<pair<int,int>> positive;\n        for (int d = 0; d < D; ++d)\n            if (observed[d] > 0) positive.emplace_back(unidx(drill_cells[d]));\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                int id = idx(r, c);\n                if (find(drill_cells.begin(), drill_cells.end(), id) != drill_cells.end()) continue;\n                if (ops_used >= max_ops - 1) break;\n                drill_cell(id);\n                ++ops_used;\n                if (observed.back() > 0) positive.emplace_back(r, c);\n            }\n        }\n        cout << \"a \" << positive.size();\n        for (auto &p : positive) cout << \" \" << p.first << \" \" << p.second;\n        cout << \"\\n\" << flush;\n        int _; cin >> _;\n    }\n\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int i0, j0, i1, j1;\n    int area() const { return (i1 - i0) * (j1 - j0); }\n};\n\nint W, D, N;\nconst int HORIZ_COUNT = (1000 - 1) * 1000;   // (W-1)*W = 999*1000\nconst int VERT_COUNT = 1000 * (1000 - 1);    // W*(W-1) = 1000*999\nconst int SEG = HORIZ_COUNT + VERT_COUNT;    // 1998000\n\nunsigned rng_state = 123456789;\nunsigned xorshift() {\n    rng_state ^= rng_state << 13;\n    rng_state ^= rng_state >> 17;\n    rng_state ^= rng_state << 5;\n    return rng_state;\n}\ninline double rnd_double() { return (xorshift() & 0xFFFFFFFF) / 4294967296.0; }\ninline int rnd_int(int n) { return xorshift() % n; }\n\nvector<vector<int>> a;\nvector<vector<Rect>> rects;\nvector<uint8_t> cnt;         // D * SEG, wall segment counts\nvector<int> pen_day;         // area penalty per day\nint total_area_penalty = 0;\nint total_L_sum = 0;\n\n// best found solution\nvector<vector<Rect>> best_rects;\nint best_cost = INT_MAX;\n\nvoid fill_boundaries(const Rect& r, vector<int>& out) {\n    out.clear();\n    if (r.i0 >= 1 && r.i0 <= W - 1) {\n        int base = (r.i0 - 1) * W + r.j0;\n        for (int j = 0; j < r.j1 - r.j0; ++j) out.push_back(base + j);\n    }\n    if (r.i1 >= 1 && r.i1 <= W - 1) {\n        int base = (r.i1 - 1) * W + r.j0;\n        for (int j = 0; j < r.j1 - r.j0; ++j) out.push_back(base + j);\n    }\n    if (r.j0 >= 1 && r.j0 <= W - 1) {\n        int base = HORIZ_COUNT + (r.j0 - 1) * W + r.i0;\n        for (int i = 0; i < r.i1 - r.i0; ++i) out.push_back(base + i);\n    }\n    if (r.j1 >= 1 && r.j1 <= W - 1) {\n        int base = HORIZ_COUNT + (r.j1 - 1) * W + r.i0;\n        for (int i = 0; i < r.i1 - r.i0; ++i) out.push_back(base + i);\n    }\n}\n\ninline int update_L_delta(int d, int seg, bool old_st, bool new_st) {\n    int delta = 0;\n    if (d > 0) {\n        bool prev = cnt[(d - 1) * SEG + seg] > 0;\n        delta += (prev ^ new_st) - (prev ^ old_st);\n    }\n    if (d + 1 < D) {\n        bool next = cnt[(d + 1) * SEG + seg] > 0;\n        delta += (next ^ new_st) - (next ^ old_st);\n    }\n    return delta;\n}\n\nvector<Rect> pack_exact(const vector<int>& targets) {\n    struct FreeRect { int i0, j0, i1, j1; };\n    vector<FreeRect> free;\n    free.push_back({0, 0, W, W});\n    vector<Rect> res(N);\n\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int x, int y) { return targets[x] > targets[y]; });\n\n    for (int idx : order) {\n        long long req = targets[idx];\n        int best = -1;\n        long long best_area = 0;\n        for (int i = 0; i < (int)free.size(); ++i) {\n            long long a = 1LL * (free[i].i1 - free[i].i0) * (free[i].j1 - free[i].j0);\n            if (a >= req) {\n                if (best == -1 || a < best_area) {\n                    best = i; best_area = a;\n                }\n            }\n        }\n        if (best == -1) {\n            long long max_a = -1;\n            for (int i = 0; i < (int)free.size(); ++i) {\n                long long a = 1LL * (free[i].i1 - free[i].i0) * (free[i].j1 - free[i].j0);\n                if (a > max_a) { max_a = a; best = i; }\n            }\n        }\n        FreeRect fr = free[best];\n        swap(free[best], free.back());\n        free.pop_back();\n\n        int avW = fr.j1 - fr.j0;\n        int avH = fr.i1 - fr.i0;\n        int w = min(avW, max(1, (int)ceil(sqrt(req))));\n        int h = max(1, (int)((req + w - 1) / w));\n        if (h > avH) {\n            h = avH;\n            w = max(1, (int)((req + h - 1) / h));\n            if (w > avW) w = avW;\n        }\n        w = max(1, min(w, avW));\n        h = max(1, min(h, avH));\n        res[idx] = {fr.i0, fr.j0, fr.i0 + h, fr.j0 + w};\n        if (w < avW) free.push_back({fr.i0, fr.j0 + w, fr.i0 + h, fr.j1});\n        if (h < avH) free.push_back({fr.i0 + h, fr.j0, fr.i1, fr.j1});\n    }\n    return res;\n}\n\nint compute_L_between(int d) {\n    int L = 0;\n    int off0 = (d - 1) * SEG, off1 = d * SEG;\n    for (int s = 0; s < SEG; ++s) {\n        bool p = cnt[off0 + s] > 0;\n        bool c = cnt[off1 + s] > 0;\n        L += (p != c);\n    }\n    return L;\n}\n\nvoid build_from_greedy() {\n    // greedy per\u2011day decision (same as previous accepted solution)\n    rects.resize(D, vector<Rect>(N));\n    rects[0] = pack_exact(a[0]);\n\n    vector<uint64_t> prev_bits((SEG + 63) / 64, 0);\n    auto set_bit = [&](int seg) {\n        prev_bits[seg >> 6] |= (1ULL << (seg & 63));\n    };\n    auto get_wall_bits = [&](const vector<Rect>& r, vector<uint64_t>& bits) {\n        fill(bits.begin(), bits.end(), 0ULL);\n        vector<int> tmp; tmp.reserve(4000);\n        for (const auto& rect : r) {\n            fill_boundaries(rect, tmp);\n            for (int s : tmp) bits[s >> 6] |= (1ULL << (s & 63));\n        }\n    };\n    get_wall_bits(rects[0], prev_bits);\n\n    vector<int> prev_areas(N);\n    for (int k = 0; k < N; ++k) prev_areas[k] = rects[0][k].area();\n    total_area_penalty = 0;\n    auto area_penalty_vec = [&](const vector<int>& areas, const vector<int>& dem) {\n        int pen = 0;\n        for (int k = 0; k < N; ++k)\n            if (areas[k] < dem[k]) pen += 100 * (dem[k] - areas[k]);\n        return pen;\n    };\n    total_area_penalty = area_penalty_vec(prev_areas, a[0]);\n    total_L_sum = 0;\n\n    for (int d = 1; d < D; ++d) {\n        auto cand = pack_exact(a[d]);\n        vector<uint64_t> cand_bits((SEG + 63) / 64, 0);\n        get_wall_bits(cand, cand_bits);\n        vector<int> cand_areas(N);\n        for (int k = 0; k < N; ++k) cand_areas[k] = cand[k].area();\n        int pen_keep   = area_penalty_vec(prev_areas, a[d]);\n        int pen_switch = area_penalty_vec(cand_areas, a[d]);\n        int L = 0;\n        for (int i = 0; i < (int)prev_bits.size(); ++i)\n            L += __builtin_popcountll(prev_bits[i] ^ cand_bits[i]);\n\n        if (pen_switch + L < pen_keep) {\n            total_area_penalty += pen_switch;\n            total_L_sum += L;\n            rects[d] = move(cand);\n            prev_bits.swap(cand_bits);\n            prev_areas.swap(cand_areas);\n        } else {\n            total_area_penalty += pen_keep;\n            rects[d] = rects[d - 1];\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false); cin.tie(nullptr);\n    cin >> W >> D >> N;\n    a.resize(D, vector<int>(N));\n    for (int d = 0; d < D; ++d)\n        for (int k = 0; k < N; ++k)\n            cin >> a[d][k];\n\n    // 1) initial greedy solution (day\u2011by\u2011day greedy switch)\n    build_from_greedy();\n\n    // 2) build count array and exact cost\n    cnt.assign(D * SEG, uint8_t(0));\n    vector<int> seg_buf; seg_buf.reserve(4000);\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            fill_boundaries(rects[d][k], seg_buf);\n            int base = d * SEG;\n            for (int s : seg_buf) cnt[base + s]++;\n        }\n    }\n\n    pen_day.resize(D, 0);\n    total_area_penalty = 0;\n    for (int d = 0; d < D; ++d) {\n        int pen = 0;\n        for (int k = 0; k < N; ++k) {\n            int ar = rects[d][k].area();\n            if (ar < a[d][k]) pen += 100 * (a[d][k] - ar);\n        }\n        pen_day[d] = pen;\n        total_area_penalty += pen;\n    }\n\n    total_L_sum = 0;\n    for (int d = 1; d < D; ++d) {\n        total_L_sum += compute_L_between(d);\n    }\n\n    best_cost = total_area_penalty + total_L_sum;\n    best_rects = rects;\n\n    // 3) simulated annealing\n    vector<int> old_segs, new_segs;\n    old_segs.reserve(4000); new_segs.reserve(4000);\n\n    auto start = chrono::steady_clock::now();\n    const double TL = 2.9;\n    while (true) {\n        double elap = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n        if (elap > TL) break;\n        double T = 500.0 * (1.0 - elap / TL);\n        if (T < 0.1) T = 0.1;\n\n        for (int iter = 0; iter < 100; ++iter) {\n            int d = rnd_int(D);\n            int k = rnd_int(N);\n            Rect old_rect = rects[d][k];\n            Rect new_rect;\n\n            int move_type = rnd_int(3);\n            if (move_type == 0) {           // shift\n                int dx = rnd_int(5) - 2;\n                int dy = rnd_int(5) - 2;\n                if (dx == 0 && dy == 0) continue;\n                new_rect = {old_rect.i0 + dx, old_rect.j0 + dy,\n                            old_rect.i1 + dx, old_rect.j1 + dy};\n            } else if (move_type == 1) {    // resize\n                int side = rnd_int(4);\n                int delta = rnd_int(9) - 4;\n                if (delta == 0) continue;\n                new_rect = old_rect;\n                if (side == 0) new_rect.i0 += delta;\n                else if (side == 1) new_rect.i1 += delta;\n                else if (side == 2) new_rect.j0 += delta;\n                else new_rect.j1 += delta;\n            } else {                        // copy from neighbour day\n                int adj = d + (rnd_int(2) ? -1 : 1);\n                if (adj < 0 || adj >= D) continue;\n                new_rect = rects[adj][k];\n            }\n\n            if (new_rect.i0 < 0 || new_rect.j0 < 0 || new_rect.i1 > W || new_rect.j1 > W) continue;\n            if (new_rect.i0 >= new_rect.i1 || new_rect.j0 >= new_rect.j1) continue;\n            bool conflict = false;\n            for (int k2 = 0; k2 < N; ++k2) {\n                if (k2 == k) continue;\n                const Rect& o = rects[d][k2];\n                if (new_rect.i0 < o.i1 && o.i0 < new_rect.i1 &&\n                    new_rect.j0 < o.j1 && o.j0 < new_rect.j1) {\n                    conflict = true; break;\n                }\n            }\n            if (conflict) continue;\n\n            int old_ar = old_rect.area(), new_ar = new_rect.area();\n            int old_short = max(0, a[d][k] - old_ar);\n            int new_short = max(0, a[d][k] - new_ar);\n            int delta_area = 100 * (new_short - old_short);\n\n            fill_boundaries(old_rect, old_segs);\n            fill_boundaries(new_rect, new_segs);\n            int delta_L = 0;\n            int d_base = d * SEG;\n\n            // tentatively apply changes\n            for (int s : old_segs) {\n                uint8_t& c = cnt[d_base + s];\n                bool old_st = (c > 0);\n                c--;\n                bool new_st = (c > 0);\n                if (old_st != new_st) delta_L += update_L_delta(d, s, old_st, new_st);\n            }\n            for (int s : new_segs) {\n                uint8_t& c = cnt[d_base + s];\n                bool old_st = (c > 0);\n                c++;\n                bool new_st = (c > 0);\n                if (old_st != new_st) delta_L += update_L_delta(d, s, old_st, new_st);\n            }\n\n            int delta_cost = delta_area + delta_L;\n            if (delta_cost <= 0 || rnd_double() < exp(-delta_cost / T)) {\n                rects[d][k] = new_rect;\n                total_area_penalty += delta_area;\n                total_L_sum += delta_L;\n                pen_day[d] += delta_area;\n            } else {\n                // revert\n                for (int s : old_segs) cnt[d_base + s]++;\n                for (int s : new_segs) cnt[d_base + s]--;\n            }\n\n            int cur_cost = total_area_penalty + total_L_sum;\n            if (cur_cost < best_cost) {\n                best_cost = cur_cost;\n                best_rects = rects;\n            }\n        }\n    }\n\n    // output best found solution\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            const Rect& r = best_rects[d][k];\n            cout << r.i0 << ' ' << r.j0 << ' ' << r.i1 << ' ' << r.j1 << '\\n';\n        }\n    }\n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <chrono>\n#include <random>\n#include <cmath>\n#include <cstring>\n#include <algorithm>\n#include <array>\n\nusing namespace std;\nusing ll = long long;\nusing ull = unsigned long long;\n\nconst int MOD = 998244353;\nconst int N = 9;\nconst int K = 81;\nconst int M = 20;\n\nstruct Move {\n    int cells[9];\n    int vals[9];\n    int m, p, q;\n};\n\n// Fast XorShift RNG\nstruct XorShift {\n    ull s;\n    XorShift(ull seed = 12345678ULL) : s(seed) {}\n    ull next() {\n        s ^= s << 13;\n        s ^= s >> 7;\n        s ^= s << 17;\n        return s;\n    }\n    int next_int(int mod) { return next() % mod; }\n    double next_double() { return (next() >> 11) * (1.0 / (1ULL << 53)); }\n};\n\n// Board operations (inlined)\ninline void apply_add(const Move& mv, int* b, ll& sc) {\n    for (int i = 0; i < 9; ++i) {\n        int c = mv.cells[i];\n        int v = mv.vals[i];\n        int old = b[c];\n        int nv = old + v;\n        if (nv >= MOD) nv -= MOD;\n        b[c] = nv;\n        sc += nv - old;\n    }\n}\ninline ll eval_add(const Move& mv, const int* b) {\n    ll d = 0;\n    for (int i = 0; i < 9; ++i) {\n        int c = mv.cells[i];\n        int v = mv.vals[i];\n        int old = b[c];\n        int nv = old + v;\n        if (nv >= MOD) nv -= MOD;\n        d += nv - old;\n    }\n    return d;\n}\ninline void apply_remove(const Move& mv, int* b, ll& sc) {\n    for (int i = 0; i < 9; ++i) {\n        int c = mv.cells[i];\n        int v = mv.vals[i];\n        int old = b[c];\n        int nv = old - v;\n        if (nv < 0) nv += MOD;\n        b[c] = nv;\n        sc += nv - old;\n    }\n}\ninline ll eval_remove(const Move& mv, const int* b) {\n    ll d = 0;\n    for (int i = 0; i < 9; ++i) {\n        int c = mv.cells[i];\n        int v = mv.vals[i];\n        int old = b[c];\n        int nv = old - v;\n        if (nv < 0) nv += MOD;\n        d += nv - old;\n    }\n    return d;\n}\n\n// Deterministic hill climbing\nvoid hill_climb(vector<int>& cur, int* board, ll& score, const vector<Move>& moves, int total_moves) {\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        int L = cur.size();\n        if (L < K) {\n            int best = -1;\n            ll best_delta = 0;\n            for (int mid = 0; mid < total_moves; ++mid) {\n                ll d = eval_add(moves[mid], board);\n                if (d > best_delta) { best_delta = d; best = mid; }\n            }\n            if (best_delta > 0) {\n                apply_add(moves[best], board, score);\n                cur.push_back(best);\n                improved = true;\n                continue;\n            }\n        }\n        if (L > 0) {\n            int best_i = -1;\n            ll best_delta = 0;\n            for (int i = 0; i < L; ++i) {\n                ll d = eval_remove(moves[cur[i]], board);\n                if (d > best_delta) { best_delta = d; best_i = i; }\n            }\n            if (best_delta > 0) {\n                apply_remove(moves[cur[best_i]], board, score);\n                cur[best_i] = cur.back();\n                cur.pop_back();\n                improved = true;\n                continue;\n            }\n        }\n        if (L > 0) {\n            bool found = false;\n            for (int i = 0; i < L && !found; ++i) {\n                int old_id = cur[i];\n                ll score_before = score;\n                apply_remove(moves[old_id], board, score);\n                int best_new = -1;\n                ll best_total = 0;\n                for (int nm = 0; nm < total_moves; ++nm) {\n                    ll delta_add = eval_add(moves[nm], board);\n                    ll total_delta = (score - score_before) + delta_add;\n                    if (total_delta > best_total) { best_total = total_delta; best_new = nm; }\n                }\n                if (best_total > 0) {\n                    apply_add(moves[best_new], board, score);\n                    cur[i] = best_new;\n                    improved = true;\n                    found = true;\n                } else {\n                    apply_add(moves[old_id], board, score);\n                }\n            }\n            if (found) continue;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // input\n    int N_in, M_in, K_in;\n    cin >> N_in >> M_in >> K_in;\n    (void)N_in; (void)M_in; (void)K_in;\n\n    int init_board[N * N];\n    ll init_sum = 0;\n    for (int i = 0; i < N * N; ++i) {\n        cin >> init_board[i];\n        init_sum += init_board[i];\n    }\n\n    int stamps[M][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                cin >> stamps[m][i][j];\n\n    // precompute moves\n    const int rows = N - 2;\n    const int cols = N - 2;\n    const int total_moves = M * rows * cols;  // 980\n    vector<Move> moves(total_moves);\n    for (int m = 0; m < M; ++m) {\n        for (int p = 0; p < rows; ++p) {\n            for (int q = 0; q < cols; ++q) {\n                int idx = m * rows * cols + p * cols + q;\n                moves[idx].m = m;\n                moves[idx].p = p;\n                moves[idx].q = q;\n                int ci = 0;\n                for (int i = 0; i < 3; ++i)\n                    for (int j = 0; j < 3; ++j) {\n                        moves[idx].cells[ci] = (p + i) * N + (q + j);\n                        moves[idx].vals[ci] = stamps[m][i][j];\n                        ++ci;\n                    }\n            }\n        }\n    }\n\n    // timing\n    auto global_start = chrono::steady_clock::now();\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - global_start).count();\n    };\n    const double time_limit = 1.95;\n\n    random_device rd;\n    ull base_seed = (((ull)rd() << 32) | rd());\n    XorShift rng(base_seed);\n\n    vector<int> global_best_applied;\n    ll global_best_score = 0;\n\n    // Beam search episodes\n    int beam_width = 50;\n    double beam_time_limit = 1.4;  // reserve rest for SA\n\n    struct BeamState {\n        array<int, N*N> rem;\n        ll score;\n        vector<int> moves;\n    };\n\n    vector<int> move_order(total_moves);\n    for (int i = 0; i < total_moves; ++i) move_order[i] = i;\n\n    while (elapsed() < beam_time_limit) {\n        // shuffle move order to diversify\n        shuffle(move_order.begin(), move_order.end(), mt19937(rng.next()));\n\n        vector<BeamState> beam;\n        beam.reserve(beam_width * total_moves);\n        {\n            BeamState init;\n            for (int i = 0; i < N*N; ++i) init.rem[i] = init_board[i];\n            init.score = init_sum;\n            beam.push_back(init);\n        }\n\n        bool truncated = false;\n        for (int step = 0; step < K; ++step) {\n            if (elapsed() > beam_time_limit) {\n                truncated = true;\n                break;\n            }\n            vector<BeamState> next_states;\n            next_states.reserve(beam.size() * total_moves);\n\n            for (const auto& st : beam) {\n                for (int mid : move_order) {\n                    const Move& mv = moves[mid];\n                    ll delta = 0;\n                    for (int i = 0; i < 9; ++i) {\n                        int c = mv.cells[i];\n                        int v = mv.vals[i];\n                        int old = st.rem[c];\n                        int nv = old + v;\n                        if (nv >= MOD) nv -= MOD;\n                        delta += nv - old;\n                    }\n                    ll new_score = st.score + delta;\n                    BeamState ns;\n                    ns.rem = st.rem;\n                    for (int i = 0; i < 9; ++i) {\n                        int c = mv.cells[i];\n                        int v = mv.vals[i];\n                        int old = ns.rem[c];\n                        int nv = old + v;\n                        if (nv >= MOD) nv -= MOD;\n                        ns.rem[c] = nv;\n                    }\n                    ns.score = new_score;\n                    ns.moves = st.moves;\n                    ns.moves.push_back(mid);\n                    next_states.push_back(move(ns));\n                }\n            }\n\n            if (next_states.empty()) break;\n\n            if (next_states.size() > (size_t)beam_width) {\n                nth_element(next_states.begin(), next_states.begin() + beam_width, next_states.end(),\n                    [](const BeamState& a, const BeamState& b) { return a.score > b.score; });\n                next_states.resize(beam_width);\n            }\n            beam = move(next_states);\n        }\n\n        if (truncated || beam.empty()) continue;\n\n        // take best state from beam\n        auto& best_st = beam[0];\n        int board[N*N];\n        for (int i = 0; i < N*N; ++i) board[i] = best_st.rem[i];\n        ll score = best_st.score;\n        vector<int> applied = best_st.moves;\n\n        // hill climb\n        hill_climb(applied, board, score, moves, total_moves);\n\n        if (score > global_best_score) {\n            global_best_score = score;\n            global_best_applied = applied;\n        }\n    }\n\n    // SA polish on global best\n    if (!global_best_applied.empty() && elapsed() < time_limit - 0.05) {\n        int board[N*N];\n        memcpy(board, init_board, sizeof(board));\n        ll score = init_sum;\n        vector<int> cur = global_best_applied;\n        for (int mid : cur) apply_add(moves[mid], board, score);\n\n        auto sa_start = chrono::steady_clock::now();\n        double remain = time_limit - elapsed();\n        double sa_budget = min(0.6, remain - 0.05);\n        if (sa_budget > 0.01) {\n            double T_start = 1e6;\n            double T_end = 0.01;\n            double log_ratio = log(T_end / T_start);\n\n            while (chrono::duration<double>(chrono::steady_clock::now() - sa_start).count() < sa_budget) {\n                double progress = chrono::duration<double>(chrono::steady_clock::now() - sa_start).count() / sa_budget;\n                double T = T_start * exp(progress * log_ratio);\n                if (T < T_end) T = T_end;\n\n                int L = cur.size();\n                double rd_val = rng.next_double();\n\n                if (L == 0) {\n                    int nm = rng.next_int(total_moves);\n                    ll delta = eval_add(moves[nm], board);\n                    if (delta >= 0 || rng.next_double() < exp(delta / T)) {\n                        apply_add(moves[nm], board, score);\n                        cur.push_back(nm);\n                    }\n                } else if (L == K) {\n                    if (rd_val < 0.55) {\n                        int idx = rng.next_int(L);\n                        int old = cur[idx];\n                        ll score_before = score;\n                        apply_remove(moves[old], board, score);\n                        int nm = rng.next_int(total_moves);\n                        ll delta_add = eval_add(moves[nm], board);\n                        ll total_delta = (score - score_before) + delta_add;\n                        if (total_delta >= 0 || rng.next_double() < exp(total_delta / T)) {\n                            apply_add(moves[nm], board, score);\n                            cur[idx] = nm;\n                        } else {\n                            apply_add(moves[old], board, score);\n                        }\n                    } else if (rd_val < 0.80) {\n                        int idx = rng.next_int(L);\n                        int old = cur[idx];\n                        ll delta = eval_remove(moves[old], board);\n                        if (delta >= 0 || rng.next_double() < exp(delta / T)) {\n                            apply_remove(moves[old], board, score);\n                            cur[idx] = cur.back();\n                            cur.pop_back();\n                        }\n                    } else {\n                        int idx = rng.next_int(L);\n                        int old_id = cur[idx];\n                        const Move& old_mv = moves[old_id];\n                        int new_id;\n                        if (rng.next_int(2) == 0) {\n                            int nm = rng.next_int(M);\n                            if (nm == old_mv.m) nm = (nm + 1) % M;\n                            new_id = nm * rows * cols + old_mv.p * cols + old_mv.q;\n                        } else {\n                            int np = old_mv.p, nq = old_mv.q;\n                            np = max(0, min(rows - 1, np + rng.next_int(3) - 1));\n                            nq = max(0, min(cols - 1, nq + rng.next_int(3) - 1));\n                            if (np == old_mv.p && nq == old_mv.q) {\n                                int nm = rng.next_int(M);\n                                if (nm == old_mv.m) nm = (nm + 1) % M;\n                                new_id = nm * rows * cols + old_mv.p * cols + old_mv.q;\n                            } else {\n                                new_id = old_mv.m * rows * cols + np * cols + nq;\n                            }\n                        }\n                        ll score_before = score;\n                        apply_remove(moves[old_id], board, score);\n                        ll delta_add = eval_add(moves[new_id], board);\n                        ll total_delta = (score - score_before) + delta_add;\n                        if (total_delta >= 0 || rng.next_double() < exp(total_delta / T)) {\n                            apply_add(moves[new_id], board, score);\n                            cur[idx] = new_id;\n                        } else {\n                            apply_add(moves[old_id], board, score);\n                        }\n                    }\n                } else {\n                    if (rd_val < 0.25) {\n                        int nm = rng.next_int(total_moves);\n                        ll delta = eval_add(moves[nm], board);\n                        if (delta >= 0 || rng.next_double() < exp(delta / T)) {\n                            apply_add(moves[nm], board, score);\n                            cur.push_back(nm);\n                        }\n                    } else if (rd_val < 0.45) {\n                        int idx = rng.next_int(L);\n                        int old = cur[idx];\n                        ll delta = eval_remove(moves[old], board);\n                        if (delta >= 0 || rng.next_double() < exp(delta / T)) {\n                            apply_remove(moves[old], board, score);\n                            cur[idx] = cur.back();\n                            cur.pop_back();\n                        }\n                    } else if (rd_val < 0.75) {\n                        int idx = rng.next_int(L);\n                        int old = cur[idx];\n                        ll score_before = score;\n                        apply_remove(moves[old], board, score);\n                        int nm = rng.next_int(total_moves);\n                        ll delta_add = eval_add(moves[nm], board);\n                        ll total_delta = (score - score_before) + delta_add;\n                        if (total_delta >= 0 || rng.next_double() < exp(total_delta / T)) {\n                            apply_add(moves[nm], board, score);\n                            cur[idx] = nm;\n                        } else {\n                            apply_add(moves[old], board, score);\n                        }\n                    } else {\n                        int idx = rng.next_int(L);\n                        int old_id = cur[idx];\n                        const Move& old_mv = moves[old_id];\n                        int new_id;\n                        if (rng.next_int(2) == 0) {\n                            int nm = rng.next_int(M);\n                            if (nm == old_mv.m) nm = (nm + 1) % M;\n                            new_id = nm * rows * cols + old_mv.p * cols + old_mv.q;\n                        } else {\n                            int np = old_mv.p, nq = old_mv.q;\n                            np = max(0, min(rows - 1, np + rng.next_int(3) - 1));\n                            nq = max(0, min(cols - 1, nq + rng.next_int(3) - 1));\n                            if (np == old_mv.p && nq == old_mv.q) {\n                                int nm = rng.next_int(M);\n                                if (nm == old_mv.m) nm = (nm + 1) % M;\n                                new_id = nm * rows * cols + old_mv.p * cols + old_mv.q;\n                            } else {\n                                new_id = old_mv.m * rows * cols + np * cols + nq;\n                            }\n                        }\n                        ll score_before = score;\n                        apply_remove(moves[old_id], board, score);\n                        ll delta_add = eval_add(moves[new_id], board);\n                        ll total_delta = (score - score_before) + delta_add;\n                        if (total_delta >= 0 || rng.next_double() < exp(total_delta / T)) {\n                            apply_add(moves[new_id], board, score);\n                            cur[idx] = new_id;\n                        } else {\n                            apply_add(moves[old_id], board, score);\n                        }\n                    }\n                }\n\n                if (score > global_best_score) {\n                    global_best_score = score;\n                    global_best_applied = cur;\n                }\n            }\n        }\n    }\n\n    // final hill climb\n    if (!global_best_applied.empty()) {\n        int board[N*N];\n        memcpy(board, init_board, sizeof(board));\n        ll score = init_sum;\n        vector<int> cur = global_best_applied;\n        for (int mid : cur) apply_add(moves[mid], board, score);\n        hill_climb(cur, board, score, moves, total_moves);\n        if (score > global_best_score) {\n            global_best_score = score;\n            global_best_applied = cur;\n        }\n    }\n\n    // output\n    cout << global_best_applied.size() << \"\\n\";\n    for (int mid : global_best_applied) {\n        cout << moves[mid].m << \" \" << moves[mid].p << \" \" << moves[mid].q << \"\\n\";\n    }\n\n    return 0;\n}","ahc033":"#include <iostream>\n#include <string>\n#include <vector>\n#include <algorithm>\n#include <climits>\nusing namespace std;\n\nconst int N = 5;\nconst int MAX_TURNS = 10000;\n\nint A[N][N];\nint arrival_gate[25];\nint arrival_pos[25];\nint arrival_idx[N];\nint grid[N][N];\nint container_pos[25];   // -1 not on ground, -2 dispatched, else cell index\nint next_needed[N];\nbool dispatched[25];     // true if already sent out from any gate\nint dispatched_count = 0;\n\nint crane_r = 0, crane_c = 0, holding = -1;\n\nbool cell_empty(int r, int c) {\n    return grid[r][c] == -1;\n}\n\n// A cell can be used as a buffer if it is empty and not a dispatch gate,\n// and if it is a receiving gate, then all arrivals for that row have finished.\nbool cell_safe_for_buffer(int r, int c) {\n    if (c == 4) return false;               // dispatch gate\n    if (c == 0) return arrival_idx[r] == N; // receiving gate only safe after all arrivals\n    return true;                            // columns 1..3\n}\n\nint count_free_buffers() {\n    int cnt = 0;\n    for (int r = 0; r < N; ++r)\n        for (int c = 0; c <= 3; ++c)\n            if (cell_empty(r, c) && cell_safe_for_buffer(r, c))\n                ++cnt;\n    return cnt;\n}\n\n// Best buffer cell for a container belonging to 'row'.\n// Prefer cells that minimise a combined cost of future distance to dispatch gate\n// and current distance from the crane.\npair<int,int> find_best_buffer(int row) {\n    int best_r = -1, best_c = -1;\n    int best_cost = INT_MAX;\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c <= 3; ++c) {\n            if (!cell_empty(r, c) || !cell_safe_for_buffer(r, c)) continue;\n            int future = abs(r - row) + abs(c - 4);\n            int cur = abs(crane_r - r) + abs(crane_c - c);\n            int cost = future * 10 + cur;   // future is more important\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_r = r;\n                best_c = c;\n            }\n        }\n    }\n    return {best_r, best_c};\n}\n\nchar move_towards(int tr, int tc) {\n    if (crane_r < tr) return 'D';\n    if (crane_r > tr) return 'U';\n    if (crane_c < tc) return 'R';\n    if (crane_c > tc) return 'L';\n    return '.';\n}\n\n// After a dispatch, update next_needed[i] to the smallest container\n// in [i*N, i*N+N-1] that has not been dispatched yet.\nvoid advance_next_needed(int i) {\n    while (next_needed[i] < i * N + N && dispatched[next_needed[i]])\n        ++next_needed[i];\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            cin >> A[i][j];\n            arrival_gate[A[i][j]] = i;\n            arrival_pos[A[i][j]] = j;\n        }\n\n    // Initialise\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            grid[i][j] = -1;\n    for (int i = 0; i < 25; ++i) {\n        container_pos[i] = -1;\n        dispatched[i] = false;\n    }\n    for (int i = 0; i < N; ++i) {\n        arrival_idx[i] = 0;\n        next_needed[i] = i * N;\n    }\n\n    string L_actions;\n    int turn = 0;\n\n    while (dispatched_count < N * N && turn < MAX_TURNS) {\n        // ---------- Step 1 : Receiving ----------\n        for (int i = 0; i < N; ++i) {\n            if (cell_empty(i, 0) && arrival_idx[i] < N) {\n                bool blocked = (holding != -1 && crane_r == i && crane_c == 0);\n                if (!blocked) {\n                    int cont = A[i][arrival_idx[i]++];\n                    grid[i][0] = cont;\n                    container_pos[cont] = i * N + 0;\n                }\n            }\n        }\n\n        char act = '.';\n\n        if (holding != -1) {\n            int C = holding;\n            int row = C / N;\n            if (C == next_needed[row]) {\n                // deliver target to its dispatch gate\n                if (crane_r == row && crane_c == 4) act = 'Q';\n                else act = move_towards(row, 4);\n            } else {\n                // store the blocking container\n                auto buf = find_best_buffer(row);\n                if (buf.first != -1) {\n                    if (crane_r == buf.first && crane_c == buf.second) act = 'Q';\n                    else act = move_towards(buf.first, buf.second);\n                } else {\n                    // no buffer \u2013 force dispatch at its own gate\n                    if (crane_r == row && crane_c == 4) act = 'Q';\n                    else act = move_towards(row, 4);\n                }\n            }\n        } else {\n            // empty hand \u2013 choose the best container to pick\n            // Priority 1: pick the smallest undelivered container currently on the ground\n            int best_target = -1;\n            int best_dist = INT_MAX;\n            for (int i = 0; i < N; ++i) {\n                int t = next_needed[i];\n                if (t >= i * N + N) continue;   // all dispatched for this row\n                if (container_pos[t] >= 0) {\n                    int pos = container_pos[t];\n                    int tr = pos / N, tc = pos % N;\n                    int d = abs(crane_r - tr) + abs(crane_c - tc);\n                    if (d < best_dist || (d == best_dist && t < best_target)) {\n                        best_dist = d;\n                        best_target = t;\n                    }\n                }\n            }\n\n            if (best_target != -1) {\n                int pos = container_pos[best_target];\n                int tr = pos / N, tc = pos % N;\n                if (crane_r == tr && crane_c == tc) act = 'P';\n                else act = move_towards(tr, tc);\n            } else {\n                // Priority 2: no needed target on ground \u2013 try to clear a blocked receiving gate\n                int free_buf = count_free_buffers();\n                int chosen_gate = -1;\n                int best_urgency = INT_MAX;  // smaller next_needed means more urgent\n                for (int i = 0; i < N; ++i) {\n                    // gate occupied and still receiving new containers\n                    if (arrival_idx[i] < N && !cell_empty(i, 0)) {\n                        if (next_needed[i] < best_urgency) {\n                            best_urgency = next_needed[i];\n                            chosen_gate = i;\n                        }\n                    }\n                }\n                if (chosen_gate != -1 && free_buf > 0) {\n                    // we can safely unblock this gate\n                    if (crane_r == chosen_gate && crane_c == 0) act = 'P';\n                    else act = move_towards(chosen_gate, 0);\n                } else if (chosen_gate != -1 && free_buf == 0) {\n                    // no free buffer, but we can still unblock by force\u2011dispatching\n                    // (this will cause an inversion, but it is necessary)\n                    if (crane_r == chosen_gate && crane_c == 0) act = 'P';\n                    else act = move_towards(chosen_gate, 0);\n                } else {\n                    // Priority 3: all receiving gates are empty \u2013 wait near the most urgent one\n                    int wait_row = -1;\n                    best_urgency = INT_MAX;\n                    for (int i = 0; i < N; ++i) {\n                        if (arrival_idx[i] < N) {\n                            if (next_needed[i] < best_urgency) {\n                                best_urgency = next_needed[i];\n                                wait_row = i;\n                            }\n                        }\n                    }\n                    if (wait_row != -1) {\n                        if (crane_r == wait_row && crane_c == 0) act = '.';\n                        else act = move_towards(wait_row, 0);\n                    } else {\n                        // everything already dispatched or waiting\n                        act = '.';\n                    }\n                }\n            }\n        }\n\n        // ---------- Apply action ----------\n        if (act == 'U') crane_r--;\n        else if (act == 'D') crane_r++;\n        else if (act == 'L') crane_c--;\n        else if (act == 'R') crane_c++;\n        else if (act == 'P') {\n            int cont = grid[crane_r][crane_c];\n            grid[crane_r][crane_c] = -1;\n            holding = cont;\n            container_pos[cont] = -1;\n        } else if (act == 'Q') {\n            grid[crane_r][crane_c] = holding;\n            container_pos[holding] = crane_r * N + crane_c;\n            holding = -1;\n        }\n        L_actions.push_back(act);\n\n        // ---------- Step 3 : Dispatching ----------\n        for (int i = 0; i < N; ++i) {\n            if (!cell_empty(i, 4)) {\n                int cont = grid[i][4];\n                grid[i][4] = -1;\n                container_pos[cont] = -2;\n                if (!dispatched[cont]) {\n                    dispatched[cont] = true;\n                    ++dispatched_count;\n                }\n                // advance next_needed[i] as far as possible\n                advance_next_needed(i);\n            }\n        }\n\n        ++turn;\n    }\n\n    // Output\n    cout << L_actions << \"\\n\";\n    for (int i = 1; i < N; ++i) cout << \"B\\n\";\n\n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <climits>\n#include <cstring>\nusing namespace std;\n\nstruct Task {\n    int r, c, h;\n};\n\nconst int MAX_S = 400;\n\nint N, S;\nvector<Task> tasks;\nint startDist[MAX_S];\nint distMat[MAX_S][MAX_S];\n\n// evaluate a permutation array, returns cost or -1 if infeasible\nlong long evaluate_array(const int* perm) {\n    long long cost = 0;\n    int load = 0;\n    int prev = -1;\n    for (int i = 0; i < S; ++i) {\n        int idx = perm[i];\n        int d = (prev == -1) ? startDist[idx] : distMat[prev][idx];\n        cost += (100LL + load) * d;\n        load += tasks[idx].h;\n        if (load < 0) return -1;\n        prev = idx;\n    }\n    if (load != 0) return -1;\n    return cost;\n}\n\nlong long evaluate_vec(const vector<int>& perm) {\n    return evaluate_array(perm.data());\n}\n\n// randomized greedy that interleaves pickups and drop\u2011offs\nvector<int> greedy_interleaved(mt19937_64& rng) {\n    auto manhattan = [](int r1, int c1, int r2, int c2) {\n        return abs(r1 - r2) + abs(c1 - c2);\n    };\n    vector<int> order;\n    vector<bool> used(S, false);\n    int cur_r = 0, cur_c = 0;\n    int load = 0;\n    while ((int)order.size() < S) {\n        vector<pair<long long, int>> cands;\n        for (int i = 0; i < S; ++i) {\n            if (used[i]) continue;\n            if (load + tasks[i].h < 0) continue;\n            int d = manhattan(cur_r, cur_c, tasks[i].r, tasks[i].c);\n            cands.emplace_back((100LL + load) * d, i);\n        }\n        if (cands.empty()) break;\n        sort(cands.begin(), cands.end());\n        int topK = min(8, (int)cands.size());\n        int pick = cands[uniform_int_distribution<int>(0, topK - 1)(rng)].second;\n        order.push_back(pick);\n        used[pick] = true;\n        cur_r = tasks[pick].r;\n        cur_c = tasks[pick].c;\n        load += tasks[pick].h;\n    }\n    return order;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto start_time = chrono::steady_clock::now();\n    auto get_time = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto rand_int = [&](int lo, int hi) {\n        return uniform_int_distribution<int>(lo, hi)(rng);\n    };\n    auto rand_double = [&]() {\n        return uniform_real_distribution<double>(0.0, 1.0)(rng);\n    };\n\n    cin >> N;\n    vector<vector<int>> H(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> H[i][j];\n\n    tasks.reserve(N * N);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (H[i][j] != 0)\n                tasks.push_back({i, j, H[i][j]});\n\n    S = tasks.size();\n    if (S == 0) return 0;\n\n    auto manhattan = [](int r1, int c1, int r2, int c2) {\n        return abs(r1 - r2) + abs(c1 - c2);\n    };\n    for (int i = 0; i < S; ++i)\n        startDist[i] = manhattan(0, 0, tasks[i].r, tasks[i].c);\n    for (int i = 0; i < S; ++i)\n        for (int j = 0; j < S; ++j)\n            distMat[i][j] = manhattan(tasks[i].r, tasks[i].c, tasks[j].r, tasks[j].c);\n\n    vector<int> posIdx, negIdx;\n    for (int i = 0; i < S; ++i)\n        (tasks[i].h > 0 ? posIdx : negIdx).push_back(i);\n\n    // -------- initial solutions --------\n    vector<int> bestPerm;\n    long long bestCost = LLONG_MAX;\n\n    auto update_best = [&](const vector<int>& cand) {\n        long long c = evaluate_vec(cand);\n        if (c != -1 && c < bestCost) {\n            bestCost = c;\n            bestPerm = cand;\n        }\n    };\n\n    // 1. all positives then negatives (shuffled inside groups)\n    for (int rep = 0; rep < 30; ++rep) {\n        vector<int> cand = posIdx;\n        shuffle(cand.begin(), cand.end(), rng);\n        vector<int> negCand = negIdx;\n        shuffle(negCand.begin(), negCand.end(), rng);\n        cand.insert(cand.end(), negCand.begin(), negCand.end());\n        update_best(cand);\n    }\n\n    // 2. greedy interleaved\n    for (int rep = 0; rep < 70; ++rep) {\n        vector<int> cand = greedy_interleaved(rng);\n        if ((int)cand.size() != S) continue;\n        update_best(cand);\n    }\n\n    // fallback (should never be needed)\n    if (bestCost == LLONG_MAX) {\n        bestPerm = posIdx;\n        bestPerm.insert(bestPerm.end(), negIdx.begin(), negIdx.end());\n        bestCost = evaluate_vec(bestPerm);\n    }\n\n    int curArr[MAX_S];\n    int bestArr[MAX_S];\n    copy(bestPerm.begin(), bestPerm.end(), bestArr);\n    copy(bestPerm.begin(), bestPerm.end(), curArr);\n    long long curCost = bestCost;\n\n    // -------- Simulated Annealing --------\n    double T = 1500.0;\n    double T_min = 0.01;\n    double alpha = 0.9998;\n    int step = 0;\n    const int CHECK_PERIOD = 2000;\n    int tmpArr[MAX_S];\n\n    while (true) {\n        if (step % CHECK_PERIOD == 0 && get_time() > 1.90) break;\n        int moveType = rand_int(0, 2);\n        if (moveType == 0) { // swap\n            int i = rand_int(0, S - 1);\n            int j = rand_int(0, S - 1);\n            if (i == j) continue;\n            swap(curArr[i], curArr[j]);\n            long long newCost = evaluate_array(curArr);\n            if (newCost != -1) {\n                long long delta = newCost - curCost;\n                if (delta <= 0 || rand_double() < exp(-delta / T)) {\n                    curCost = newCost;\n                    if (curCost < bestCost) {\n                        bestCost = curCost;\n                        memcpy(bestArr, curArr, S * sizeof(int));\n                    }\n                } else {\n                    swap(curArr[i], curArr[j]);\n                }\n            } else {\n                swap(curArr[i], curArr[j]);\n            }\n        } else if (moveType == 1) { // reverse\n            if (S < 2) continue;\n            int l = rand_int(0, S - 2);\n            int r = rand_int(l + 1, S - 1);\n            reverse(curArr + l, curArr + r + 1);\n            long long newCost = evaluate_array(curArr);\n            if (newCost != -1) {\n                long long delta = newCost - curCost;\n                if (delta <= 0 || rand_double() < exp(-delta / T)) {\n                    curCost = newCost;\n                    if (curCost < bestCost) {\n                        bestCost = curCost;\n                        memcpy(bestArr, curArr, S * sizeof(int));\n                    }\n                } else {\n                    reverse(curArr + l, curArr + r + 1);\n                }\n            } else {\n                reverse(curArr + l, curArr + r + 1);\n            }\n        } else { // insert\n            int from = rand_int(0, S - 1);\n            int to = rand_int(0, S - 1);\n            if (from == to || from == to + 1) continue;\n            int val = curArr[from];\n            if (from < to) {\n                memcpy(tmpArr, curArr, from * sizeof(int));\n                memcpy(tmpArr + from, curArr + from + 1, (to - from) * sizeof(int));\n                tmpArr[to] = val;\n                memcpy(tmpArr + to + 1, curArr + to + 1, (S - to - 1) * sizeof(int));\n            } else {\n                memcpy(tmpArr, curArr, to * sizeof(int));\n                tmpArr[to] = val;\n                memcpy(tmpArr + to + 1, curArr + to, (from - to) * sizeof(int));\n                memcpy(tmpArr + from + 1, curArr + from + 1, (S - from - 1) * sizeof(int));\n            }\n            long long newCost = evaluate_array(tmpArr);\n            if (newCost != -1) {\n                long long delta = newCost - curCost;\n                if (delta <= 0 || rand_double() < exp(-delta / T)) {\n                    memcpy(curArr, tmpArr, S * sizeof(int));\n                    curCost = newCost;\n                    if (curCost < bestCost) {\n                        bestCost = curCost;\n                        memcpy(bestArr, curArr, S * sizeof(int));\n                    }\n                }\n            }\n        }\n        T *= alpha;\n        if (T < T_min) T = T_min;\n        ++step;\n    }\n\n    // -------- Hill climbing --------\n    int no_improve = 0;\n    const int MAX_HILL = 100000;\n    for (int rep = 0; rep < MAX_HILL; ++rep) {\n        if (get_time() > 1.98) break;\n        int moveType = rand_int(0, 2);\n        if (moveType == 0) {\n            int i = rand_int(0, S - 1);\n            int j = rand_int(0, S - 1);\n            if (i == j) continue;\n            swap(curArr[i], curArr[j]);\n            long long newCost = evaluate_array(curArr);\n            if (newCost != -1 && newCost < curCost) {\n                curCost = newCost;\n                if (curCost < bestCost) {\n                    bestCost = curCost;\n                    memcpy(bestArr, curArr, S * sizeof(int));\n                }\n                no_improve = 0;\n            } else {\n                swap(curArr[i], curArr[j]);\n                ++no_improve;\n            }\n        } else if (moveType == 1) {\n            if (S < 2) continue;\n            int l = rand_int(0, S - 2);\n            int r = rand_int(l + 1, S - 1);\n            reverse(curArr + l, curArr + r + 1);\n            long long newCost = evaluate_array(curArr);\n            if (newCost != -1 && newCost < curCost) {\n                curCost = newCost;\n                if (curCost < bestCost) {\n                    bestCost = curCost;\n                    memcpy(bestArr, curArr, S * sizeof(int));\n                }\n                no_improve = 0;\n            } else {\n                reverse(curArr + l, curArr + r + 1);\n                ++no_improve;\n            }\n        } else {\n            int from = rand_int(0, S - 1);\n            int to = rand_int(0, S - 1);\n            if (from == to || from == to + 1) continue;\n            int val = curArr[from];\n            if (from < to) {\n                memcpy(tmpArr, curArr, from * sizeof(int));\n                memcpy(tmpArr + from, curArr + from + 1, (to - from) * sizeof(int));\n                tmpArr[to] = val;\n                memcpy(tmpArr + to + 1, curArr + to + 1, (S - to - 1) * sizeof(int));\n            } else {\n                memcpy(tmpArr, curArr, to * sizeof(int));\n                tmpArr[to] = val;\n                memcpy(tmpArr + to + 1, curArr + to, (from - to) * sizeof(int));\n                memcpy(tmpArr + from + 1, curArr + from + 1, (S - from - 1) * sizeof(int));\n            }\n            long long newCost = evaluate_array(tmpArr);\n            if (newCost != -1 && newCost < curCost) {\n                memcpy(curArr, tmpArr, S * sizeof(int));\n                curCost = newCost;\n                if (curCost < bestCost) {\n                    bestCost = curCost;\n                    memcpy(bestArr, curArr, S * sizeof(int));\n                }\n                no_improve = 0;\n            } else {\n                ++no_improve;\n            }\n        }\n        if (no_improve >= 5000) break;\n    }\n\n    // -------- Output --------\n    vector<string> ops;\n    int cur_r = 0, cur_c = 0;\n    for (int i = 0; i < S; ++i) {\n        int idx = bestArr[i];\n        int tr = tasks[idx].r, tc = tasks[idx].c;\n        while (cur_r < tr) { ops.push_back(\"D\"); cur_r++; }\n        while (cur_r > tr) { ops.push_back(\"U\"); cur_r--; }\n        while (cur_c < tc) { ops.push_back(\"R\"); cur_c++; }\n        while (cur_c > tc) { ops.push_back(\"L\"); cur_c--; }\n        if (tasks[idx].h > 0)\n            ops.push_back(\"+\" + to_string(tasks[idx].h));\n        else\n            ops.push_back(\"-\" + to_string(-tasks[idx].h));\n    }\n    for (const auto& s : ops) cout << s << '\\n';\n\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <chrono>\n#include <cstdint>\n#include <cstring>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, T;\n    cin >> N >> M >> T;\n    const int seed_cnt = 2 * N * (N - 1);   // 60\n    const int cells = N * N;                // 36\n\n    // initial pool\n    vector<vector<int>> seeds(seed_cnt, vector<int>(M));\n    for (int i = 0; i < seed_cnt; ++i)\n        for (int j = 0; j < M; ++j)\n            cin >> seeds[i][j];\n\n    // grid helper: linear index of cell (r,c) = r*N + c\n    auto idx = [&](int r, int c) { return r * N + c; };\n\n    // adjacency list for cells\n    vector<vector<int>> adj(cells);\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int id = idx(r, c);\n            if (r > 0) adj[id].push_back(idx(r - 1, c));\n            if (r < N - 1) adj[id].push_back(idx(r + 1, c));\n            if (c > 0) adj[id].push_back(idx(r, c - 1));\n            if (c < N - 1) adj[id].push_back(idx(r, c + 1));\n        }\n    }\n\n    // list of edges (each unordered pair once)\n    vector<pair<int, int>> edges;\n    for (int i = 0; i < cells; ++i)\n        for (int nb : adj[i])\n            if (i < nb) edges.push_back({i, nb});\n\n    // cell ordering by degree (descending) \u2013 used later if needed\n    vector<int> deg(cells);\n    for (int i = 0; i < cells; ++i) deg[i] = adj[i].size();\n    vector<int> cell_order(cells);\n    iota(cell_order.begin(), cell_order.end(), 0);\n    sort(cell_order.begin(), cell_order.end(), [&](int a, int b) {\n        if (deg[a] != deg[b]) return deg[a] > deg[b];\n        return a < b;\n    });\n\n    // random generator\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> cell_dist(0, cells - 1);\n\n    // time limit per turn (2 sec total for 10 turns \u2192 0.2 sec per turn)\n    const auto turn_time_limit = chrono::milliseconds(180);\n\n    for (int t = 0; t < T; ++t) {\n        // ----- compute current feature maximums and seed statistics -----\n        vector<int> cur_max(M, 0);\n        for (int i = 0; i < seed_cnt; ++i)\n            for (int j = 0; j < M; ++j)\n                if (seeds[i][j] > cur_max[j]) cur_max[j] = seeds[i][j];\n\n        vector<uint16_t> mask(seed_cnt, 0);\n        vector<int> sum_val(seed_cnt, 0);\n        for (int i = 0; i < seed_cnt; ++i) {\n            uint16_t m = 0;\n            int s = 0;\n            for (int j = 0; j < M; ++j) {\n                s += seeds[i][j];\n                if (seeds[i][j] == cur_max[j]) m |= (1 << j);\n            }\n            mask[i] = m;\n            sum_val[i] = s;\n        }\n\n        // pairwise potential (sum of feature\u2011wise max)\n        vector<vector<int>> pot(seed_cnt, vector<int>(seed_cnt, 0));\n        for (int i = 0; i < seed_cnt; ++i)\n            for (int j = i + 1; j < seed_cnt; ++j) {\n                int p = 0;\n                for (int l = 0; l < M; ++l) p += max(seeds[i][l], seeds[j][l]);\n                pot[i][j] = pot[j][i] = p;\n            }\n\n        // ----- seed selection -----\n        vector<bool> selected_flag(seed_cnt, false);\n        vector<int> selected;\n\n        // greedy set cover for current maximum features\n        uint16_t uncovered = (1 << M) - 1;\n        while (uncovered) {\n            int best_i = -1, best_cnt = 0, best_score = -1;\n            for (int i = 0; i < seed_cnt; ++i) {\n                if (selected_flag[i]) continue;\n                int cnt = __builtin_popcount((unsigned int)(mask[i] & uncovered));\n                if (cnt == 0) continue;\n                int score = __builtin_popcount((unsigned int)mask[i]) * 1000 + sum_val[i];\n                if (cnt > best_cnt || (cnt == best_cnt && score > best_score)) {\n                    best_cnt = cnt;\n                    best_score = score;\n                    best_i = i;\n                }\n            }\n            if (best_i == -1) break;   // should never happen\n            selected_flag[best_i] = true;\n            selected.push_back(best_i);\n            uncovered &= ~mask[best_i];\n        }\n\n        // fill remaining slots using pair potential with already selected seeds\n        while ((int)selected.size() < cells) {\n            int best_i = -1;\n            long long best_score = -1;\n            for (int i = 0; i < seed_cnt; ++i) {\n                if (selected_flag[i]) continue;\n                int max_pot = 0;\n                for (int s : selected) max_pot = max(max_pot, pot[s][i]);\n                long long score = max_pot * 10LL + sum_val[i];\n                if (score > best_score) {\n                    best_score = score;\n                    best_i = i;\n                }\n            }\n            selected_flag[best_i] = true;\n            selected.push_back(best_i);\n        }\n\n        // ----- intra\u2011edge score (based on current maximum masks) -----\n        auto pair_score_fn = [&](uint16_t m1, uint16_t m2) {\n            return 2 * __builtin_popcount((unsigned int)(m1 & m2))\n                 + __builtin_popcount((unsigned int)(m1 ^ m2));\n        };\n\n        vector<vector<int>> pair_score(seed_cnt, vector<int>(seed_cnt));\n        for (int i = 0; i < seed_cnt; ++i)\n            for (int j = 0; j < seed_cnt; ++j)\n                pair_score[i][j] = pair_score_fn(mask[i], mask[j]);\n\n        // ----- initial placement: greedy, starting from the best pair -----\n        // find best pair among selected\n        int best_pair_val = -1;\n        int best_a = -1, best_b = -1;\n        for (int i = 0; i < (int)selected.size(); ++i)\n            for (int j = i + 1; j < (int)selected.size(); ++j) {\n                int val = pot[selected[i]][selected[j]];\n                if (val > best_pair_val) {\n                    best_pair_val = val;\n                    best_a = i;   // index in selected\n                    best_b = j;\n                }\n            }\n\n        vector<int> assign(cells, -1);\n        vector<bool> cell_used(cells, false);\n        vector<int> seeds_to_place = selected; // copy\n\n        // start with a high\u2011degree edge (we pick (2,2)-(2,3) if N=6)\n        int start_cell1 = idx(2, 2), start_cell2 = idx(2, 3);\n        assign[start_cell1] = seeds_to_place[best_a];\n        assign[start_cell2] = seeds_to_place[best_b];\n        cell_used[start_cell1] = cell_used[start_cell2] = true;\n\n        // mark those two seeds as placed\n        vector<bool> seed_placed(seed_cnt, false);\n        seed_placed[seeds_to_place[best_a]] = seed_placed[seeds_to_place[best_b]] = true;\n\n        // list of frontier cells (empty cells adjacent to a placed cell)\n        vector<int> frontier;\n        auto add_frontier = [&](int cell) {\n            for (int nb : adj[cell])\n                if (!cell_used[nb]) {\n                    bool already = false;\n                    for (int f : frontier) if (f == nb) { already = true; break; }\n                    if (!already) frontier.push_back(nb);\n                }\n        };\n        add_frontier(start_cell1);\n        add_frontier(start_cell2);\n\n        // place remaining seeds\n        vector<int> unplaced;\n        for (int idx : selected)\n            if (!seed_placed[idx]) unplaced.push_back(idx);\n\n        while (!unplaced.empty()) {\n            int best_cell = -1, best_seed = -1;\n            int best_gain = -1;\n            // for each frontier cell and each unplaced seed, compute gain = sum of pair_score with all placed neighbours\n            for (int cell : frontier) {\n                // compute neighbour masks already placed\n                int base_gain = 0;   // could be precomputed but small\n                for (int nb : adj[cell])\n                    if (assign[nb] != -1)\n                        base_gain = 0; // we'll compute per seed\n                for (int sidx = 0; sidx < (int)unplaced.size(); ++sidx) {\n                    int seed = unplaced[sidx];\n                    int gain = 0;\n                    for (int nb : adj[cell]) {\n                        if (assign[nb] != -1)\n                            gain += pair_score[seed][assign[nb]];\n                    }\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        best_cell = cell;\n                        best_seed = sidx;\n                    }\n                }\n            }\n            // place the best found\n            assign[best_cell] = unplaced[best_seed];\n            cell_used[best_cell] = true;\n            seed_placed[unplaced[best_seed]] = true;\n            // update frontier: remove the cell just filled and add its empty neighbours\n            frontier.erase(remove(frontier.begin(), frontier.end(), best_cell), frontier.end());\n            add_frontier(best_cell);\n            // remove the placed seed from unplaced\n            unplaced.erase(unplaced.begin() + best_seed);\n        }\n\n        // ----- hill climbing with delta swaps -----\n        // delta function\n        auto delta_swap = [&](int u, int v) {\n            int delta = 0;\n            for (int nb : adj[u]) {\n                if (nb == v) continue;\n                delta -= pair_score[assign[u]][assign[nb]];\n                delta += pair_score[assign[v]][assign[nb]];\n            }\n            for (int nb : adj[v]) {\n                if (nb == u) continue;\n                delta -= pair_score[assign[v]][assign[nb]];\n                delta += pair_score[assign[u]][assign[nb]];\n            }\n            return delta;\n        };\n\n        int cur_total = 0;\n        for (auto &e : edges)\n            cur_total += pair_score[assign[e.first]][assign[e.second]];\n\n        int best_total = cur_total;\n        vector<int> best_assign = assign;\n\n        auto turn_start = chrono::steady_clock::now();\n        for (int it = 0; ; ++it) {\n            if (it % 1024 == 0) {\n                auto now = chrono::steady_clock::now();\n                if (now - turn_start > turn_time_limit) break;\n            }\n            int u = cell_dist(rng);\n            int v = cell_dist(rng);\n            if (u == v) continue;\n\n            int delta = delta_swap(u, v);\n            if (delta > 0) {\n                swap(assign[u], assign[v]);\n                cur_total += delta;\n                if (cur_total > best_total) {\n                    best_total = cur_total;\n                    best_assign = assign;\n                }\n            }\n        }\n\n        assign = best_assign;\n\n        // ----- output -----\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                if (c) cout << ' ';\n                cout << assign[idx(r, c)];\n            }\n            cout << '\\n';\n        }\n        cout.flush();\n\n        // ----- read next generation -----\n        for (int i = 0; i < seed_cnt; ++i)\n            for (int j = 0; j < M; ++j)\n                cin >> seeds[i][j];\n    }\n\n    return 0;\n}","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <functional>\nusing namespace std;\n\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(0);\n    \n    int N, M, V;\n    cin >> N >> M >> V;\n    vector<string> s(N), t(N);\n    for (int i = 0; i < N; ++i) cin >> s[i];\n    for (int i = 0; i < N; ++i) cin >> t[i];\n    \n    int sources = 0, targets = 0;\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') ++sources;\n            if (t[i][j] == '1' && s[i][j] == '0') ++targets;\n        }\n    }\n    \n    int C = V - 1;                // number of leaves\n    vector<int> arm_len(C);\n    for (int i = 0; i < C; ++i) arm_len[i] = i + 1;\n    \n    vector<int> cur_dir(C, 0);    // 0:right, 1:down, 2:left, 3:up\n    vector<bool> hold(C, false);\n    \n    // choose best initial root\n    int init_rx = 0, init_ry = 0;\n    {\n        int best_act = -1;\n        vector<vector<int>> tmp_adj(C);\n        auto count_actions = [&](int rx, int ry) -> int {\n            for (int i = 0; i < C; ++i) tmp_adj[i].clear();\n            vector<int> cell_list;\n            for (int i = 0; i < C; ++i) {\n                int L = arm_len[i];\n                for (int d = 0; d < 4; ++d) {\n                    int nx = rx + dx[d] * L;\n                    int ny = ry + dy[d] * L;\n                    if (nx < 0 || nx >= N || ny < 0 || ny >= N) continue;\n                    bool ok = false;\n                    if (!hold[i] && s[nx][ny] == '1' && t[nx][ny] == '0') ok = true;\n                    else if (hold[i] && t[nx][ny] == '1' && s[nx][ny] == '0') ok = true;\n                    if (ok) {\n                        int cid = nx * N + ny;\n                        int idx = -1;\n                        for (int k = 0; k < (int)cell_list.size(); ++k) {\n                            if (cell_list[k] == cid) { idx = k; break; }\n                        }\n                        if (idx == -1) {\n                            idx = cell_list.size();\n                            cell_list.push_back(cid);\n                        }\n                        tmp_adj[i].push_back(idx);\n                    }\n                }\n            }\n            int R = cell_list.size();\n            vector<int> matchR(R, -1);\n            vector<bool> vis;\n            function<bool(int)> dfs = [&](int u) -> bool {\n                for (int v : tmp_adj[u]) {\n                    if (vis[v]) continue;\n                    vis[v] = true;\n                    if (matchR[v] == -1 || dfs(matchR[v])) {\n                        matchR[v] = u;\n                        return true;\n                    }\n                }\n                return false;\n            };\n            int cnt = 0;\n            for (int i = 0; i < C; ++i) {\n                vis.assign(R, false);\n                if (dfs(i)) ++cnt;\n            }\n            return cnt;\n        };\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                int act = count_actions(i, j);\n                if (act > best_act) {\n                    best_act = act;\n                    init_rx = i;\n                    init_ry = j;\n                }\n            }\n        }\n    }\n    int rx = init_rx, ry = init_ry;\n    \n    // output tree\n    cout << V << \"\\n\";\n    for (int i = 0; i < C; ++i) cout << 0 << \" \" << arm_len[i] << \"\\n\";\n    cout << init_rx << \" \" << init_ry << \"\\n\";\n    \n    const int MAX_TURNS = 100000;\n    int turn_cnt = 0;\n    \n    auto output_turn = [&](char mv, const string& rot, const string& act) {\n        string S(2 * V, '.');\n        S[0] = mv;\n        for (int i = 0; i < C; ++i) S[1 + i] = rot[i];\n        for (int i = 0; i < V; ++i) S[V + i] = act[i];\n        cout << S << \"\\n\";\n        ++turn_cnt;\n    };\n    \n    // full matching function\n    auto compute_matching = [&](int x, int y, vector<int>& mcell, vector<int>& mdir) -> int {\n        mcell.assign(C, -1);\n        mdir.assign(C, -1);\n        vector<vector<pair<int,int>>> adj(C);\n        vector<int> cell_list;\n        for (int i = 0; i < C; ++i) {\n            int L = arm_len[i];\n            for (int d = 0; d < 4; ++d) {\n                int nx = x + dx[d] * L;\n                int ny = y + dy[d] * L;\n                if (nx < 0 || nx >= N || ny < 0 || ny >= N) continue;\n                if (!hold[i] && s[nx][ny] == '1' && t[nx][ny] == '0') {\n                    int cid = nx * N + ny;\n                    int idx = -1;\n                    for (int k = 0; k < (int)cell_list.size(); ++k)\n                        if (cell_list[k] == cid) { idx = k; break; }\n                    if (idx == -1) {\n                        idx = cell_list.size();\n                        cell_list.push_back(cid);\n                    }\n                    adj[i].emplace_back(idx, d);\n                } else if (hold[i] && t[nx][ny] == '1' && s[nx][ny] == '0') {\n                    int cid = nx * N + ny;\n                    int idx = -1;\n                    for (int k = 0; k < (int)cell_list.size(); ++k)\n                        if (cell_list[k] == cid) { idx = k; break; }\n                    if (idx == -1) {\n                        idx = cell_list.size();\n                        cell_list.push_back(cid);\n                    }\n                    adj[i].emplace_back(idx, d);\n                }\n            }\n        }\n        int R = cell_list.size();\n        vector<int> matchR(R, -1);\n        vector<bool> vis;\n        function<bool(int)> dfs = [&](int u) -> bool {\n            for (auto [v, d] : adj[u]) {\n                if (vis[v]) continue;\n                vis[v] = true;\n                if (matchR[v] == -1 || dfs(matchR[v])) {\n                    matchR[v] = u;\n                    mcell[u] = cell_list[v];\n                    mdir[u] = d;\n                    return true;\n                }\n            }\n            return false;\n        };\n        int cnt = 0;\n        for (int i = 0; i < C; ++i) {\n            vis.assign(R, false);\n            if (dfs(i)) ++cnt;\n        }\n        return cnt;\n    };\n    \n    // function that executes a sequence of moves + rotations + actions\n    auto execute_plan = [&](int tr, int tc, vector<int>& mcell, vector<int>& mdir) {\n        // build Manhattan path\n        vector<pair<int,int>> path;\n        int cx = rx, cy = ry;\n        while (cx != tr) {\n            cx += (tr > cx ? 1 : -1);\n            path.emplace_back(cx, cy);\n        }\n        while (cy != tc) {\n            cy += (tc > cy ? 1 : -1);\n            path.emplace_back(cx, cy);\n        }\n        int D = path.size();\n        vector<int> needed(C, 0);\n        for (int i = 0; i < C; ++i) {\n            if (mcell[i] != -1) {\n                int diff = (mdir[i] - cur_dir[i] + 4) % 4;\n                needed[i] = min(diff, 4 - diff);\n            }\n        }\n        int max_st = 0;\n        for (int i = 0; i < C; ++i) max_st = max(max_st, needed[i]);\n        int T = max({1, D, max_st});\n        int pidx = 0;\n        for (int t = 0; t < T; ++t) {\n            char mv = '.';\n            if (pidx < D) {\n                auto [nr, nc] = path[pidx];\n                if (nr > rx) mv = 'D';\n                else if (nr < rx) mv = 'U';\n                else if (nc > ry) mv = 'R';\n                else if (nc < ry) mv = 'L';\n                rx = nr; ry = nc;\n                ++pidx;\n            }\n            string rot(C, '.');\n            string act(V, '.');\n            for (int i = 0; i < C; ++i) {\n                if (needed[i] > 0) {\n                    int diff = (mdir[i] - cur_dir[i] + 4) % 4;\n                    if (diff == 1) {\n                        rot[i] = 'R';\n                        cur_dir[i] = (cur_dir[i] + 1) % 4;\n                        needed[i]--;\n                    } else if (diff == 3) {\n                        rot[i] = 'L';\n                        cur_dir[i] = (cur_dir[i] + 3) % 4;\n                        needed[i]--;\n                    } else { // diff == 2\n                        rot[i] = 'R';\n                        cur_dir[i] = (cur_dir[i] + 1) % 4;\n                        needed[i]--;\n                    }\n                }\n                if (t == T-1 && mcell[i] != -1) {\n                    act[i+1] = 'P';\n                }\n            }\n            output_turn(mv, rot, act);\n        }\n        // apply actions\n        for (int i = 0; i < C; ++i) {\n            if (mcell[i] != -1) {\n                int r = mcell[i] / N, c = mcell[i] % N;\n                if (!hold[i]) {\n                    s[r][c] = '0';\n                    --sources;\n                    hold[i] = true;\n                } else {\n                    s[r][c] = '1';\n                    --targets;\n                    hold[i] = false;\n                }\n            }\n        }\n    };\n    \n    vector<int> mcell(C), mdir(C);\n    while (turn_cnt < MAX_TURNS) {\n        if (sources == 0 && targets == 0) {\n            bool any = false;\n            for (bool h : hold) if (h) any = true;\n            if (!any) break;\n        }\n        \n        int act_cnt = compute_matching(rx, ry, mcell, mdir);\n        if (act_cnt > 0) {\n            execute_plan(rx, ry, mcell, mdir);\n            continue;\n        }\n        \n        // BFS to find a reachable cell with actions\n        vector<vector<int>> dist(N, vector<int>(N, -1));\n        queue<pair<int,int>> q;\n        q.push({rx, ry});\n        dist[rx][ry] = 0;\n        int tr = -1, tc = -1;\n        vector<int> best_mcell, best_mdir;\n        while (!q.empty()) {\n            auto [r, c] = q.front(); q.pop();\n            int d = dist[r][c];\n            int act = compute_matching(r, c, mcell, mdir);\n            if (act > 0) {\n                tr = r; tc = c;\n                best_mcell = mcell;\n                best_mdir = mdir;\n                break;\n            }\n            for (int k = 0; k < 4; ++k) {\n                int nr = r + dx[k], nc = c + dy[k];\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N && dist[nr][nc] == -1) {\n                    dist[nr][nc] = d + 1;\n                    q.push({nr, nc});\n                }\n            }\n        }\n        \n        if (tr == -1) {\n            // fallback: move one step towards centroid\n            double sumr = 0, sumc = 0;\n            int cnt = 0;\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') || (t[i][j] == '1' && s[i][j] == '0')) {\n                        sumr += i; sumc += j; cnt++;\n                    }\n            if (cnt == 0) break;\n            tr = (int)(sumr / cnt + 0.5);\n            tc = (int)(sumc / cnt + 0.5);\n            tr = max(0, min(N-1, tr));\n            tc = max(0, min(N-1, tc));\n            if (tr == rx && tc == ry) {\n                // stuck, break\n                break;\n            }\n            best_mcell.assign(C, -1);\n            best_mdir.assign(C, -1);\n        }\n        \n        execute_plan(tr, tc, best_mcell, best_mdir);\n    }\n    \n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <unordered_map>\n\nconst int S = 4000;                // cell size\nconst int W = 100000 / S;          // grid width  (25)\nconst int H = 100000 / S;          // grid height (25)\nconst int MAX_PERIMETER = 400000;\n\nstruct Edge {\n    int to, rev, cap;\n};\n\nclass Dinic {\n    int N;\n    std::vector<std::vector<Edge>> g;\n    std::vector<int> level, iter;\n\n    bool bfs(int s, int t) {\n        std::fill(level.begin(), level.end(), -1);\n        std::queue<int> q;\n        level[s] = 0;\n        q.push(s);\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (auto &e : g[v]) {\n                if (e.cap > 0 && level[e.to] == -1) {\n                    level[e.to] = level[v] + 1;\n                    q.push(e.to);\n                }\n            }\n        }\n        return level[t] != -1;\n    }\n\n    int dfs(int s, int t, int f) {\n        std::vector<std::pair<int,int>> st;\n        std::vector<int> prev(N, -1), prev_edge(N, -1);\n        st.push_back({s, f});\n        prev[s] = s;\n        while (!st.empty()) {\n            auto [v, flow] = st.back();\n            if (v == t) {\n                for (int u = t; u != s; u = prev[u]) {\n                    int ei = prev_edge[u];\n                    Edge &e = g[prev[u]][ei];\n                    e.cap -= flow;\n                    g[u][e.rev].cap += flow;\n                }\n                return flow;\n            }\n            bool found = false;\n            for (int &i = iter[v]; i < (int)g[v].size(); /* increment inside */) {\n                Edge &e = g[v][i];\n                if (e.cap > 0 && level[v] + 1 == level[e.to]) {\n                    prev[e.to] = v;\n                    prev_edge[e.to] = i;\n                    st.push_back({e.to, std::min(flow, e.cap)});\n                    ++i;\n                    found = true;\n                    break;\n                } else {\n                    ++i;\n                }\n            }\n            if (!found) {\n                st.pop_back();\n            }\n        }\n        return 0;\n    }\n\npublic:\n    explicit Dinic(int n) : N(n), g(n), level(n), iter(n) {}\n\n    void add_edge(int from, int to, int cap) {\n        g[from].push_back({to, (int)g[to].size(), cap});\n        g[to].push_back({from, (int)g[from].size() - 1, 0});\n    }\n\n    void add_undirected(int u, int v, int cap) {\n        add_edge(u, v, cap);\n        add_edge(v, u, cap);\n    }\n\n    int max_flow(int s, int t) {\n        int flow = 0;\n        while (bfs(s, t)) {\n            std::fill(iter.begin(), iter.end(), 0);\n            int f;\n            while ((f = dfs(s, t, 1'000'000'000)) > 0)\n                flow += f;\n        }\n        return flow;\n    }\n\n    std::vector<bool> get_source_set(int s) {\n        std::vector<bool> vis(N, false);\n        std::queue<int> q;\n        q.push(s);\n        vis[s] = true;\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (auto &e : g[v]) {\n                if (e.cap > 0 && !vis[e.to]) {\n                    vis[e.to] = true;\n                    q.push(e.to);\n                }\n            }\n        }\n        return vis;\n    }\n};\n\nint main() {\n    std::ios::sync_with_stdio(false);\n    std::cin.tie(nullptr);\n\n    int N;\n    std::cin >> N;\n    std::vector<int> x(2 * N), y(2 * N);\n    for (int i = 0; i < 2 * N; ++i)\n        std::cin >> x[i] >> y[i];\n\n    // weight = mackerels - sardines per cell\n    std::vector<std::vector<int>> weight(H, std::vector<int>(W, 0));\n    for (int i = 0; i < N; ++i) {\n        int cx = std::min(x[i] / S, W - 1);\n        int cy = std::min(y[i] / S, H - 1);\n        weight[cy][cx]++;\n    }\n    for (int i = N; i < 2 * N; ++i) {\n        int cx = std::min(x[i] / S, W - 1);\n        int cy = std::min(y[i] / S, H - 1);\n        weight[cy][cx]--;\n    }\n\n    const int dx[4] = {1, -1, 0, 0};\n    const int dy[4] = {0, 0, 1, -1};\n\n    // trade\u2011off parameters (penalty per grid edge)\n    std::vector<int> lambdas = {\n        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 18, 20,\n        25, 30, 35, 40, 50, 60, 70, 80, 100, 120, 150, 200, 250, 300, 400, 500\n    };\n\n    int best_score = -1;\n    std::vector<std::vector<bool>> best_inside(H, std::vector<bool>(W, false));\n\n    for (int lambda : lambdas) {\n        Dinic dinic(W * H + 2);\n        int src = W * H, sink = src + 1;\n\n        // unary terms\n        for (int j = 0; j < H; ++j)\n            for (int i = 0; i < W; ++i) {\n                int id = i + j * W;\n                int w = weight[j][i];\n                if (w > 0) dinic.add_edge(src, id, w);\n                else if (w < 0) dinic.add_edge(id, sink, -w);\n            }\n\n        // pairwise terms (grid edges)\n        for (int j = 0; j < H; ++j)\n            for (int i = 0; i < W; ++i) {\n                int id = i + j * W;\n                if (i + 1 < W) dinic.add_undirected(id, id + 1, lambda);\n                if (j + 1 < H) dinic.add_undirected(id, id + W, lambda);\n            }\n\n        dinic.max_flow(src, sink);\n        auto vis = dinic.get_source_set(src);\n        std::vector<std::vector<bool>> inside(H, std::vector<bool>(W, false));\n        for (int j = 0; j < H; ++j)\n            for (int i = 0; i < W; ++i)\n                inside[j][i] = vis[i + j * W];\n\n        // connected components of the selected cells\n        std::vector<std::vector<int>> comp(H, std::vector<int>(W, -1));\n        int comp_cnt = 0;\n        for (int j = 0; j < H; ++j)\n            for (int i = 0; i < W; ++i)\n                if (inside[j][i] && comp[j][i] == -1) {\n                    std::queue<std::pair<int,int>> q;\n                    q.push({i, j});\n                    comp[j][i] = comp_cnt;\n                    while (!q.empty()) {\n                        auto [cx, cy] = q.front(); q.pop();\n                        for (int d = 0; d < 4; ++d) {\n                            int nx = cx + dx[d], ny = cy + dy[d];\n                            if (nx >= 0 && nx < W && ny >= 0 && ny < H &&\n                                inside[ny][nx] && comp[ny][nx] == -1) {\n                                comp[ny][nx] = comp_cnt;\n                                q.push({nx, ny});\n                            }\n                        }\n                    }\n                    ++comp_cnt;\n                }\n\n        // evaluate each component (fill holes, check perimeter)\n        for (int c = 0; c < comp_cnt; ++c) {\n            int min_i = W, max_i = -1, min_j = H, max_j = -1;\n            for (int j = 0; j < H; ++j)\n                for (int i = 0; i < W; ++i)\n                    if (comp[j][i] == c) {\n                        min_i = std::min(min_i, i); max_i = std::max(max_i, i);\n                        min_j = std::min(min_j, j); max_j = std::max(max_j, j);\n                    }\n            int lw = max_i - min_i + 3;\n            int lh = max_j - min_j + 3;\n            std::vector<std::vector<bool>> local(lh, std::vector<bool>(lw, false));\n            for (int j = min_j; j <= max_j; ++j)\n                for (int i = min_i; i <= max_i; ++i)\n                    if (comp[j][i] == c)\n                        local[j - min_j + 1][i - min_i + 1] = true;\n\n            // flood fill the outside from borders\n            std::vector<std::vector<bool>> vis_local(lh, std::vector<bool>(lw, false));\n            std::queue<std::pair<int,int>> q;\n            for (int y = 0; y < lh; ++y) {\n                if (!local[y][0]) { q.push({0, y}); vis_local[y][0] = true; }\n                if (!local[y][lw - 1]) { q.push({lw - 1, y}); vis_local[y][lw - 1] = true; }\n            }\n            for (int x = 0; x < lw; ++x) {\n                if (!local[0][x]) { q.push({x, 0}); vis_local[0][x] = true; }\n                if (!local[lh - 1][x]) { q.push({x, lh - 1}); vis_local[lh - 1][x] = true; }\n            }\n            while (!q.empty()) {\n                auto [cx, cy] = q.front(); q.pop();\n                for (int d = 0; d < 4; ++d) {\n                    int nx = cx + dx[d], ny = cy + dy[d];\n                    if (nx >= 0 && nx < lw && ny >= 0 && ny < lh &&\n                        !vis_local[ny][nx] && !local[ny][nx]) {\n                        vis_local[ny][nx] = true;\n                        q.push({nx, ny});\n                    }\n                }\n            }\n            // fill holes\n            for (int y = 0; y < lh; ++y)\n                for (int x = 0; x < lw; ++x)\n                    if (!vis_local[y][x] && !local[y][x])\n                        local[y][x] = true;\n\n            auto is_inside = [&](int i, int j) -> bool {\n                if (i < min_i || i > max_i || j < min_j || j > max_j) return false;\n                return local[j - min_j + 1][i - min_i + 1];\n            };\n\n            int cur_w = 0;\n            int cur_perim = 0;\n            for (int j = min_j; j <= max_j; ++j)\n                for (int i = min_i; i <= max_i; ++i)\n                    if (is_inside(i, j)) {\n                        cur_w += weight[j][i];\n                        if (!is_inside(i + 1, j)) ++cur_perim;\n                        if (!is_inside(i - 1, j)) ++cur_perim;\n                        if (!is_inside(i, j + 1)) ++cur_perim;\n                        if (!is_inside(i, j - 1)) ++cur_perim;\n                    }\n\n            if ((long long)cur_perim * S <= MAX_PERIMETER) {\n                int score = std::max(0, cur_w + 1);\n                if (score > best_score) {\n                    best_score = score;\n                    best_inside.assign(H, std::vector<bool>(W, false));\n                    for (int j = min_j; j <= max_j; ++j)\n                        for (int i = min_i; i <= max_i; ++i)\n                            if (is_inside(i, j))\n                                best_inside[j][i] = true;\n                }\n            }\n        }\n    }\n\n    // ---------- fallback ----------\n    if (best_score <= 0) {\n        int bx = x[0], by = y[0];\n        for (int i = 0; i < N; ++i) {\n            int px = x[i], py = y[i];\n            bool ok = true;\n            for (int j = N; j < 2 * N; ++j) {\n                if (x[j] >= px && x[j] <= px + 1 && y[j] >= py && y[j] <= py + 1) {\n                    ok = false;\n                    break;\n                }\n            }\n            if (ok) { bx = px; by = py; break; }\n        }\n        if (bx == 100000) bx = 99999;\n        if (by == 100000) by = 99999;\n        std::cout << \"4\\n\";\n        std::cout << bx << ' ' << by << '\\n';\n        std::cout << bx + 1 << ' ' << by << '\\n';\n        std::cout << bx + 1 << ' ' << by + 1 << '\\n';\n        std::cout << bx << ' ' << by + 1 << '\\n';\n        return 0;\n    }\n\n    // ---------- trace outer boundary ----------\n    struct Seg { int x1, y1, x2, y2; };\n    std::vector<Seg> segs;\n    segs.reserve(4 * W * H);\n    for (int j = 0; j < H; ++j)\n        for (int i = 0; i < W; ++i) {\n            if (!best_inside[j][i]) continue;\n            int x = i * S, y = j * S;\n            if (j == 0 || !best_inside[j - 1][i])\n                segs.push_back({x, y, x + S, y});\n            if (j == H - 1 || !best_inside[j + 1][i])\n                segs.push_back({x, y + S, x + S, y + S});\n            if (i == 0 || !best_inside[j][i - 1])\n                segs.push_back({x, y, x, y + S});\n            if (i == W - 1 || !best_inside[j][i + 1])\n                segs.push_back({x + S, y, x + S, y + S});\n        }\n\n    std::unordered_map<long long, std::vector<int>> vmap;\n    for (int idx = 0; idx < (int)segs.size(); ++idx) {\n        long long k1 = ((long long)segs[idx].x1 << 32) | segs[idx].y1;\n        long long k2 = ((long long)segs[idx].x2 << 32) | segs[idx].y2;\n        vmap[k1].push_back(idx);\n        vmap[k2].push_back(idx);\n    }\n\n    std::vector<std::pair<int,int>> poly;\n    int start_x = segs[0].x1, start_y = segs[0].y1;\n    poly.push_back({start_x, start_y});\n    int cur_x = segs[0].x2, cur_y = segs[0].y2;\n    poly.push_back({cur_x, cur_y});\n    int prev_seg = 0;\n    while (true) {\n        long long key = ((long long)cur_x << 32) | cur_y;\n        int next_seg = -1;\n        for (int sid : vmap[key]) {\n            if (sid != prev_seg) { next_seg = sid; break; }\n        }\n        if (next_seg == -1) break;\n        int nx, ny;\n        if (segs[next_seg].x1 == cur_x && segs[next_seg].y1 == cur_y) {\n            nx = segs[next_seg].x2;\n            ny = segs[next_seg].y2;\n        } else {\n            nx = segs[next_seg].x1;\n            ny = segs[next_seg].y1;\n        }\n        if (nx == start_x && ny == start_y) break;\n        poly.push_back({nx, ny});\n        cur_x = nx; cur_y = ny;\n        prev_seg = next_seg;\n    }\n\n    // remove collinear vertices\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        for (size_t i = 0; i < poly.size(); ++i) {\n            size_t prv = (i == 0) ? poly.size() - 1 : i - 1;\n            size_t nxt = (i + 1) % poly.size();\n            if (poly[prv].first == poly[i].first && poly[i].first == poly[nxt].first) {\n                poly.erase(poly.begin() + i);\n                changed = true;\n                break;\n            }\n            if (poly[prv].second == poly[i].second && poly[i].second == poly[nxt].second) {\n                poly.erase(poly.begin() + i);\n                changed = true;\n                break;\n            }\n        }\n    }\n\n    if (poly.size() < 4) {\n        std::cout << \"4\\n0 0\\n100000 0\\n100000 100000\\n0 100000\\n\";\n        return 0;\n    }\n\n    std::cout << poly.size() << '\\n';\n    for (auto [xx, yy] : poly)\n        std::cout << xx << ' ' << yy << '\\n';\n\n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <string>\n#include <utility>\n#include <random>\n#include <chrono>\nusing namespace std;\nusing namespace std::chrono;\n\n// ------------------------------------------------------------\nstruct PlacedRect {\n    int index;          // original index (0..N-1)\n    long long x, y;     // position\n    long long w, h;     // size after rotation\n    int rot;            // 0 or 1\n    char dir;           // 'U' or 'L'\n    int base;           // -1 or original index of reference\n};\n\nstruct Decision {\n    bool placed;\n    int rot;\n    char dir;\n    int base;\n};\n\n// ------------------------------------------------------------\npair<long long, long long> get_position(const vector<PlacedRect>& rects,\n                                         int base, char dir,\n                                         long long w, long long h) {\n    long long x, y;\n    if (dir == 'U') {\n        if (base == -1) {\n            x = 0;\n        } else {\n            auto it = find_if(rects.begin(), rects.end(),\n                              [base](const PlacedRect& r){ return r.index == base; });\n            x = it->x + it->w;\n        }\n        y = 0;\n        for (const auto& pr : rects) {\n            if (x + w > pr.x && pr.x + pr.w > x) {\n                if (pr.y + pr.h > y) y = pr.y + pr.h;\n            }\n        }\n    } else { // 'L'\n        if (base == -1) {\n            y = 0;\n        } else {\n            auto it = find_if(rects.begin(), rects.end(),\n                              [base](const PlacedRect& r){ return r.index == base; });\n            y = it->y + it->h;\n        }\n        x = 0;\n        for (const auto& pr : rects) {\n            if (y + h > pr.y && pr.y + pr.h > y) {\n                if (pr.x + pr.w > x) x = pr.x + pr.w;\n            }\n        }\n    }\n    return {x, y};\n}\n\n// ------------------------------------------------------------\nlong long evaluate_full(const vector<Decision>& dec,\n                         const vector<long long>& ew,\n                         const vector<long long>& eh) {\n    int N = (int)dec.size();\n    vector<PlacedRect> rects;\n    vector<bool> placed_flag(N, false);\n    long long W = 0, H = 0, sum_skip = 0;\n    for (int i = 0; i < N; ++i) {\n        if (!dec[i].placed) {\n            sum_skip += ew[i] + eh[i];\n            continue;\n        }\n        long long w = (dec[i].rot ? eh[i] : ew[i]);\n        long long h = (dec[i].rot ? ew[i] : eh[i]);\n        int base = dec[i].base;\n        if (base != -1 && !placed_flag[base]) {\n            base = -1;\n        }\n        auto [x, y] = get_position(rects, base, dec[i].dir, w, h);\n        rects.push_back({i, x, y, w, h, dec[i].rot, dec[i].dir, base});\n        placed_flag[i] = true;\n        W = max(W, x + w);\n        H = max(H, y + h);\n    }\n    return W + H + sum_skip;\n}\n\n// ------------------------------------------------------------\nvoid fix_base_consistency(vector<Decision>& dec) {\n    int N = (int)dec.size();\n    vector<bool> placed(N, false);\n    for (int i = 0; i < N; ++i) {\n        if (dec[i].placed) {\n            if (dec[i].base != -1 && !placed[dec[i].base]) {\n                dec[i].base = -1;\n            }\n            placed[i] = true;\n        }\n    }\n}\n\n// ------------------------------------------------------------\nlong long compute_est_skip(const vector<Decision>& dec,\n                           const vector<long long>& ew,\n                           const vector<long long>& eh) {\n    long long sk = 0;\n    int N = (int)dec.size();\n    for (int i = 0; i < N; ++i)\n        if (!dec[i].placed) sk += ew[i] + eh[i];\n    return sk;\n}\n\n// ------------------------------------------------------------\nvector<PlacedRect> decisions_to_rects(const vector<Decision>& dec,\n                                       const vector<long long>& ew,\n                                       const vector<long long>& eh) {\n    int N = (int)dec.size();\n    vector<PlacedRect> rects;\n    vector<bool> placed(N, false);\n    for (int i = 0; i < N; ++i) {\n        if (dec[i].placed) {\n            long long w = (dec[i].rot ? eh[i] : ew[i]);\n            long long h = (dec[i].rot ? ew[i] : eh[i]);\n            int base = dec[i].base;\n            if (base != -1 && !placed[base]) base = -1;\n            auto [x, y] = get_position(rects, base, dec[i].dir, w, h);\n            rects.push_back({i, x, y, w, h, dec[i].rot, dec[i].dir, base});\n            placed[i] = true;\n        }\n    }\n    return rects;\n}\n\n// ------------------------------------------------------------\n// A fast hill-climbing call (no time check).\nvoid hill_climb(vector<Decision>& cur_dec, long long& cur_best,\n                const vector<long long>& ew, const vector<long long>& eh,\n                int iterations, mt19937& rng) {\n    int N = (int)ew.size();\n    auto get_valid_bases = [&](const vector<Decision>& dec, int idx) -> vector<int> {\n        vector<int> valid = {-1};\n        for (int j = 0; j < idx; ++j)\n            if (dec[j].placed) valid.push_back(j);\n        return valid;\n    };\n    uniform_int_distribution<int> idx_dist(0, N - 1);\n    uniform_int_distribution<int> rot_dist(0, 1);\n    uniform_int_distribution<int> dir_dist(0, 1);\n\n    for (int iter = 0; iter < iterations; ++iter) {\n        int i = idx_dist(rng);\n        auto old_dec = cur_dec;\n        bool improved = false;\n\n        if (cur_dec[i].placed) {\n            // flip rotation\n            {\n                auto cand = cur_dec;\n                cand[i].rot = 1 - cur_dec[i].rot;\n                long long val = evaluate_full(cand, ew, eh);\n                if (val < cur_best) { cur_best = val; cur_dec = cand; improved = true; }\n            }\n            // flip direction\n            {\n                auto cand = cur_dec;\n                cand[i].dir = (cur_dec[i].dir == 'U' ? 'L' : 'U');\n                long long val = evaluate_full(cand, ew, eh);\n                if (val < cur_best) { cur_best = val; cur_dec = cand; improved = true; }\n            }\n            // change base\n            {\n                auto bases = get_valid_bases(cur_dec, i);\n                if (!bases.empty()) {\n                    uniform_int_distribution<int> base_dist(0, (int)bases.size() - 1);\n                    int nb = bases[base_dist(rng)];\n                    auto cand = cur_dec;\n                    cand[i].base = nb;\n                    long long val = evaluate_full(cand, ew, eh);\n                    if (val < cur_best) { cur_best = val; cur_dec = cand; improved = true; }\n                }\n            }\n            // change to skip\n            {\n                auto cand = cur_dec;\n                cand[i].placed = false;\n                long long val = evaluate_full(cand, ew, eh);\n                if (val < cur_best) { cur_best = val; cur_dec = cand; improved = true; }\n            }\n        } else {\n            // currently skipped \u2013 try to place\n            auto bases = get_valid_bases(cur_dec, i);\n            if (!bases.empty()) {\n                int rot = rot_dist(rng);\n                char dir = (dir_dist(rng) == 0 ? 'U' : 'L');\n                uniform_int_distribution<int> base_dist(0, (int)bases.size() - 1);\n                int nb = bases[base_dist(rng)];\n                auto cand = cur_dec;\n                cand[i].placed = true;\n                cand[i].rot = rot;\n                cand[i].dir = dir;\n                cand[i].base = nb;\n                long long val = evaluate_full(cand, ew, eh);\n                if (val < cur_best) { cur_best = val; cur_dec = cand; improved = true; }\n            }\n        }\n        if (!improved)\n            cur_dec = old_dec;\n    }\n}\n\n// ------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    auto start_time = steady_clock::now();\n\n    int N, T, sigma;\n    cin >> N >> T >> sigma;\n    vector<int> w_obs(N), h_obs(N);\n    for (int i = 0; i < N; ++i)\n        cin >> w_obs[i] >> h_obs[i];\n\n    // ----- 1. Measurement phase -----\n    vector<double> sum_w(N), sum_h(N);\n    vector<int> cnt(N);\n    for (int i = 0; i < N; ++i) {\n        sum_w[i] = w_obs[i];\n        sum_h[i] = h_obs[i];\n        cnt[i] = 1;\n    }\n\n    int measure_count = min(2 * N, T - 1);   // leave at least one turn for final\n    int rot0_num = min(N, measure_count);\n    int rot1_num = min(N, measure_count - rot0_num);\n\n    for (int i = 0; i < rot0_num; ++i) {\n        cout << 1 << \"\\n\" << i << \" 0 U -1\\n\" << flush;\n        long long Wp, Hp;\n        cin >> Wp >> Hp;\n        sum_w[i] += Wp; sum_h[i] += Hp; cnt[i]++;\n    }\n    for (int i = 0; i < rot1_num; ++i) {\n        cout << 1 << \"\\n\" << i << \" 1 U -1\\n\" << flush;\n        long long Wp, Hp;\n        cin >> Wp >> Hp;\n        sum_w[i] += Hp;   // rotated: measured H' approximates true w\n        sum_h[i] += Wp;   // measured W' approximates true h\n        cnt[i]++;\n    }\n\n    int turns_done = rot0_num + rot1_num;\n\n    vector<long long> ew(N), eh(N);\n    for (int i = 0; i < N; ++i) {\n        ew[i] = (long long)round(sum_w[i] / cnt[i]);\n        eh[i] = (long long)round(sum_h[i] / cnt[i]);\n    }\n\n    // ----- 2. Suffix sum for beam heuristic -----\n    vector<long long> suffix_sum(N + 1, 0);\n    for (int i = N - 1; i >= 0; --i)\n        suffix_sum[i] = suffix_sum[i + 1] + ew[i] + eh[i];\n\n    // ----- 3. Beam search -----\n    const int BEAM_WIDTH = 80;\n    struct State {\n        vector<PlacedRect> rects;\n        long long W, H, sum_skip;\n    };\n    vector<State> beam;\n    beam.push_back(State{ {}, 0LL, 0LL, 0LL });\n\n    for (int i = 0; i < N; ++i) {\n        vector<State> next;\n        next.reserve(BEAM_WIDTH * 30);\n\n        for (const auto& st : beam) {\n            // skip child\n            State skip_child = st;\n            skip_child.sum_skip += ew[i] + eh[i];\n            next.push_back(move(skip_child));\n\n            // place children\n            for (int rot = 0; rot <= 1; ++rot) {\n                long long w = (rot ? eh[i] : ew[i]);\n                long long h = (rot ? ew[i] : eh[i]);\n                for (char dir : {'U', 'L'}) {\n                    vector<int> bases = {-1};\n                    int sz = (int)st.rects.size();\n                    for (int k = max(0, sz - 5); k < sz; ++k)\n                        bases.push_back(st.rects[k].index);\n                    sort(bases.begin(), bases.end());\n                    bases.erase(unique(bases.begin(), bases.end()), bases.end());\n\n                    for (int base : bases) {\n                        auto [x, y] = get_position(st.rects, base, dir, w, h);\n                        long long nW = max(st.W, x + w);\n                        long long nH = max(st.H, y + h);\n                        State child = st;\n                        child.rects.push_back({i, x, y, w, h, rot, dir, base});\n                        child.W = nW;\n                        child.H = nH;\n                        next.push_back(move(child));\n                    }\n                }\n            }\n        }\n\n        // keep top BEAM_WIDTH according to heuristic (W+H+skip + suffix)\n        vector<pair<long long, int>> costs(next.size());\n        for (int j = 0; j < (int)next.size(); ++j) {\n            const auto& ns = next[j];\n            costs[j] = { ns.W + ns.H + ns.sum_skip + suffix_sum[i + 1], j };\n        }\n        sort(costs.begin(), costs.end());\n        beam.clear();\n        for (int j = 0; j < min(BEAM_WIDTH, (int)costs.size()); ++j)\n            beam.push_back(move(next[costs[j].second]));\n    }\n\n    // choose best complete state\n    long long best_cost = beam[0].W + beam[0].H + beam[0].sum_skip;\n    const State* best_state = &beam[0];\n    for (const auto& st : beam) {\n        long long cost = st.W + st.H + st.sum_skip;\n        if (cost < best_cost) {\n            best_cost = cost;\n            best_state = &st;\n        }\n    }\n\n    vector<Decision> base_decisions(N);\n    for (int i = 0; i < N; ++i)\n        base_decisions[i].placed = false;\n    for (const auto& pr : best_state->rects)\n        base_decisions[pr.index] = {true, pr.rot, pr.dir, pr.base};\n\n    // ----- 4. Hill climbing on the beam best -----\n    mt19937 rng(1234);\n    auto cur_dec = base_decisions;\n    long long cur_best = best_cost;\n    hill_climb(cur_dec, cur_best, ew, eh, 3000, rng);\n    fix_base_consistency(cur_dec);\n\n    // ----- 5. Generate extra candidates -----\n    int rem = T - turns_done;\n    int max_extra = min(20, max(0, rem - 1));  // leave at least one turn for main\n    vector<vector<Decision>> candidates;\n    vector<long long> est_skip_cand;\n    candidates.push_back(cur_dec);\n    est_skip_cand.push_back(compute_est_skip(cur_dec, ew, eh));\n\n    if (max_extra > 0) {\n        auto get_valid_bases = [&](const vector<Decision>& dec, int idx) -> vector<int> {\n            vector<int> valid = {-1};\n            for (int j = 0; j < idx; ++j)\n                if (dec[j].placed) valid.push_back(j);\n            return valid;\n        };\n        for (int k = 0; k < max_extra; ++k) {\n            auto dec = cur_dec;  // start from the hill-climbed best\n            // perturb: with 15% probability flip each rectangle's status/settings\n            for (int i = 0; i < N; ++i) {\n                if (rng() % 100 < 15) {\n                    if (dec[i].placed) {\n                        if (rng() % 2) {\n                            dec[i].placed = false;\n                        } else {\n                            dec[i].rot = rng() % 2;\n                            dec[i].dir = (rng() % 2 ? 'U' : 'L');\n                            auto bases = get_valid_bases(dec, i);\n                            if (!bases.empty())\n                                dec[i].base = bases[rng() % bases.size()];\n                        }\n                    } else {\n                        dec[i].placed = true;\n                        dec[i].rot = rng() % 2;\n                        dec[i].dir = (rng() % 2 ? 'U' : 'L');\n                        auto bases = get_valid_bases(dec, i);\n                        if (!bases.empty())\n                            dec[i].base = bases[rng() % bases.size()];\n                        else\n                            dec[i].placed = false;\n                    }\n                }\n            }\n            long long val = evaluate_full(dec, ew, eh);\n            hill_climb(dec, val, ew, eh, 200, rng);\n            fix_base_consistency(dec);\n            candidates.push_back(dec);\n            est_skip_cand.push_back(compute_est_skip(dec, ew, eh));\n        }\n    }\n\n    // ----- 6. Remaining turns: output candidates, track best measured -----\n    int best_cand_idx = 0;\n    long long best_meas = 1e18;\n    vector<long long> meas_scores(candidates.size(), -1);\n\n    for (int t = 0; t < rem; ++t) {\n        int idx = (t < (int)candidates.size()) ? t : best_cand_idx;\n        auto& dec = candidates[idx];\n        auto rects = decisions_to_rects(dec, ew, eh);\n        int n = (int)rects.size();\n        cout << n << \"\\n\";\n        for (const auto& pr : rects)\n            cout << pr.index << \" \" << pr.rot << \" \" << pr.dir << \" \" << pr.base << \"\\n\";\n        cout << flush;\n\n        long long Wp, Hp;\n        cin >> Wp >> Hp;\n        long long est_score = Wp + Hp + est_skip_cand[idx];\n        if (t < (int)candidates.size()) {\n            meas_scores[idx] = est_score;\n            if (est_score < best_meas) {\n                best_meas = est_score;\n                best_cand_idx = idx;\n            }\n        }\n        // if t >= candidates.size(), we just repeat the current best_idx, which may have been updated.\n    }\n\n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <stack>\n#include <ctime>\n#include <cmath>\n#include <cstdint>\n#include <random>\n\nusing namespace std;\n\n// fast random number generator\nuint32_t xor_state;\nvoid init_random() {\n    random_device rd;\n    xor_state = rd();\n    if(xor_state == 0) xor_state = 123456789;\n}\nuint32_t xorshift32() {\n    uint32_t x = xor_state;\n    x ^= x << 13;\n    x ^= x >> 17;\n    x ^= x << 5;\n    return xor_state = x;\n}\ninline double random_double() {\n    return (xorshift32() >> 8) / double(1 << 24);\n}\ninline int random_int(int n) {\n    return xorshift32() % n;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    init_random();\n\n    int N, M, H;\n    cin >> N >> M >> H;\n    vector<int> A(N);\n    for(int i=0; i<N; i++) cin >> A[i];\n    vector<vector<int>> adj(N);\n    for(int i=0; i<M; i++){\n        int u, v; cin >> u >> v;\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n    // skip coordinates\n    for(int i=0; i<N; i++){\n        int x, y; cin >> x >> y;\n    }\n\n    // state\n    vector<int> parent(N, -1);\n    vector<int> depth(N, 0);\n    vector<vector<int>> children(N);\n    vector<int> subtree_sum_A = A;\n    vector<int> subtree_max_depth(N, 0);\n    vector<int> root_of(N);\n    iota(root_of.begin(), root_of.end(), 0);\n\n    // greedy initialization (process vertices in descending A)\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int i, int j){ return A[i] > A[j]; });\n\n    for(int v : order){\n        if(parent[v] != -1) continue;\n        int best_u = -1;\n        int best_udepth = -1;\n        for(int u : adj[v]){\n            if(root_of[u] == v) continue;\n            int new_d = depth[u] + 1;\n            if(new_d + subtree_max_depth[v] <= H){\n                if(depth[u] > best_udepth){\n                    best_udepth = depth[u];\n                    best_u = u;\n                }\n            }\n        }\n        if(best_u != -1){\n            int delta = depth[best_u] + 1;\n            int new_root = root_of[best_u];\n            parent[v] = best_u;\n            children[best_u].push_back(v);\n            stack<int> st;\n            st.push(v);\n            while(!st.empty()){\n                int node = st.top(); st.pop();\n                depth[node] += delta;\n                root_of[node] = new_root;\n                for(int child : children[node]){\n                    st.push(child);\n                }\n            }\n            // update ancestors\n            vector<int> to_update;\n            int cur = best_u;\n            while(cur != -1){\n                to_update.push_back(cur);\n                cur = parent[cur];\n            }\n            sort(to_update.begin(), to_update.end(), [&](int a, int b){ return depth[a] > depth[b]; });\n            for(int node : to_update){\n                int sum = A[node];\n                int max_d = 0;\n                for(int child : children[node]){\n                    sum += subtree_sum_A[child];\n                    max_d = max(max_d, subtree_max_depth[child] + 1);\n                }\n                subtree_sum_A[node] = sum;\n                subtree_max_depth[node] = max_d;\n            }\n        }\n    }\n\n    // initial score\n    long long score = 0;\n    for(int i=0; i<N; i++){\n        score += (depth[i] + 1LL) * A[i];\n    }\n    long long best_score = score;\n    vector<int> best_parent = parent;\n\n    // helper functions for SA\n    auto is_descendant = [&](int anc, int desc) -> bool {\n        if(depth[desc] < depth[anc]) return false;\n        int cur = desc;\n        while(cur != -1 && depth[cur] > depth[anc]){\n            cur = parent[cur];\n        }\n        return cur == anc;\n    };\n\n    auto apply_move = [&](int v, int new_p, int delta) {\n        int old_p = parent[v];\n        int old_d = depth[v];\n        int new_d = (new_p == -1) ? 0 : depth[new_p] + 1;\n        int depth_delta = new_d - old_d;\n        // remove from old parent\n        if(old_p != -1){\n            auto it = find(children[old_p].begin(), children[old_p].end(), v);\n            if(it != children[old_p].end()) children[old_p].erase(it);\n        }\n        // add to new parent\n        if(new_p != -1){\n            children[new_p].push_back(v);\n        }\n        parent[v] = new_p;\n        // update depths in subtree of v\n        if(depth_delta != 0){\n            stack<int> st;\n            st.push(v);\n            while(!st.empty()){\n                int node = st.top(); st.pop();\n                depth[node] += depth_delta;\n                for(int child : children[node]){\n                    st.push(child);\n                }\n            }\n        }\n        // update subtree properties for affected ancestors\n        vector<int> to_update;\n        if(old_p != -1){\n            int cur = old_p;\n            while(cur != -1){\n                to_update.push_back(cur);\n                cur = parent[cur];\n            }\n        }\n        if(new_p != -1){\n            int cur = new_p;\n            while(cur != -1){\n                to_update.push_back(cur);\n                cur = parent[cur];\n            }\n        }\n        sort(to_update.begin(), to_update.end(), [&](int a, int b){ return depth[a] > depth[b]; });\n        to_update.erase(unique(to_update.begin(), to_update.end()), to_update.end());\n        for(int node : to_update){\n            int sum = A[node];\n            int max_d = 0;\n            for(int child : children[node]){\n                sum += subtree_sum_A[child];\n                max_d = max(max_d, subtree_max_depth[child] + 1);\n            }\n            subtree_sum_A[node] = sum;\n            subtree_max_depth[node] = max_d;\n        }\n    };\n\n    // simulated annealing\n    clock_t start_clock = clock();\n    double time_limit_sec = 1.95;\n    double T_start = 20000.0;\n    double T_end = 0.1;\n    double T = T_start;\n    int iter_count = 0;\n\n    while(true){\n        if(iter_count % 1000 == 0){\n            double elapsed = double(clock() - start_clock) / CLOCKS_PER_SEC;\n            if(elapsed >= time_limit_sec) break;\n            T = T_start * pow(T_end / T_start, elapsed / time_limit_sec);\n        }\n        iter_count++;\n        bool moved = false;\n        for(int attempt = 0; attempt < 5; attempt++){\n            int v = random_int(N);\n            int old_p = parent[v];\n            int u;\n            if(old_p != -1 && random_double() < 0.1){\n                u = -1;  // make root\n            } else {\n                if(adj[v].empty()) continue;\n                u = adj[v][random_int(adj[v].size())];\n            }\n            if(u == old_p) continue;\n            int new_d;\n            if(u == -1){\n                new_d = 0;\n            } else {\n                if(is_descendant(v, u) || is_descendant(u, v)) continue;\n                new_d = depth[u] + 1;\n                if(new_d + subtree_max_depth[v] > H) continue;\n            }\n            int delta = (new_d - depth[v]) * subtree_sum_A[v];\n            if(delta >= 0 || random_double() < exp(delta / T)){\n                apply_move(v, u, delta);\n                score += delta;\n                moved = true;\n                if(score > best_score){\n                    best_score = score;\n                    best_parent = parent;\n                }\n                break;\n            }\n        }\n    }\n\n    for(int i=0; i<N; i++){\n        cout << best_parent[i] << (i==N-1 ? \"\\n\" : \" \");\n    }\n\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <cstring>\nusing namespace std;\n\nconst int N = 20;\nconst int INF = 1e9;\nconst int MAX_K = 2 * N; // at most 40\n\nint K;\npair<int,int> oni[MAX_K];\nbool fuku[N][N];\nint L_max[N], R_min[N], U_max[N], D_min[N];\nint fea[MAX_K][4]; // feasible directions, terminated by -1\n\n// ---------- evaluation ----------\nint evaluate(const vector<int>& dir, bool allow_oneway) {\n    int L[N] = {0}, R[N] = {0};\n    for (int k = 0; k < K; ++k) {\n        int d = dir[k];\n        if (d <= 1) {\n            int i = oni[k].first, j = oni[k].second;\n            if (d == 0) {\n                if (j+1 > L[i]) L[i] = j+1;\n            } else {\n                if (N-j > R[i]) R[i] = N-j;\n            }\n        }\n    }\n    int row_shift[N] = {0};\n    int cost = 0;\n    for (int i = 0; i < N; ++i) {\n        if (L[i] > 0 && R[i] > 0) {\n            cost += 2 * (L[i] + R[i]);\n            row_shift[i] = 0;\n        } else if (L[i] > 0) {\n            int safe = L_max[i] + 1;\n            if (allow_oneway && L[i] <= safe) {\n                cost += L[i];\n                row_shift[i] = -L[i];\n            } else {\n                cost += 2 * L[i];\n                row_shift[i] = 0;\n            }\n        } else if (R[i] > 0) {\n            int safe = N - R_min[i];\n            if (allow_oneway && R[i] <= safe) {\n                cost += R[i];\n                row_shift[i] = R[i];\n            } else {\n                cost += 2 * R[i];\n                row_shift[i] = 0;\n            }\n        }\n    }\n    // shifted fuku\n    bool fuku_new[N][N] = {false};\n    for (int i = 0; i < N; ++i) {\n        int sh = row_shift[i];\n        for (int j = 0; j < N; ++j) {\n            if (fuku[i][j]) {\n                int nj = j + sh;\n                if (nj < 0 || nj >= N) return INF;\n                fuku_new[i][nj] = true;\n            }\n        }\n    }\n    // column oni after row shifts\n    int col_oni[N][N];\n    int col_sz[N] = {0};\n    for (int k = 0; k < K; ++k) {\n        int d = dir[k];\n        if (d >= 2) {\n            int i = oni[k].first, j = oni[k].second;\n            int sh = row_shift[i];\n            int nj = j + sh;\n            if (nj < 0 || nj >= N) continue;\n            int pos = col_sz[nj];\n            col_oni[nj][pos] = i;\n            col_sz[nj] = pos + 1;\n        }\n    }\n    for (int j = 0; j < N; ++j)\n        if (col_sz[j] > 1) sort(col_oni[j], col_oni[j] + col_sz[j]);\n\n    for (int j = 0; j < N; ++j) {\n        int m = col_sz[j];\n        if (m == 0) continue;\n        int max_i = col_oni[j][m-1];\n        int min_i = col_oni[j][0];\n        int min_f = N, max_f = -1;\n        for (int r = 0; r < N; ++r) if (fuku_new[r][j]) { min_f = r; break; }\n        for (int r = N-1; r >= 0; --r) if (fuku_new[r][j]) { max_f = r; break; }\n        bool up_ok = (max_i < min_f);\n        bool down_ok = (min_i > max_f);\n        if (allow_oneway && up_ok) {\n            cost += max_i + 1;\n        } else if (allow_oneway && down_ok) {\n            cost += N - min_i;\n        } else {\n            int U_safe = min_f;\n            int D_safe = (max_f == -1) ? N : N - 1 - max_f;\n            int suf[N+1];\n            suf[m] = 0;\n            for (int idx = m-1; idx >= 0; --idx)\n                suf[idx] = max(suf[idx+1], N - col_oni[j][idx]);\n            int best = INF;\n            for (int U = 0; U <= U_safe; ++U) {\n                int idx = lower_bound(col_oni[j], col_oni[j] + m, U) - col_oni[j];\n                int D = suf[idx];\n                if (D <= D_safe) {\n                    int cst = 2 * (U + D);\n                    if (cst < best) best = cst;\n                }\n            }\n            if (best >= INF) return INF;\n            cost += best;\n        }\n    }\n    return cost;\n}\n\n// ---------- output generation ----------\nvoid output_solution(const vector<int>& dir, bool allow_oneway) {\n    int L[N] = {0}, R[N] = {0};\n    for (int k = 0; k < K; ++k) {\n        int d = dir[k];\n        if (d <= 1) {\n            int i = oni[k].first, j = oni[k].second;\n            if (d == 0) L[i] = max(L[i], j+1);\n            else R[i] = max(R[i], N-j);\n        }\n    }\n    int row_shift[N] = {0};\n    vector<pair<char,int>> ops;\n    for (int i = 0; i < N; ++i) {\n        if (L[i] > 0 && R[i] > 0) {\n            for (int t = 0; t < L[i]; ++t) ops.push_back({'L', i});\n            for (int t = 0; t < L[i]; ++t) ops.push_back({'R', i});\n            for (int t = 0; t < R[i]; ++t) ops.push_back({'R', i});\n            for (int t = 0; t < R[i]; ++t) ops.push_back({'L', i});\n            row_shift[i] = 0;\n        } else if (L[i] > 0) {\n            int safe = L_max[i] + 1;\n            if (allow_oneway && L[i] <= safe) {\n                for (int t = 0; t < L[i]; ++t) ops.push_back({'L', i});\n                row_shift[i] = -L[i];\n            } else {\n                for (int t = 0; t < L[i]; ++t) ops.push_back({'L', i});\n                for (int t = 0; t < L[i]; ++t) ops.push_back({'R', i});\n                row_shift[i] = 0;\n            }\n        } else if (R[i] > 0) {\n            int safe = N - R_min[i];\n            if (allow_oneway && R[i] <= safe) {\n                for (int t = 0; t < R[i]; ++t) ops.push_back({'R', i});\n                row_shift[i] = R[i];\n            } else {\n                for (int t = 0; t < R[i]; ++t) ops.push_back({'R', i});\n                for (int t = 0; t < R[i]; ++t) ops.push_back({'L', i});\n                row_shift[i] = 0;\n            }\n        }\n    }\n    // shifted fuku\n    bool fuku_new[N][N] = {false};\n    for (int i = 0; i < N; ++i) {\n        int sh = row_shift[i];\n        for (int j = 0; j < N; ++j) if (fuku[i][j]) fuku_new[i][j+sh] = true;\n    }\n    // column oni after shift\n    int col_oni[N][N];\n    int col_sz[N] = {0};\n    for (int k = 0; k < K; ++k) {\n        int d = dir[k];\n        if (d >= 2) {\n            int i = oni[k].first, j = oni[k].second;\n            int sh = row_shift[i];\n            int nj = j + sh;\n            if (nj < 0 || nj >= N) continue;\n            int idx = col_sz[nj];\n            col_oni[nj][idx] = i;\n            col_sz[nj] = idx + 1;\n        }\n    }\n    for (int j = 0; j < N; ++j) if (col_sz[j] > 1) sort(col_oni[j], col_oni[j] + col_sz[j]);\n    for (int j = 0; j < N; ++j) {\n        int m = col_sz[j];\n        if (m == 0) continue;\n        int max_i = col_oni[j][m-1];\n        int min_i = col_oni[j][0];\n        int min_f = N, max_f = -1;\n        for (int r = 0; r < N; ++r) if (fuku_new[r][j]) { min_f = r; break; }\n        for (int r = N-1; r >= 0; --r) if (fuku_new[r][j]) { max_f = r; break; }\n        bool up_ok = (max_i < min_f);\n        bool down_ok = (min_i > max_f);\n        if (allow_oneway && up_ok) {\n            int len = max_i + 1;\n            for (int t = 0; t < len; ++t) ops.push_back({'U', j});\n        } else if (allow_oneway && down_ok) {\n            int len = N - min_i;\n            for (int t = 0; t < len; ++t) ops.push_back({'D', j});\n        } else {\n            int U_safe = min_f;\n            int D_safe = (max_f == -1) ? N : N - 1 - max_f;\n            int suf[N+1];\n            suf[m] = 0;\n            for (int idx = m-1; idx >= 0; --idx) suf[idx] = max(suf[idx+1], N - col_oni[j][idx]);\n            int best = INF, best_U = 0, best_D = 0;\n            for (int U = 0; U <= U_safe; ++U) {\n                int idx = lower_bound(col_oni[j], col_oni[j] + m, U) - col_oni[j];\n                int D = suf[idx];\n                if (D <= D_safe) {\n                    int cst = 2 * (U + D);\n                    if (cst < best) { best = cst; best_U = U; best_D = D; }\n                }\n            }\n            for (int t = 0; t < best_U; ++t) ops.push_back({'U', j});\n            for (int t = 0; t < best_U; ++t) ops.push_back({'D', j});\n            for (int t = 0; t < best_D; ++t) ops.push_back({'D', j});\n            for (int t = 0; t < best_D; ++t) ops.push_back({'U', j});\n        }\n    }\n    for (auto [c, p] : ops) cout << c << ' ' << p << '\\n';\n}\n\n// ---------- main ----------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> n;\n    vector<string> C(n);\n    for (int i = 0; i < n; ++i) cin >> C[i];\n\n    // init board\n    K = 0;\n    memset(fuku, 0, sizeof fuku);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (C[i][j] == 'x') oni[K++] = {i, j};\n            else if (C[i][j] == 'o') fuku[i][j] = true;\n        }\n    }\n    for (int i = 0; i < N; ++i) {\n        L_max[i] = N-1;\n        for (int j = 0; j < N; ++j) if (fuku[i][j]) { L_max[i] = j-1; break; }\n        R_min[i] = 0;\n        for (int j = N-1; j >= 0; --j) if (fuku[i][j]) { R_min[i] = j+1; break; }\n    }\n    for (int j = 0; j < N; ++j) {\n        U_max[j] = N-1;\n        for (int i = 0; i < N; ++i) if (fuku[i][j]) { U_max[j] = i-1; break; }\n        D_min[j] = 0;\n        for (int i = N-1; i >= 0; --i) if (fuku[i][j]) { D_min[j] = i+1; break; }\n    }\n    // feasible directions per Oni\n    for (int k = 0; k < K; ++k) {\n        int i = oni[k].first, j = oni[k].second;\n        int idx = 0;\n        if (j <= L_max[i]) fea[k][idx++] = 0;\n        if (j >= R_min[i]) fea[k][idx++] = 1;\n        if (i <= U_max[j]) fea[k][idx++] = 2;\n        if (i >= D_min[j]) fea[k][idx++] = 3;\n        fea[k][idx] = -1;\n    }\n\n    // ---------- baseline: symmetric only, min-distance greedy ----------\n    mt19937 rng(random_device{}());\n    auto dist = [&](int k, int d) {\n        int i = oni[k].first, j = oni[k].second;\n        if (d == 0) return j+1;\n        if (d == 1) return N - j;\n        if (d == 2) return i+1;\n        return N - i;\n    };\n    auto greedy_dir = [&]() {\n        vector<int> dir(K);\n        for (int k = 0; k < K; ++k) {\n            const int* f = fea[k];\n            int best_d = f[0], best_dist = dist(k, f[0]);\n            for (int t = 1; f[t] != -1; ++t) {\n                int d = f[t];\n                int dd = dist(k, d);\n                if (dd < best_dist) { best_dist = dd; best_d = d; }\n            }\n            dir[k] = best_d;\n        }\n        return dir;\n    };\n\n    vector<int> base_dir = greedy_dir();\n    int base_cost = evaluate(base_dir, false);\n    {\n        // try a few random min-distance picks to improve baseline\n        uniform_int_distribution<int> coin(0,1);\n        for (int rep = 0; rep < 20; ++rep) {\n            vector<int> dir(K);\n            for (int k = 0; k < K; ++k) {\n                const int* f = fea[k];\n                int cnt = 0; while (f[cnt] != -1) ++cnt;\n                // choose uniformly among those with min distance\n                int best_d = f[0], best_dist = dist(k, f[0]);\n                vector<int> cand = {f[0]};\n                for (int t = 1; t < cnt; ++t) {\n                    int d = f[t];\n                    int dd = dist(k, d);\n                    if (dd < best_dist) { best_dist = dd; best_d = d; cand.clear(); cand.push_back(d); }\n                    else if (dd == best_dist) cand.push_back(d);\n                }\n                dir[k] = cand[rng() % cand.size()];\n            }\n            int cst = evaluate(dir, false);\n            if (cst < base_cost) { base_cost = cst; base_dir = dir; }\n        }\n    }\n\n    vector<int> best_dir = base_dir;\n    int best_cost = base_cost;\n    bool best_allow_oneway = false;\n\n    // ---------- optimization with one-way allowed ----------\n    uniform_real_distribution<double> dist01(0.0, 1.0);\n    auto start_total = chrono::steady_clock::now();\n    double time_limit = 1.95;\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - start_total).count() >= time_limit) break;\n\n        // random initial direction assignment (feasible)\n        vector<int> cur_dir(K);\n        for (int k = 0; k < K; ++k) {\n            const int* f = fea[k];\n            int cnt = 0; while (f[cnt] != -1) ++cnt;\n            cur_dir[k] = f[rng() % cnt];\n        }\n        int cur_cost = evaluate(cur_dir, true);\n        if (cur_cost >= INF) continue;\n\n        // hill-climb\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            for (int k = 0; k < K; ++k) {\n                const int* f = fea[k];\n                int cnt = 0; while (f[cnt] != -1) ++cnt;\n                if (cnt <= 1) continue;\n                int old_d = cur_dir[k];\n                for (int t = 0; t < cnt; ++t) {\n                    int nd = f[t];\n                    if (nd == old_d) continue;\n                    cur_dir[k] = nd;\n                    int new_cost = evaluate(cur_dir, true);\n                    if (new_cost < cur_cost) {\n                        cur_cost = new_cost;\n                        improved = true;\n                        break;\n                    }\n                }\n                if (improved) break;\n                cur_dir[k] = old_d;\n            }\n        }\n        if (cur_cost < best_cost) {\n            best_cost = cur_cost;\n            best_dir = cur_dir;\n            best_allow_oneway = true;\n        }\n\n        // SA\n        double T = 2.0;\n        while (true) {\n            auto now2 = chrono::steady_clock::now();\n            if (chrono::duration<double>(now2 - start_total).count() >= time_limit) break;\n            for (int step = 0; step < 80; ++step) {\n                int k = rng() % K;\n                const int* f = fea[k];\n                int cnt = 0; while (f[cnt] != -1) ++cnt;\n                if (cnt <= 1) continue;\n                int old_d = cur_dir[k];\n                int nd = f[rng() % cnt];\n                if (nd == old_d) continue;\n                cur_dir[k] = nd;\n                int new_cost = evaluate(cur_dir, true);\n                if (new_cost >= INF) { cur_dir[k] = old_d; continue; }\n                int delta = new_cost - cur_cost;\n                if (delta <= 0 || dist01(rng) < exp(-delta / T)) {\n                    cur_cost = new_cost;\n                    if (cur_cost < best_cost) {\n                        best_cost = cur_cost;\n                        best_dir = cur_dir;\n                        best_allow_oneway = true;\n                    }\n                } else {\n                    cur_dir[k] = old_d;\n                }\n            }\n            T *= 0.99;\n            if (T < 0.01) break;\n        }\n    }\n\n    output_solution(best_dir, best_allow_oneway);\n    return 0;\n}","ahc044":"#include <iostream>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n#include <cstring>\n#include <random>\n#include <vector>\nusing namespace std;\n\nconst int N = 100;\nconst int L = 500000;\nint T[N];\n\n// fast simulation: we need this many times, keep it simple\nint real_error(const int a[N], const int b[N]) {\n    int t[N] = {0};\n    int cur = 0;\n    t[0] = 1;\n    for (int step = 1; step < L; ++step) {\n        cur = (t[cur] & 1) ? a[cur] : b[cur];\n        t[cur]++;\n    }\n    int err = 0;\n    for (int i = 0; i < N; ++i) {\n        int diff = t[i] - T[i];\n        if (diff < 0) diff = -diff;\n        err += diff;\n    }\n    return err;\n}\n\n// surrogate: stationary distribution of the random walk (a_i and b_i with equal probability)\ndouble surrogate_error(const int a[N], const int b[N]) {\n    double pi[N], new_pi[N];\n    for (int i = 0; i < N; ++i) pi[i] = 1.0 / N;\n    const int max_iter = 100;\n    for (int iter = 0; iter < max_iter; ++iter) {\n        for (int i = 0; i < N; ++i) new_pi[i] = 0.0;\n        for (int i = 0; i < N; ++i) {\n            if (a[i] == b[i]) {\n                new_pi[a[i]] += pi[i];\n            } else {\n                new_pi[a[i]] += pi[i] * 0.5;\n                new_pi[b[i]] += pi[i] * 0.5;\n            }\n        }\n        for (int i = 0; i < N; ++i) pi[i] = new_pi[i];\n    }\n    double err = 0.0;\n    for (int i = 0; i < N; ++i) err += fabs(pi[i] * L - T[i]);\n    return err;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    int N_in, L_in;\n    cin >> N_in >> L_in;\n    for (int i = 0; i < N; ++i) cin >> T[i];\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto rand_int = [&](int max) { return uniform_int_distribution<int>(0, max-1)(rng); };\n    auto rand_double = [&]() { return uniform_real_distribution<double>(0.0, 1.0)(rng); };\n\n    // ---------- greedy initial solution (approximate balance) ----------\n    vector<int> caps(N, 0);\n    for (int i = 0; i < N; ++i) caps[i] = 2 * T[i];\n    vector<pair<int,int>> items; // (weight, node_i)\n    for (int i = 0; i < N; ++i) {\n        items.emplace_back(T[i], i);\n        items.emplace_back(T[i], i);\n    }\n    sort(items.begin(), items.end(), greater<pair<int,int>>());\n\n    int init_a[N], init_b[N];\n    for (int i = 0; i < N; ++i) init_a[i] = init_b[i] = -1;\n\n    for (auto &p : items) {\n        int w = p.first;\n        int i = p.second;\n        int best_j = 0;\n        int best_cap = -1;\n        for (int j = 0; j < N; ++j) {\n            if (caps[j] > best_cap) {\n                best_cap = caps[j];\n                best_j = j;\n            }\n        }\n        if (init_a[i] == -1) init_a[i] = best_j;\n        else init_b[i] = best_j;\n        caps[best_j] -= w;\n    }\n    for (int i = 0; i < N; ++i) {\n        if (init_a[i] == -1) init_a[i] = i;\n        if (init_b[i] == -1) init_b[i] = i;\n    }\n\n    int best_a[N], best_b[N];\n    memcpy(best_a, init_a, sizeof(best_a));\n    memcpy(best_b, init_b, sizeof(best_b));\n    int best_err = real_error(best_a, best_b);\n\n    // fallback: if greedy yields huge error, start from a simple cycle\n    if (best_err > 1000000) {\n        for (int i = 0; i < N; ++i) {\n            best_a[i] = (i + 1) % N;\n            best_b[i] = (i + 1) % N;\n        }\n        best_err = real_error(best_a, best_b);\n    }\n\n    int cur_a[N], cur_b[N];\n    memcpy(cur_a, best_a, sizeof(cur_a));\n    memcpy(cur_b, best_b, sizeof(cur_b));\n    int cur_real_err = best_err;\n    double cur_surr_err = surrogate_error(cur_a, cur_b);\n    double best_surr_err = cur_surr_err;\n\n    auto start = chrono::steady_clock::now();\n    double elapsed = 0.0;\n    const double time_limit_surr = 1.3;\n    const double time_limit_total = 1.95;\n\n    // ---------- Stage 1: Surrogate SA ----------\n    double temp_surr = 200.0;\n    double temp_surr_end = 0.1;\n    int iter = 0;\n    while (true) {\n        if (iter % 100 == 0) {\n            auto now = chrono::steady_clock::now();\n            elapsed = chrono::duration<double>(now - start).count();\n            if (elapsed > time_limit_surr) break;\n            double progress = elapsed / time_limit_surr;\n            temp_surr = 200.0 * pow(temp_surr_end / 200.0, progress);\n        }\n        int type = rand_int(10);\n        int i = rand_int(N);\n        int old_a = cur_a[i], old_b = cur_b[i];\n        if (type < 4) {\n            cur_a[i] = rand_int(N);\n        } else if (type < 8) {\n            cur_b[i] = rand_int(N);\n        } else if (type == 8) {\n            swap(cur_a[i], cur_b[i]);\n        } else {\n            cur_a[i] = rand_int(N);\n            cur_b[i] = rand_int(N);\n        }\n        double new_surr_err = surrogate_error(cur_a, cur_b);\n        double delta = new_surr_err - cur_surr_err;\n        bool accepted = false;\n        if (delta <= 0) {\n            accepted = true;\n        } else if (rand_double() < exp(-delta / temp_surr)) {\n            accepted = true;\n        }\n        if (accepted) {\n            cur_surr_err = new_surr_err;\n            if (cur_surr_err < best_surr_err) {\n                best_surr_err = cur_surr_err;\n                int real_err = real_error(cur_a, cur_b);\n                if (real_err < best_err) {\n                    best_err = real_err;\n                    memcpy(best_a, cur_a, sizeof(cur_a));\n                    memcpy(best_b, cur_b, sizeof(cur_b));\n                }\n            }\n        } else {\n            cur_a[i] = old_a;\n            cur_b[i] = old_b;\n        }\n        ++iter;\n    }\n\n    // restore best found\n    memcpy(cur_a, best_a, sizeof(cur_a));\n    memcpy(cur_b, best_b, sizeof(cur_b));\n    cur_real_err = best_err;\n\n    // ---------- Stage 2: Real SA ----------\n    double temp_real = max(cur_real_err * 0.25, 10.0);\n    double temp_real_end = 0.1;\n    iter = 0;\n    while (true) {\n        if (iter % 10 == 0) {\n            auto now = chrono::steady_clock::now();\n            elapsed = chrono::duration<double>(now - start).count();\n            if (elapsed > time_limit_total) break;\n            double progress = max(0.0, min(1.0, (elapsed - time_limit_surr) / (time_limit_total - time_limit_surr)));\n            temp_real = max(cur_real_err * 0.25, 10.0) * pow(temp_real_end / max(cur_real_err * 0.25, 10.0), progress);\n        }\n        int type = rand_int(10);\n        int i = rand_int(N);\n        int old_a = cur_a[i], old_b = cur_b[i];\n        if (type < 4) {\n            cur_a[i] = rand_int(N);\n        } else if (type < 8) {\n            cur_b[i] = rand_int(N);\n        } else if (type == 8) {\n            swap(cur_a[i], cur_b[i]);\n        } else {\n            cur_a[i] = rand_int(N);\n            cur_b[i] = rand_int(N);\n        }\n        int new_err = real_error(cur_a, cur_b);\n        int delta = new_err - cur_real_err;\n        bool accepted = false;\n        if (delta <= 0) {\n            accepted = true;\n        } else if (rand_double() < exp(-delta / temp_real)) {\n            accepted = true;\n        }\n        if (accepted) {\n            cur_real_err = new_err;\n            if (new_err < best_err) {\n                best_err = new_err;\n                memcpy(best_a, cur_a, sizeof(cur_a));\n                memcpy(best_b, cur_b, sizeof(cur_b));\n            }\n        } else {\n            cur_a[i] = old_a;\n            cur_b[i] = old_b;\n        }\n        ++iter;\n        if (best_err == 0) break;\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << best_a[i] << \" \" << best_b[i] << \"\\n\";\n    }\n\n    return 0;\n}","ahc045":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n#include <cstdint>\n#include <limits>\n#include <chrono>\n#include <random>\n#include <tuple>\n#include <functional>\n\nusing namespace std;\nusing namespace chrono;\n\nstruct DSU {\n    vector<int> parent;\n    DSU(int n) { parent.assign(n, -1); }\n    int find(int x) { return parent[x] < 0 ? x : parent[x] = find(parent[x]); }\n    bool unite(int x, int y) {\n        x = find(x); y = find(y);\n        if (x == y) return false;\n        if (parent[x] > parent[y]) swap(x, y);\n        parent[x] += parent[y];\n        parent[y] = x;\n        return true;\n    }\n};\n\nint N, M, Q, L, W;\nint q_used = 0;\nvector<int> cx, cy;\nvector<vector<double>> gdist;\nvector<tuple<double, int, int>> global_edges;   // (est_dist, u, v)\n\n// ---------- query ----------\nvector<pair<int, int>> query_subset(const vector<int>& C) {\n    if (q_used >= Q) return {};\n    ++q_used;\n    int l = (int)C.size();\n    cout << \"? \" << l;\n    for (int c : C) cout << ' ' << c;\n    cout << endl;\n    vector<pair<int, int>> res(l - 1);\n    for (int i = 0; i < l - 1; ++i) cin >> res[i].first >> res[i].second;\n    return res;\n}\n\n// ---------- Prim's MST cost (fast for moderate sizes) ----------\ndouble mst_cost_prim(const vector<int>& cities) {\n    int k = (int)cities.size();\n    if (k <= 1) return 0.0;\n    vector<double> minD(k, 1e18);\n    vector<bool> in(k, false);\n    minD[0] = 0.0;\n    double total = 0.0;\n    for (int i = 0; i < k; ++i) {\n        int u = -1;\n        double best = 1e18;\n        for (int j = 0; j < k; ++j) {\n            if (!in[j] && minD[j] < best) { best = minD[j]; u = j; }\n        }\n        if (u < 0) break;\n        in[u] = true;\n        total += minD[u];\n        for (int v = 0; v < k; ++v) {\n            if (!in[v]) {\n                double d = gdist[cities[u]][cities[v]];\n                if (d < minD[v]) minD[v] = d;\n            }\n        }\n    }\n    return total;\n}\n\n// ---------- evaluate total MST cost of a contiguous partition ----------\ndouble evaluate_partition(const vector<int>& order, const vector<int>& G,\n                          vector<int>& group_of, vector<int>& local_id) {\n    double total = 0.0;\n    vector<DSU> dsus; dsus.reserve(M);\n    for (int i = 0; i < M; ++i) dsus.emplace_back(G[i]);\n    vector<int> edge_cnt(M, 0);\n    int cur = 0;\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < G[i]; ++j) {\n            int city = order[cur + j];\n            group_of[city] = i;\n            local_id[city] = j;\n        }\n        cur += G[i];\n    }\n    for (auto& [d, u, v] : global_edges) {\n        int gu = group_of[u], gv = group_of[v];\n        if (gu != gv) continue;\n        if (edge_cnt[gu] == G[gu] - 1) continue;\n        int lu = local_id[u], lv = local_id[v];\n        if (dsus[gu].unite(lu, lv)) {\n            total += d;\n            ++edge_cnt[gu];\n            if (edge_cnt[gu] == G[gu] - 1) {\n                bool done = true;\n                for (int i = 0; i < M; ++i)\n                    if (edge_cnt[i] < G[i] - 1) { done = false; break; }\n                if (done) break;\n            }\n        }\n    }\n    return total;\n}\n\n// ---------- global order heuristics ----------\n\n// double\u2011MST TSP\nvector<int> double_mst_tsp() {\n    DSU dsu(N);\n    vector<vector<int>> tree(N);\n    for (auto& [d, u, v] : global_edges) {\n        if (dsu.unite(u, v)) {\n            tree[u].push_back(v);\n            tree[v].push_back(u);\n        }\n    }\n    vector<int> path; path.reserve(N);\n    vector<bool> vis(N, false);\n    function<void(int)> dfs = [&](int u) {\n        vis[u] = true;\n        path.push_back(u);\n        for (int v : tree[u]) if (!vis[v]) dfs(v);\n    };\n    dfs(0);\n    // short 2\u2011opt\n    auto t0 = steady_clock::now();\n    auto elapsed = [&]() { return duration<double>(steady_clock::now() - t0).count(); };\n    auto dist = [&](int a, int b) { return gdist[a][b]; };\n    int n = N;\n    bool improved = true;\n    while (improved && elapsed() < 0.35) {\n        improved = false;\n        for (int i = 0; i < n - 1; ++i) {\n            for (int j = i + 2; j < n - 1; ++j) {\n                if (elapsed() > 0.35) break;\n                int a = path[i], b = path[i + 1], c = path[j], d_ = path[j + 1];\n                double old = dist(a, b) + dist(c, d_);\n                double nw  = dist(a, c) + dist(b, d_);\n                if (nw + 1e-9 < old) {\n                    reverse(path.begin() + i + 1, path.begin() + j + 1);\n                    improved = true;\n                }\n            }\n        }\n    }\n    return path;\n}\n\n// NN TSP from start city\nvector<int> nn_tsp(int start) {\n    vector<int> path(N);\n    path[0] = start;\n    vector<bool> used(N, false);\n    used[start] = true;\n    for (int i = 1; i < N; ++i) {\n        int last = path[i - 1];\n        int best = -1;\n        double bestd = 1e18;\n        for (int j = 0; j < N; ++j) {\n            if (used[j]) continue;\n            double d = gdist[last][j];\n            if (d < bestd) { bestd = d; best = j; }\n        }\n        path[i] = best;\n        used[best] = true;\n    }\n    return path;\n}\n\n// 2\u2011opt with time limit\nvector<int> two_opt_order(vector<int> order, double time_limit) {\n    auto t0 = steady_clock::now();\n    auto elapsed = [&]() { return duration<double>(steady_clock::now() - t0).count(); };\n    auto dist = [&](int a, int b) { return gdist[a][b]; };\n    int n = N;\n    bool improved = true;\n    while (improved && elapsed() < time_limit) {\n        improved = false;\n        for (int i = 0; i < n - 1; ++i) {\n            for (int j = i + 2; j < n - 1; ++j) {\n                if (elapsed() >= time_limit) break;\n                int a = order[i], b = order[i + 1], c = order[j], d_ = order[j + 1];\n                double old = dist(a, b) + dist(c, d_);\n                double nw  = dist(a, c) + dist(b, d_);\n                if (nw + 1e-9 < old) {\n                    reverse(order.begin() + i + 1, order.begin() + j + 1);\n                    improved = true;\n                }\n            }\n        }\n    }\n    return order;\n}\n\n// ---------- quick 2\u2011opt pass for a group ----------\nvoid quick_2opt_group(vector<int>& order) {\n    int k = (int)order.size();\n    if (k <= 3) return;\n    auto d = [&](int a, int b) { return gdist[a][b]; };\n    for (int i = 0; i < k - 1; ++i) {\n        for (int j = i + 2; j < k - 1; ++j) {\n            int a = order[i], b = order[i + 1], c = order[j], d_ = order[j + 1];\n            double old = d(a, b) + d(c, d_);\n            double nw  = d(a, c) + d(b, d_);\n            if (nw + 1e-9 < old) {\n                reverse(order.begin() + i + 1, order.begin() + j + 1);\n            }\n        }\n    }\n}\n\n// ---------- build final tree for one group ----------\nvector<pair<int, int>> build_group_tree(const vector<int>& order, int allowed) {\n    int sz = (int)order.size();\n    vector<pair<int, int>> edges;\n    if (sz <= 1) return edges;\n\n    DSU dsu(N);\n    int pos = 0;\n\n    if (allowed > 0 && q_used < Q) {\n        int take = min(L, sz - pos);\n        vector<int> subset(order.begin(), order.begin() + take);\n        auto res = query_subset(subset);\n        for (auto& e : res) if (dsu.unite(e.first, e.second)) edges.push_back(e);\n        pos += take;\n        --allowed;\n    }\n    while (pos < sz && allowed > 0 && q_used < Q) {\n        int anchor = order[pos - 1];\n        int take = min(L - 1, sz - pos);\n        vector<int> subset = {anchor};\n        subset.insert(subset.end(), order.begin() + pos, order.begin() + pos + take);\n        auto res = query_subset(subset);\n        for (auto& e : res) if (dsu.unite(e.first, e.second)) edges.push_back(e);\n        pos += take;\n        --allowed;\n    }\n\n    // fill remaining using local estimated MST\n    if ((int)edges.size() < sz - 1) {\n        vector<tuple<double, int, int>> loc;\n        loc.reserve(sz * (sz - 1) / 2);\n        for (int i = 0; i < sz; ++i)\n            for (int j = i + 1; j < sz; ++j)\n                loc.emplace_back(gdist[order[i]][order[j]], order[i], order[j]);\n        sort(loc.begin(), loc.end());\n        for (auto& [d, u, v] : loc) {\n            if ((int)edges.size() == sz - 1) break;\n            if (dsu.unite(u, v)) edges.emplace_back(u, v);\n        }\n    }\n    return edges;\n}\n\n// ---------- main ----------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    auto start_time = steady_clock::now();\n    auto elapsed = [&]() { return duration<double>(steady_clock::now() - start_time).count(); };\n\n    cin >> N >> M >> Q >> L >> W;\n    vector<int> G(M);\n    for (int i = 0; i < M; ++i) cin >> G[i];\n\n    vector<int> lx(N), rx(N), ly(N), ry(N);\n    cx.resize(N); cy.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n        cx[i] = (lx[i] + rx[i]) / 2;\n        cy[i] = (ly[i] + ry[i]) / 2;\n    }\n\n    // build estimated distance matrix + sorted edge list\n    gdist.assign(N, vector<double>(N, 0.0));\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            double dx = cx[i] - cx[j];\n            double dy = cy[i] - cy[j];\n            double d = sqrt(dx * dx + dy * dy);\n            gdist[i][j] = gdist[j][i] = d;\n            global_edges.emplace_back(d, i, j);\n        }\n    }\n    sort(global_edges.begin(), global_edges.end());\n\n    vector<int> group_of(N), local_id(N);\n    auto evaluate = [&](const vector<int>& ord) {\n        return evaluate_partition(ord, G, group_of, local_id);\n    };\n\n    // ---------- find good global ordering ----------\n    vector<int> best_order;\n    double best_cost = 1e18;\n\n    // candidate 1: double\u2011MST TSP\n    {\n        vector<int> cand = double_mst_tsp();\n        double cost = evaluate(cand);\n        if (cost < best_cost) { best_cost = cost; best_order = move(cand); }\n    }\n\n    // candidate 2: centroid NN + short 2\u2011opt\n    if (elapsed() < 1.5) {\n        double sx = 0, sy = 0;\n        for (int i = 0; i < N; ++i) { sx += cx[i]; sy += cy[i]; }\n        sx /= N; sy /= N;\n        int start = 0;\n        double bd = 1e18;\n        for (int i = 0; i < N; ++i) {\n            double dx = cx[i] - sx, dy = cy[i] - sy;\n            double d = dx * dx + dy * dy;\n            if (d < bd) { bd = d; start = i; }\n        }\n        vector<int> cand = nn_tsp(start);\n        cand = two_opt_order(move(cand), min(0.45, 1.8 - elapsed()));\n        double cost = evaluate(cand);\n        if (cost < best_cost) { best_cost = cost; best_order = move(cand); }\n    }\n\n    // a few random starts (if time permits)\n    mt19937 rng(12345);\n    uniform_int_distribution<int> rnd_city(0, N - 1);\n    for (int rep = 0; rep < 4 && elapsed() < 1.5; ++rep) {\n        int start = rnd_city(rng);\n        vector<int> cand = nn_tsp(start);\n        cand = two_opt_order(move(cand), min(0.25, (1.7 - elapsed()) * 0.5));\n        double cost = evaluate(cand);\n        if (cost < best_cost) { best_cost = cost; best_order = move(cand); }\n    }\n\n    if (best_order.empty()) { // fallback\n        best_order = double_mst_tsp();\n    }\n\n    // ---------- partition into groups ----------\n    vector<vector<int>> groups(M);\n    int cur_idx = 0;\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < G[i]; ++j)\n            groups[i].push_back(best_order[cur_idx++]);\n    }\n\n    // ---------- boundary swap local search ----------\n    const int SWAP_CAND = 3;\n    for (int sweep = 0; sweep < 5 && elapsed() < 1.7; ++sweep) {\n        bool any_improved = false;\n        for (int i = 0; i < M - 1 && elapsed() < 1.7; ++i) {\n            if (G[i] < 2 || G[i + 1] < 2) continue;\n            int Lsz = G[i], Rsz = G[i + 1];\n            int Lcnt = min(SWAP_CAND, Lsz);\n            int Rcnt = min(SWAP_CAND, Rsz);\n\n            double old_cost = mst_cost_prim(groups[i]) + mst_cost_prim(groups[i + 1]);\n            double best_delta = 0;\n            pair<int, int> best_swap = {-1, -1};\n\n            for (int a = 0; a < Lcnt; ++a) {\n                for (int b = 0; b < Rcnt; ++b) {\n                    int idxL = Lsz - Lcnt + a;\n                    int idxR = b;\n                    swap(groups[i][idxL], groups[i + 1][idxR]);\n                    double new_cost = mst_cost_prim(groups[i]) + mst_cost_prim(groups[i + 1]);\n                    double delta = old_cost - new_cost;\n                    if (delta > best_delta + 1e-9) {\n                        best_delta = delta;\n                        best_swap = {idxL, idxR};\n                    }\n                    swap(groups[i][idxL], groups[i + 1][idxR]);\n                }\n            }\n            if (best_delta > 1e-9) {\n                swap(groups[i][best_swap.first], groups[i + 1][best_swap.second]);\n                any_improved = true;\n            }\n        }\n        if (!any_improved) break;\n    }\n\n    // ---------- quick intra\u2011group order improvement ----------\n    if (elapsed() < 1.7) {\n        for (int i = 0; i < M; ++i) {\n            if (groups[i].size() > 2) quick_2opt_group(groups[i]);\n        }\n    }\n\n    // ---------- group information & query allocation ----------\n    struct Info {\n        int idx, size, need_queries;\n        vector<int> tsp_order;    // order inside group (after improvement)\n        double chain_cost, mst_cost;\n    };\n    vector<Info> infos(M);\n    for (int i = 0; i < M; ++i) {\n        infos[i].idx = i;\n        infos[i].size = (int)groups[i].size();\n        infos[i].tsp_order = groups[i];\n        if (infos[i].size <= 1) {\n            infos[i].need_queries = 0;\n            infos[i].chain_cost = infos[i].mst_cost = 0;\n        } else {\n            double chain = 0;\n            for (int j = 1; j < (int)infos[i].tsp_order.size(); ++j)\n                chain += gdist[infos[i].tsp_order[j - 1]][infos[i].tsp_order[j]];\n            infos[i].chain_cost = chain;\n            infos[i].mst_cost = mst_cost_prim(groups[i]);\n            int sz = infos[i].size;\n            if (sz <= 2) infos[i].need_queries = 0;\n            else if (sz <= L) infos[i].need_queries = 1;\n            else infos[i].need_queries = 1 + (sz - 2) / (L - 1);\n        }\n    }\n\n    vector<int> alloc(M, 0);\n    int total_need = 0;\n    for (auto& info : infos) total_need += info.need_queries;\n    if (total_need > Q) {\n        vector<pair<double, int>> ord;\n        for (int i = 0; i < M; ++i) {\n            if (infos[i].need_queries > 0) {\n                double benefit = max(0.0, infos[i].chain_cost - infos[i].mst_cost);\n                ord.emplace_back(benefit / infos[i].need_queries, i);\n            }\n        }\n        sort(ord.begin(), ord.end(), [](auto& a, auto& b) { return a.first > b.first; });\n        int remaining = Q;\n        for (auto& p : ord) {\n            int i = p.second;\n            int give = min(infos[i].need_queries, remaining);\n            alloc[i] = give;\n            remaining -= give;\n            if (remaining == 0) break;\n        }\n    } else {\n        for (int i = 0; i < M; ++i) alloc[i] = infos[i].need_queries;\n    }\n\n    // query execution order (highest benefit first)\n    vector<int> query_order;\n    {\n        vector<pair<double, int>> tmp;\n        for (int i = 0; i < M; ++i)\n            if (alloc[i] > 0)\n                tmp.emplace_back(max(0.0, infos[i].chain_cost - infos[i].mst_cost) / alloc[i], i);\n        sort(tmp.begin(), tmp.end(), [](auto& a, auto& b) { return a.first > b.first; });\n        for (auto& p : tmp) query_order.push_back(p.second);\n        for (int i = 0; i < M; ++i)\n            if (alloc[i] == 0) query_order.push_back(i);\n    }\n\n    // ---------- build final trees ----------\n    vector<vector<pair<int, int>>> out_edges(M);\n    for (int idx : query_order) {\n        if (q_used >= Q) break;\n        if (groups[idx].size() <= 1) continue;\n        int allowed = alloc[idx];\n        out_edges[idx] = build_group_tree(infos[idx].tsp_order, allowed);\n    }\n\n    // safety fallback\n    for (int i = 0; i < M; ++i) {\n        if (groups[i].size() <= 1) continue;\n        if (!out_edges[i].empty()) continue;\n        out_edges[i] = build_group_tree(infos[i].tsp_order, 0);\n    }\n\n    // ---------- output ----------\n    cout << '!' << endl;\n    for (int i = 0; i < M; ++i) {\n        const auto& cities = groups[i];\n        for (int j = 0; j < (int)cities.size(); ++j) {\n            if (j) cout << ' ';\n            cout << cities[j];\n        }\n        cout << endl;\n        for (auto& e : out_edges[i]) {\n            cout << e.first << ' ' << e.second << endl;\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <string>\n\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int N, M;\n    cin >> N >> M;\n    vector<int> R(M), C(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> R[i] >> C[i];\n    }\n\n    int total = N * N;\n    int S = total;          // represents \"no block\"\n    int state_size = total + 1;\n    int MAX_STATE = total * state_size;\n\n    // precompute row and column for each cell\n    vector<int> pr(total), pc(total);\n    for (int i = 0; i < total; ++i) {\n        pr[i] = i / N;\n        pc[i] = i % N;\n    }\n\n    vector<int> vis(MAX_STATE, 0);\n    vector<int> ps(MAX_STATE);\n    vector<int> pa(MAX_STATE);\n    vector<int> q(MAX_STATE);\n    int tok = 0;\n\n    vector<int> total_actions;\n\n    // process each segment: start -> target1, target1 -> target2, ...\n    for (int seg = 0; seg < M - 1; ++seg) {\n        int start_pos = R[seg] * N + C[seg];\n        int target_pos = R[seg+1] * N + C[seg+1];\n\n        ++tok;\n        int head = 0, tail = 0;\n        int start_state = start_pos * state_size + S;\n        vis[start_state] = tok;\n        ps[start_state] = -1;\n        q[tail++] = start_state;\n        int goal_state = -1;\n\n        while (head < tail) {\n            int s = q[head++];\n            int pos = s / state_size;\n            int block = s % state_size;\n            if (pos == target_pos && block == S) {\n                goal_state = s;\n                break;\n            }\n            int r = pr[pos], c = pc[pos];\n\n            for (int d = 0; d < 4; ++d) {\n                // --- Move ---\n                int nr = r, nc = c;\n                if (d == 0) nr--;\n                else if (d == 1) nr++;\n                else if (d == 2) nc--;\n                else nc++;\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                    int npos = nr * N + nc;\n                    if (npos != block) {\n                        int nstate = npos * state_size + block;\n                        if (vis[nstate] != tok) {\n                            vis[nstate] = tok;\n                            ps[nstate] = s;\n                            pa[nstate] = 0 * 4 + d;  // Move\n                            q[tail++] = nstate;\n                        }\n                    }\n                }\n\n                // --- Slide ---\n                int slide_pos;\n                if (block == S) {\n                    if (d == 0) slide_pos = c;                     // (0, c)\n                    else if (d == 1) slide_pos = (N-1)*N + c;      // (N-1, c)\n                    else if (d == 2) slide_pos = r * N;            // (r, 0)\n                    else slide_pos = r * N + (N-1);                // (r, N-1)\n                } else {\n                    int br = block / N, bc = block % N;\n                    if (d == 0) {  // up\n                        if (bc == c && br < r) slide_pos = (br + 1) * N + c;\n                        else slide_pos = c;\n                    } else if (d == 1) {  // down\n                        if (bc == c && br > r) slide_pos = (br - 1) * N + c;\n                        else slide_pos = (N-1)*N + c;\n                    } else if (d == 2) {  // left\n                        if (br == r && bc < c) slide_pos = r * N + (bc + 1);\n                        else slide_pos = r * N;\n                    } else {  // right\n                        if (br == r && bc > c) slide_pos = r * N + (bc - 1);\n                        else slide_pos = r * N + (N-1);\n                    }\n                }\n                int nstate_s = slide_pos * state_size + block;\n                if (vis[nstate_s] != tok) {\n                    vis[nstate_s] = tok;\n                    ps[nstate_s] = s;\n                    pa[nstate_s] = 1 * 4 + d;  // Slide\n                    q[tail++] = nstate_s;\n                }\n\n                // --- Alter ---\n                int adj_r = r, adj_c = c;\n                if (d == 0) adj_r--;\n                else if (d == 1) adj_r++;\n                else if (d == 2) adj_c--;\n                else adj_c++;\n                if (adj_r >= 0 && adj_r < N && adj_c >= 0 && adj_c < N) {\n                    int adj_id = adj_r * N + adj_c;\n                    if (block == S) {\n                        // place block\n                        int nstate = pos * state_size + adj_id;\n                        if (vis[nstate] != tok) {\n                            vis[nstate] = tok;\n                            ps[nstate] = s;\n                            pa[nstate] = 2 * 4 + d;  // Alter (place)\n                            q[tail++] = nstate;\n                        }\n                    } else {\n                        if (adj_id == block) {\n                            // remove block\n                            int nstate = pos * state_size + S;\n                            if (vis[nstate] != tok) {\n                                vis[nstate] = tok;\n                                ps[nstate] = s;\n                                pa[nstate] = 2 * 4 + d;  // Alter (remove)\n                                q[tail++] = nstate;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        // reconstruct action sequence for this segment\n        vector<int> seg_actions;\n        for (int s = goal_state; s != start_state; s = ps[s]) {\n            seg_actions.push_back(pa[s]);\n        }\n        reverse(seg_actions.begin(), seg_actions.end());\n        total_actions.insert(total_actions.end(), seg_actions.begin(), seg_actions.end());\n    }\n\n    // cancel consecutive identical Alter actions (place/remove pairs that do nothing)\n    vector<int> opt_actions;\n    for (int aid : total_actions) {\n        if (!opt_actions.empty() && opt_actions.back() == aid && (aid / 4) == 2) {\n            opt_actions.pop_back();\n        } else {\n            opt_actions.push_back(aid);\n        }\n    }\n    total_actions = move(opt_actions);\n\n    const char act_chars[3] = {'M', 'S', 'A'};\n    const char dir_chars[4] = {'U', 'D', 'L', 'R'};\n    for (int aid : total_actions) {\n        cout << act_chars[aid / 4] << ' ' << dir_chars[aid % 4] << '\\n';\n    }\n\n    return 0;\n}"}}}