{"model_name":"mimo-v2.5-pro","codes":{"1":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\n\nstruct Company {\n    int x, y, r;\n};\n\nstruct Node {\n    int x1, y1, x2, y2;\n    vector<int> ids;          // indices of companies in this node\n    int cut_type;             // 0: leaf, 1: vertical, 2: horizontal\n    int cut_pos;              // coordinate of the cut (if not leaf)\n    Node *left, *right;\n    Node() : left(nullptr), right(nullptr) {}\n};\n\nint n;\nvector<Company> comps;\nvector<int> a, b, c, d;      // answer rectangles\n\n// recursively build the partition tree\nNode* build(int x1, int y1, int x2, int y2, vector<int>& ids) {\n    Node* node = new Node();\n    node->x1 = x1; node->y1 = y1; node->x2 = x2; node->y2 = y2;\n    node->ids = ids;\n\n    // leaf: single company\n    if (ids.size() == 1) {\n        node->cut_type = 0;\n        return node;\n    }\n\n    // total desired area in this node\n    ll total_r = 0;\n    for (int i : ids) total_r += comps[i].r;\n\n    // find extreme coordinates of points in this node\n    int min_x = 10000, max_x = 0, min_y = 10000, max_y = 0;\n    for (int i : ids) {\n        min_x = min(min_x, comps[i].x);\n        max_x = max(max_x, comps[i].x);\n        min_y = min(min_y, comps[i].y);\n        max_y = max(max_y, comps[i].y);\n    }\n\n    ll best_cost = LLONG_MAX;\n    int best_type = -1;   // 1 vertical, 2 horizontal\n    int best_pos = -1;\n\n    // ----- vertical cuts -----\n    if (max_x > min_x) {   // at least two different x coordinates\n        for (int X = x1 + 1; X < x2; ++X) {\n            if (X <= min_x || X > max_x) continue;   // ensure both sides non\u2011empty\n            ll left_sum = 0;\n            for (int i : ids)\n                if (comps[i].x < X) left_sum += comps[i].r;\n            ll left_area  = (ll)(X - x1) * (y2 - y1);\n            ll right_sum  = total_r - left_sum;\n            ll right_area = (ll)(x2 - X) * (y2 - y1);\n            ll cost = (left_area - left_sum) * (left_area - left_sum)\n                    + (right_area - right_sum) * (right_area - right_sum);\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_type = 1;\n                best_pos  = X;\n            }\n        }\n    }\n\n    // ----- horizontal cuts -----\n    if (max_y > min_y) {\n        for (int Y = y1 + 1; Y < y2; ++Y) {\n            if (Y <= min_y || Y > max_y) continue;\n            ll bottom_sum = 0;\n            for (int i : ids)\n                if (comps[i].y < Y) bottom_sum += comps[i].r;\n            ll bottom_area = (ll)(x2 - x1) * (Y - y1);\n            ll top_sum     = total_r - bottom_sum;\n            ll top_area    = (ll)(x2 - x1) * (y2 - Y);\n            ll cost = (bottom_area - bottom_sum) * (bottom_area - bottom_sum)\n                    + (top_area - top_sum) * (top_area - top_sum);\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_type = 2;\n                best_pos  = Y;\n            }\n        }\n    }\n\n    // At least one orientation must be valid because points are distinct.\n    assert(best_type != -1);\n\n    // split the point set according to the chosen cut\n    if (best_type == 1) {   // vertical\n        vector<int> left_ids, right_ids;\n        for (int i : ids) {\n            if (comps[i].x < best_pos) left_ids.push_back(i);\n            else right_ids.push_back(i);\n        }\n        node->cut_type = 1;\n        node->cut_pos  = best_pos;\n        node->left  = build(x1, y1, best_pos, y2, left_ids);\n        node->right = build(best_pos, y1, x2, y2, right_ids);\n    } else {                // horizontal\n        vector<int> bottom_ids, top_ids;\n        for (int i : ids) {\n            if (comps[i].y < best_pos) bottom_ids.push_back(i);\n            else top_ids.push_back(i);\n        }\n        node->cut_type = 2;\n        node->cut_pos  = best_pos;\n        node->left  = build(x1, y1, x2, best_pos, bottom_ids);\n        node->right = build(x1, best_pos, x2, y2, top_ids);\n    }\n\n    return node;\n}\n\n// collect leaf rectangles into the answer arrays\nvoid collect(Node* node) {\n    if (node->cut_type == 0) {\n        int i = node->ids[0];\n        a[i] = node->x1;\n        b[i] = node->y1;\n        c[i] = node->x2;\n        d[i] = node->y2;\n        return;\n    }\n    collect(node->left);\n    collect(node->right);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n;\n    comps.resize(n);\n    for (int i = 0; i < n; ++i)\n        cin >> comps[i].x >> comps[i].y >> comps[i].r;\n\n    a.resize(n); b.resize(n); c.resize(n); d.resize(n);\n\n    vector<int> ids(n);\n    iota(ids.begin(), ids.end(), 0);\n    Node* root = build(0, 0, 10000, 10000, ids);\n\n    collect(root);\n\n    for (int i = 0; i < n; ++i)\n        cout << a[i] << ' ' << b[i] << ' ' << c[i] << ' ' << d[i] << '\\n';\n\n    return 0;\n}","ahc002":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <cassert>\n#include <tuple>\n\nusing namespace std;\n\nconst int N = 50;\nconst int dr[4] = {-1, 1, 0, 0};\nconst int dc[4] = {0, 0, -1, 1};\nconst char dir_char[4] = {'U', 'D', 'L', 'R'};\n\nstruct Neighbor {\n    int r, c;\n    char dir;\n};\n\n// Get valid neighbors from (r,c) given visited tiles.\nvector<Neighbor> get_neighbors(int r, int c, const vector<char>& visited,\n                               const vector<vector<int>>& tile_id) {\n    vector<Neighbor> res;\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) {\n            int tile = tile_id[nr][nc];\n            if (!visited[tile]) {\n                res.push_back({nr, nc, dir_char[d]});\n            }\n        }\n    }\n    return res;\n}\n\n// Greedily extend the path from the last square.\nvoid extend_greedy(vector<pair<int,int>>& path, vector<int>& tiles,\n                   vector<char>& visited, int& score,\n                   const vector<vector<int>>& p,\n                   const vector<vector<int>>& tile_id) {\n    while (true) {\n        int r = path.back().first, c = path.back().second;\n        auto candidates = get_neighbors(r, c, visited, tile_id);\n        if (candidates.empty()) break;\n        // Choose neighbor with highest p.\n        auto best = max_element(candidates.begin(), candidates.end(),\n                                [&](const Neighbor& a, const Neighbor& b) {\n                                    return p[a.r][a.c] < p[b.r][b.c];\n                                });\n        path.push_back({best->r, best->c});\n        tiles.push_back(tile_id[best->r][best->c]);\n        visited[tile_id[best->r][best->c]] = 1;\n        score += p[best->r][best->c];\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Read input.\n    int si, sj;\n    cin >> si >> sj;\n    vector<vector<int>> tile_id(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> tile_id[i][j];\n    vector<vector<int>> 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    // Determine number of tiles.\n    int M = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            M = max(M, tile_id[i][j] + 1);\n\n    // Initial greedy path.\n    vector<pair<int,int>> cur_path;\n    vector<int> cur_tiles;\n    vector<char> cur_visited(M, 0);\n    int cur_score = 0;\n\n    cur_path.emplace_back(si, sj);\n    cur_tiles.push_back(tile_id[si][sj]);\n    cur_visited[tile_id[si][sj]] = 1;\n    cur_score += p[si][sj];\n    extend_greedy(cur_path, cur_tiles, cur_visited, cur_score, p, tile_id);\n\n    vector<pair<int,int>> best_path = cur_path;\n    int best_score = cur_score;\n\n    // Simulated annealing parameters.\n    const int ITER = 100000;\n    const double T_start = 100.0;\n    const double T_min = 1e-3;\n    const double cooling = pow(T_min / T_start, 1.0 / ITER);\n    double T = T_start;\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> real_dist(0.0, 1.0);\n\n    auto start_time = chrono::steady_clock::now();\n    const chrono::milliseconds time_limit(1800); // 1.8 seconds\n\n    for (int iter = 0; iter < ITER; ++iter) {\n        // Time check.\n        if (iter % 1000 == 0) {\n            auto now = chrono::steady_clock::now();\n            if (chrono::duration_cast<chrono::milliseconds>(now - start_time) > time_limit)\n                break;\n        }\n\n        // Copy current state.\n        vector<pair<int,int>> new_path = cur_path;\n        vector<int> new_tiles = cur_tiles;\n        vector<char> new_visited = cur_visited;\n        int new_score = cur_score;\n\n        double op = real_dist(rng);\n        if (op < 0.4) {\n            // Extend: add one move at the end.\n            if (!new_path.empty()) {\n                int r = new_path.back().first, c = new_path.back().second;\n                auto candidates = get_neighbors(r, c, new_visited, tile_id);\n                if (!candidates.empty()) {\n                    uniform_int_distribution<int> dist(0, candidates.size() - 1);\n                    int idx = dist(rng);\n                    auto& cand = candidates[idx];\n                    new_path.push_back({cand.r, cand.c});\n                    new_tiles.push_back(tile_id[cand.r][cand.c]);\n                    new_visited[tile_id[cand.r][cand.c]] = 1;\n                    new_score += p[cand.r][cand.c];\n                }\n            }\n        } else if (op < 0.6) {\n            // Shrink: remove last move.\n            if (new_path.size() > 1) {\n                auto last = new_path.back();\n                int tile = new_tiles.back();\n                new_path.pop_back();\n                new_tiles.pop_back();\n                new_visited[tile] = 0;\n                new_score -= p[last.first][last.second];\n            }\n        } else {\n            // Modify: truncate at random index, change next move, then extend greedily.\n            if (new_path.size() <= 1) {\n                // Fallback to extend.\n                if (!new_path.empty()) {\n                    int r = new_path.back().first, c = new_path.back().second;\n                    auto candidates = get_neighbors(r, c, new_visited, tile_id);\n                    if (!candidates.empty()) {\n                        uniform_int_distribution<int> dist(0, candidates.size() - 1);\n                        int idx = dist(rng);\n                        auto& cand = candidates[idx];\n                        new_path.push_back({cand.r, cand.c});\n                        new_tiles.push_back(tile_id[cand.r][cand.c]);\n                        new_visited[tile_id[cand.r][cand.c]] = 1;\n                        new_score += p[cand.r][cand.c];\n                    }\n                }\n            } else {\n                int L = new_path.size();\n                uniform_int_distribution<int> idx_dist(1, L - 1);\n                int k = idx_dist(rng); // index of the square to replace (move from k-1 to k)\n                // Remove squares from index k onward.\n                for (int i = k; i < L; ++i) {\n                    int tile = new_tiles[i];\n                    new_visited[tile] = 0;\n                    new_score -= p[new_path[i].first][new_path[i].second];\n                }\n                new_path.resize(k);\n                new_tiles.resize(k);\n                // Choose a new move from the square at index k-1.\n                int r_prev = new_path.back().first, c_prev = new_path.back().second;\n                auto candidates = get_neighbors(r_prev, c_prev, new_visited, tile_id);\n                if (!candidates.empty()) {\n                    uniform_int_distribution<int> dist(0, candidates.size() - 1);\n                    int idx = dist(rng);\n                    auto& cand = candidates[idx];\n                    new_path.push_back({cand.r, cand.c});\n                    new_tiles.push_back(tile_id[cand.r][cand.c]);\n                    new_visited[tile_id[cand.r][cand.c]] = 1;\n                    new_score += p[cand.r][cand.c];\n                    // Extend greedily from the new endpoint.\n                    extend_greedy(new_path, new_tiles, new_visited, new_score, p, tile_id);\n                }\n            }\n        }\n\n        // Metropolis criterion.\n        int delta = new_score - cur_score;\n        bool accept = false;\n        if (delta > 0) {\n            accept = true;\n        } else {\n            double prob = exp(delta / T);\n            if (real_dist(rng) < prob) accept = true;\n        }\n\n        if (accept) {\n            cur_path = std::move(new_path);\n            cur_tiles = std::move(new_tiles);\n            cur_visited = std::move(new_visited);\n            cur_score = new_score;\n            if (cur_score > best_score) {\n                best_score = cur_score;\n                best_path = cur_path;\n            }\n        }\n\n        // Cooling.\n        T *= cooling;\n    }\n\n    // Convert best_path to move string.\n    string moves;\n    for (size_t i = 1; i < best_path.size(); ++i) {\n        int dr = best_path[i].first - best_path[i-1].first;\n        int dc = best_path[i].second - best_path[i-1].second;\n        if (dr == -1 && dc == 0) moves += 'U';\n        else if (dr == 1 && dc == 0) moves += 'D';\n        else if (dr == 0 && dc == -1) moves += 'L';\n        else if (dr == 0 && dc == 1) moves += 'R';\n        else assert(false);\n    }\n\n    cout << moves << endl;\n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <string>\n\nusing namespace std;\n\nconst int N = 30;\n\ndouble h_est[N][N-1]; // horizontal edges: between (i,j) and (i,j+1)\ndouble v_est[N-1][N]; // vertical edges: between (i,j) and (i+1,j)\n\nstruct Node {\n    int i, j;\n    bool operator==(const Node& other) const { return i == other.i && j == other.j; }\n    bool operator!=(const Node& other) const { return !(*this == other); }\n};\n\nusing PQElement = pair<double, Node>;\n\nstruct Compare {\n    bool operator()(const PQElement& a, const PQElement& b) const {\n        return a.first > b.first;\n    }\n};\n\ndouble getEdgeEstimate(int i, int j, int ni, int nj) {\n    if (i == ni) {\n        if (nj == j+1) return h_est[i][j];\n        else if (nj == j-1) return h_est[i][j-1];\n    } else if (j == nj) {\n        if (ni == i+1) return v_est[i][j];\n        else if (ni == i-1) return v_est[i-1][j];\n    }\n    return 0.0; // should not happen\n}\n\nvoid updateEdge(int i, int j, int ni, int nj, double factor) {\n    if (i == ni) {\n        if (nj == j+1) {\n            h_est[i][j] *= factor;\n            if (h_est[i][j] < 500.0) h_est[i][j] = 500.0;\n            if (h_est[i][j] > 15000.0) h_est[i][j] = 15000.0;\n        } else if (nj == j-1) {\n            h_est[i][j-1] *= factor;\n            if (h_est[i][j-1] < 500.0) h_est[i][j-1] = 500.0;\n            if (h_est[i][j-1] > 15000.0) h_est[i][j-1] = 15000.0;\n        }\n    } else if (j == nj) {\n        if (ni == i+1) {\n            v_est[i][j] *= factor;\n            if (v_est[i][j] < 500.0) v_est[i][j] = 500.0;\n            if (v_est[i][j] > 15000.0) v_est[i][j] = 15000.0;\n        } else if (ni == i-1) {\n            v_est[i-1][j] *= factor;\n            if (v_est[i-1][j] < 500.0) v_est[i-1][j] = 500.0;\n            if (v_est[i-1][j] > 15000.0) v_est[i-1][j] = 15000.0;\n        }\n    }\n}\n\nvoid updateEstimates(const vector<Node>& path, int obs, int k) {\n    int path_length = path.size() - 1;\n    if (path_length == 0) return;\n    double pred = 0.0;\n    for (int idx = 0; idx < path_length; idx++) {\n        auto& from = path[idx];\n        auto& to = path[idx+1];\n        pred += getEdgeEstimate(from.i, from.j, to.i, to.j);\n    }\n    double factor = obs / pred;\n    double alpha = 0.1 * (1.0 - k/1000.0);\n    double damp_factor = 1.0 + alpha * (factor - 1.0);\n    double edge_factor = pow(damp_factor, 1.0 / path_length);\n    for (int idx = 0; idx < path_length; idx++) {\n        auto& from = path[idx];\n        auto& to = path[idx+1];\n        updateEdge(from.i, from.j, to.i, to.j, edge_factor);\n    }\n}\n\npair<string, vector<Node>> computePath(int si, int sj, int ti, int tj) {\n    vector<vector<double>> dist(N, vector<double>(N, 1e18));\n    vector<vector<Node>> prev(N, vector<Node>(N, {-1,-1}));\n    dist[si][sj] = 0.0;\n    priority_queue<PQElement, vector<PQElement>, Compare> pq;\n    pq.push({0.0, {si, sj}});\n    while (!pq.empty()) {\n        auto [d, node] = pq.top(); pq.pop();\n        if (d > dist[node.i][node.j]) continue;\n        if (node.i == ti && node.j == tj) break;\n        // right\n        if (node.j+1 < N) {\n            double w = h_est[node.i][node.j];\n            if (dist[node.i][node.j] + w < dist[node.i][node.j+1]) {\n                dist[node.i][node.j+1] = dist[node.i][node.j] + w;\n                prev[node.i][node.j+1] = {node.i, node.j};\n                pq.push({dist[node.i][node.j+1], {node.i, node.j+1}});\n            }\n        }\n        // left\n        if (node.j-1 >= 0) {\n            double w = h_est[node.i][node.j-1];\n            if (dist[node.i][node.j] + w < dist[node.i][node.j-1]) {\n                dist[node.i][node.j-1] = dist[node.i][node.j] + w;\n                prev[node.i][node.j-1] = {node.i, node.j};\n                pq.push({dist[node.i][node.j-1], {node.i, node.j-1}});\n            }\n        }\n        // down\n        if (node.i+1 < N) {\n            double w = v_est[node.i][node.j];\n            if (dist[node.i][node.j] + w < dist[node.i+1][node.j]) {\n                dist[node.i+1][node.j] = dist[node.i][node.j] + w;\n                prev[node.i+1][node.j] = {node.i, node.j};\n                pq.push({dist[node.i+1][node.j], {node.i+1, node.j}});\n            }\n        }\n        // up\n        if (node.i-1 >= 0) {\n            double w = v_est[node.i-1][node.j];\n            if (dist[node.i][node.j] + w < dist[node.i-1][node.j]) {\n                dist[node.i-1][node.j] = dist[node.i][node.j] + w;\n                prev[node.i-1][node.j] = {node.i, node.j};\n                pq.push({dist[node.i-1][node.j], {node.i-1, node.j}});\n            }\n        }\n    }\n    // reconstruct path\n    vector<Node> path_nodes;\n    Node cur = {ti, tj};\n    while (cur.i != si || cur.j != sj) {\n        path_nodes.push_back(cur);\n        cur = prev[cur.i][cur.j];\n    }\n    path_nodes.push_back({si, sj});\n    reverse(path_nodes.begin(), path_nodes.end());\n    // convert to string\n    string path_str;\n    for (size_t idx = 0; idx < path_nodes.size()-1; idx++) {\n        auto& from = path_nodes[idx];\n        auto& to = path_nodes[idx+1];\n        if (to.i == from.i && to.j == from.j+1) path_str += 'R';\n        else if (to.i == from.i && to.j == from.j-1) path_str += 'L';\n        else if (to.i == from.i+1 && to.j == from.j) path_str += 'D';\n        else if (to.i == from.i-1 && to.j == from.j) path_str += 'U';\n    }\n    return {path_str, path_nodes};\n}\n\nint main() {\n    // initialize estimates\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N-1; ++j)\n            h_est[i][j] = 5000.0;\n    for (int i = 0; i < N-1; ++i)\n        for (int j = 0; j < N; ++j)\n            v_est[i][j] = 5000.0;\n\n    for (int k = 0; k < 1000; ++k) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n        auto [path_str, path_nodes] = computePath(si, sj, ti, tj);\n        cout << path_str << endl;\n        cout.flush();\n        int obs;\n        cin >> obs;\n        updateEstimates(path_nodes, obs, k);\n    }\n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <cmath>\n#include <numeric>\n#include <array>\n#include <cassert>\n\nusing namespace std;\n\nconst int N = 20; // fixed\nconst int ALPHABET = 8; // A..H\n\nstruct Placement {\n    int str_idx;\n    int row, col; // starting position\n    int dir;      // 0: horizontal, 1: vertical\n    int len;\n};\n\nvector<string> strings;\nvector<Placement> placements;\nvector<vector<int>> placements_by_str;\nvector<vector<pair<int, char>>> cell_lists; // for each cell, list of (placement_id, required_char)\n\n// random generator\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// ------------------------------------------------------------\n// Generate all placements and group by string\nvoid generate_placements() {\n    int M = strings.size();\n    placements_by_str.resize(M);\n    placements.clear();\n    placements.reserve(M * 800);\n    int id = 0;\n    for (int s = 0; s < M; ++s) {\n        int len = strings[s].size();\n        for (int dir = 0; dir < 2; ++dir) {\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    placements.push_back({s, r, c, dir, len});\n                    placements_by_str[s].push_back(id);\n                    ++id;\n                }\n            }\n        }\n    }\n}\n\n// Build cell lists (reverse index)\nvoid build_cell_lists() {\n    cell_lists.assign(N * N, {});\n    for (int pid = 0; pid < (int)placements.size(); ++pid) {\n        const Placement& p = placements[pid];\n        for (int off = 0; off < p.len; ++off) {\n            int r, c;\n            if (p.dir == 0) { // horizontal\n                r = p.row;\n                c = (p.col + off) % N;\n            } else { // vertical\n                r = (p.row + off) % N;\n                c = p.col;\n            }\n            int cell = r * N + c;\n            char req = strings[p.str_idx][off];\n            cell_lists[cell].emplace_back(pid, req);\n        }\n    }\n}\n\n// Check if a string appears as a subsequence in the matrix\nbool is_subsequence(const vector<vector<char>>& mat, const string& s) {\n    int len = s.size();\n    // horizontal\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            bool ok = true;\n            for (int p = 0; p < len; ++p) {\n                if (mat[i][(j + p) % N] != s[p]) {\n                    ok = false;\n                    break;\n                }\n            }\n            if (ok) return true;\n        }\n    }\n    // vertical\n    for (int j = 0; j < N; ++j) {\n        for (int i = 0; i < N; ++i) {\n            bool ok = true;\n            for (int p = 0; p < len; ++p) {\n                if (mat[(i + p) % N][j] != s[p]) {\n                    ok = false;\n                    break;\n                }\n            }\n            if (ok) return true;\n        }\n    }\n    return false;\n}\n\n// Evaluate a matrix: number of satisfied strings\nint evaluate(const vector<vector<char>>& mat) {\n    int cnt = 0;\n    for (const string& s : strings) {\n        if (is_subsequence(mat, s)) ++cnt;\n    }\n    return cnt;\n}\n\n// ------------------------------------------------------------\n// Greedy construction (randomized)\nvector<vector<char>> greedy(int seed) {\n    mt19937 gen(seed);\n    vector<vector<char>> mat(N, vector<char>(N, '.'));\n    int M = strings.size();\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    shuffle(order.begin(), order.end(), gen);\n\n    for (int idx : order) {\n        const string& s = strings[idx];\n        int len = s.size();\n        vector<int> plist = placements_by_str[idx];\n        shuffle(plist.begin(), plist.end(), gen);\n        bool placed = false;\n        for (int pid : plist) {\n            const Placement& p = placements[pid];\n            // check compatibility\n            bool compatible = true;\n            for (int off = 0; off < len; ++off) {\n                int r, c;\n                if (p.dir == 0) {\n                    r = p.row;\n                    c = (p.col + off) % N;\n                } else {\n                    r = (p.row + off) % N;\n                    c = p.col;\n                }\n                if (mat[r][c] != '.' && mat[r][c] != s[off]) {\n                    compatible = false;\n                    break;\n                }\n            }\n            if (compatible) {\n                // place\n                for (int off = 0; off < len; ++off) {\n                    int r, c;\n                    if (p.dir == 0) {\n                        r = p.row;\n                        c = (p.col + off) % N;\n                    } else {\n                        r = (p.row + off) % N;\n                        c = p.col;\n                    }\n                    if (mat[r][c] == '.') {\n                        mat[r][c] = s[off];\n                    }\n                }\n                placed = true;\n                break;\n            }\n        }\n        // if not placed, we simply skip\n    }\n    // fill remaining '.' with 'A'\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (mat[i][j] == '.')\n                mat[i][j] = 'A';\n    return mat;\n}\n\n// ------------------------------------------------------------\n// Simulated Annealing\nvector<vector<char>> simulated_annealing(vector<vector<char>> mat) {\n    int M = strings.size();\n    int P = placements.size();\n    // Initialize placement_match_count and string_sat_count\n    vector<int> placement_match_count(P, 0);\n    vector<int> string_sat_count(M, 0);\n    int global_c = 0;\n\n    // Compute initial counts\n    for (int pid = 0; pid < P; ++pid) {\n        const Placement& p = placements[pid];\n        int cnt = 0;\n        for (int off = 0; off < p.len; ++off) {\n            int r, c;\n            if (p.dir == 0) {\n                r = p.row;\n                c = (p.col + off) % N;\n            } else {\n                r = (p.row + off) % N;\n                c = p.col;\n            }\n            if (mat[r][c] == strings[p.str_idx][off]) ++cnt;\n        }\n        placement_match_count[pid] = cnt;\n        if (cnt == p.len) {\n            ++string_sat_count[p.str_idx];\n        }\n    }\n    for (int s = 0; s < M; ++s)\n        if (string_sat_count[s] > 0) ++global_c;\n\n    // SA parameters\n    const int ITER = 200000; // adjustable\n    double T = 10.0;\n    double cooling = 0.99995; // such that after ITER, T ~ 10 * 0.99995^200000 \u2248 0.00045\n    uniform_int_distribution<int> cell_dist(0, N*N - 1);\n    uniform_int_distribution<int> char_dist(0, ALPHABET - 1);\n    uniform_real_distribution<double> prob_dist(0.0, 1.0);\n\n    for (int iter = 0; iter < ITER; ++iter) {\n        int cell = cell_dist(rng);\n        char old_char = mat[cell / N][cell % N];\n        char new_char = 'A' + char_dist(rng);\n        if (new_char == old_char) continue;\n\n        // We'll compute changes and apply them if accepted\n        vector<pair<int, int>> changed_placements; // (pid, old_count)\n        vector<pair<int, int>> changed_strings;    // (str_idx, delta)\n        int delta_c = 0;\n\n        for (const auto& [pid, req] : cell_lists[cell]) {\n            int cur_cnt = placement_match_count[pid];\n            int new_cnt = cur_cnt;\n            if (old_char == req) --new_cnt;\n            if (new_char == req) ++new_cnt;\n            if (new_cnt == cur_cnt) continue;\n\n            int len = placements[pid].len;\n            bool was_sat = (cur_cnt == len);\n            bool now_sat = (new_cnt == len);\n\n            changed_placements.emplace_back(pid, cur_cnt);\n            placement_match_count[pid] = new_cnt;\n\n            if (was_sat != now_sat) {\n                int str_idx = placements[pid].str_idx;\n                int delta = now_sat ? 1 : -1;\n                changed_strings.emplace_back(str_idx, delta);\n                string_sat_count[str_idx] += delta;\n                if (delta == 1 && string_sat_count[str_idx] == 1) ++delta_c;\n                if (delta == -1 && string_sat_count[str_idx] == 0) --delta_c;\n            }\n        }\n\n        // Decide acceptance\n        bool accept = false;\n        if (delta_c >= 0) accept = true;\n        else {\n            double prob = exp(delta_c / T);\n            if (prob_dist(rng) < prob) accept = true;\n        }\n\n        if (accept) {\n            mat[cell / N][cell % N] = new_char;\n            global_c += delta_c;\n            if (global_c == M) break; // perfect, we can stop\n        } else {\n            // revert changes\n            for (auto& [pid, old_cnt] : changed_placements) {\n                placement_match_count[pid] = old_cnt;\n            }\n            for (auto& [str_idx, delta] : changed_strings) {\n                string_sat_count[str_idx] -= delta;\n            }\n        }\n\n        T *= cooling;\n    }\n\n    return mat;\n}\n\n// ------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    cin >> N >> M;\n    strings.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> strings[i];\n    }\n\n    generate_placements();\n    build_cell_lists();\n\n    // Run greedy several times to get a good starting matrix\n    vector<vector<char>> best_mat;\n    int best_c = -1;\n    const int GREEDY_TRIES = 10;\n    for (int t = 0; t < GREEDY_TRIES; ++t) {\n        auto mat = greedy(rng());\n        int c = evaluate(mat);\n        if (c > best_c) {\n            best_c = c;\n            best_mat = mat;\n        }\n        if (best_c == M) break;\n    }\n\n    // If greedy already achieved perfect, we can skip SA (but we may still run SA to reduce dots? but we have no dots)\n    if (best_c < M) {\n        best_mat = simulated_annealing(best_mat);\n    }\n\n    // Output\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << best_mat[i][j];\n        }\n        cout << '\\n';\n    }\n    return 0;\n}","ahc005":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <utility>\n\nusing namespace std;\n\nconst int INF = 1e9;\nconst int dr[4] = {-1, 1, 0, 0};\nconst int dc[4] = {0, 0, -1, 1};\nconst char dir_char[4] = {'U', 'D', 'L', 'R'};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, si, sj;\n    cin >> N >> si >> sj;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> grid[i];\n    }\n\n    // assign indices to road squares\n    vector<vector<int>> idx(N, vector<int>(N, -1));\n    vector<int> row, col, w;\n    int V = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != '#') {\n                idx[i][j] = V;\n                row.push_back(i);\n                col.push_back(j);\n                w.push_back(grid[i][j] - '0');\n                ++V;\n            }\n        }\n    }\n\n    // ---------- horizontal segments ----------\n    vector<int> seg_id_h(V, -1);\n    vector<vector<int>> seg_nodes_h;\n    int h_cnt = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != '#' && seg_id_h[idx[i][j]] == -1) {\n                int sid = h_cnt++;\n                seg_nodes_h.push_back({});\n                int jj = j;\n                while (jj < N && grid[i][jj] != '#') {\n                    int id = idx[i][jj];\n                    seg_id_h[id] = sid;\n                    seg_nodes_h[sid].push_back(id);\n                    ++jj;\n                }\n            }\n        }\n    }\n\n    // ---------- vertical segments ----------\n    vector<int> seg_id_v(V, -1);\n    vector<vector<int>> seg_nodes_v;\n    int v_cnt = 0;\n    for (int j = 0; j < N; ++j) {\n        for (int i = 0; i < N; ++i) {\n            if (grid[i][j] != '#' && seg_id_v[idx[i][j]] == -1) {\n                int sid = v_cnt++;\n                seg_nodes_v.push_back({});\n                int ii = i;\n                while (ii < N && grid[ii][j] != '#') {\n                    int id = idx[ii][j];\n                    seg_id_v[id] = sid;\n                    seg_nodes_v[sid].push_back(id);\n                    ++ii;\n                }\n            }\n        }\n    }\n\n    // choose the orientation with fewer segments\n    bool use_horiz = (h_cnt <= v_cnt);\n    int seg_cnt;\n    vector<int> seg_id(V);\n    vector<vector<int>> seg_nodes;\n    if (use_horiz) {\n        seg_cnt = h_cnt;\n        seg_id = seg_id_h;\n        seg_nodes = seg_nodes_h;\n    } else {\n        seg_cnt = v_cnt;\n        seg_id = seg_id_v;\n        seg_nodes = seg_nodes_v;\n    }\n\n    int start_idx = idx[si][sj];\n    int start_seg = seg_id[start_idx];\n    vector<bool> seg_visited(seg_cnt, false);\n    seg_visited[start_seg] = true;\n    int remaining = seg_cnt - 1;\n\n    string moves;\n    int cur = start_idx;\n\n    // Dijkstra from a source, filling dist and pred\n    auto dijkstra = [&](int src, vector<int>& dist, vector<int>& pred) {\n        dist.assign(V, INF);\n        pred.assign(V, -1);\n        dist[src] = 0;\n        using P = pair<int, int>;\n        priority_queue<P, vector<P>, greater<P>> pq;\n        pq.emplace(0, src);\n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop();\n            if (d != dist[u]) continue;\n            int r = row[u], c = col[u];\n            for (int k = 0; k < 4; ++k) {\n                int nr = r + dr[k];\n                int nc = c + dc[k];\n                if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n                int v = idx[nr][nc];\n                if (v == -1) continue;\n                int nd = d + w[v];\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    pred[v] = u;\n                    pq.emplace(nd, v);\n                }\n            }\n        }\n    };\n\n    // main loop: visit all segments\n    while (remaining > 0) {\n        vector<int> dist(V), pred(V);\n        dijkstra(cur, dist, pred);\n\n        // find the closest unvisited segment and its closest square\n        int best_seg = -1, best_node = -1, best_dist = INF;\n        for (int s = 0; s < seg_cnt; ++s) {\n            if (seg_visited[s]) continue;\n            int min_d = INF, node = -1;\n            for (int v : seg_nodes[s]) {\n                if (dist[v] < min_d) {\n                    min_d = dist[v];\n                    node = v;\n                }\n            }\n            if (min_d < best_dist) {\n                best_dist = min_d;\n                best_seg = s;\n                best_node = node;\n            }\n        }\n\n        // reconstruct the path from cur to best_node\n        vector<int> path;\n        for (int v = best_node; v != cur; v = pred[v]) {\n            path.push_back(v);\n        }\n        path.push_back(cur);\n        reverse(path.begin(), path.end());   // now path[0] = cur, path[last] = best_node\n\n        // walk along the path, record moves and mark newly visited segments\n        for (size_t i = 0; i + 1 < path.size(); ++i) {\n            int from = path[i];\n            int to = path[i+1];\n            int dr = row[to] - row[from];\n            int dc = col[to] - col[from];\n            char move;\n            if (dr == -1) move = 'U';\n            else if (dr == 1) move = 'D';\n            else if (dc == -1) move = 'L';\n            else if (dc == 1) move = 'R';\n            else { /* should not happen */ }\n            moves += move;\n            int s = seg_id[to];\n            if (!seg_visited[s]) {\n                seg_visited[s] = true;\n                --remaining;\n            }\n        }\n        cur = best_node;\n    }\n\n    // return to the start square\n    if (cur != start_idx) {\n        vector<int> dist(V), pred(V);\n        dijkstra(cur, dist, pred);\n        vector<int> path;\n        for (int v = start_idx; v != cur; v = pred[v]) {\n            path.push_back(v);\n        }\n        path.push_back(cur);\n        reverse(path.begin(), path.end());\n        for (size_t i = 0; i + 1 < path.size(); ++i) {\n            int from = path[i];\n            int to = path[i+1];\n            int dr = row[to] - row[from];\n            int dc = col[to] - col[from];\n            char move;\n            if (dr == -1) move = 'U';\n            else if (dr == 1) move = 'D';\n            else if (dc == -1) move = 'L';\n            else if (dc == 1) move = 'R';\n            moves += move;\n        }\n    }\n\n    cout << moves << '\\n';\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K, R;\n    cin >> N >> M >> K >> R;\n    \n    vector<vector<int>> d(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\n    vector<vector<int>> succ(N);\n    vector<int> prereq_count(N, 0);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        succ[u].push_back(v);\n        ++prereq_count[v];\n    }\n\n    vector<int> out_degree(N);\n    for (int i = 0; i < N; ++i) {\n        out_degree[i] = succ[i].size();\n    }\n\n    vector<int> task_status(N, -1);\n    vector<int> task_start_day(N, -1);\n    vector<int> prereq_rem = prereq_count;\n    vector<int> member_task(M, -1);\n    \n    vector<vector<double>> est_s(M, vector<double>(K));\n    for (int j = 0; j < M; ++j) {\n        for (int k = 0; k < K; ++k) {\n            double sum = 0.0;\n            for (int i = 0; i < N; ++i) sum += d[i][k];\n            est_s[j][k] = sum / N;\n        }\n    }\n\n    int day = 0;\n    while (true) {\n        ++day;\n        if (day > 2000) break;\n\n        if (day > 1) {\n            int n;\n            cin >> n;\n            if (n == -1) break;\n            for (int i = 0; i < n; ++i) {\n                int f;\n                cin >> f;\n                --f;\n                int task = member_task[f];\n                if (task != -1) {\n                    task_status[task] = 1;\n                    int t_obs = (day - 1) - task_start_day[task] + 1;\n                    \n                    double w_pred = 0.0;\n                    int deficit_count = 0;\n                    for (int k = 0; k < K; ++k) {\n                        if (d[task][k] > est_s[f][k]) {\n                            w_pred += d[task][k] - est_s[f][k];\n                            ++deficit_count;\n                        }\n                    }\n                    \n                    if (t_obs > 1) {\n                        double error = t_obs - w_pred;\n                        if (deficit_count > 0 && abs(error) > 1e-9) {\n                            double delta = error / deficit_count;\n                            for (int k = 0; k < K; ++k) {\n                                if (d[task][k] > est_s[f][k]) {\n                                    est_s[f][k] = max(0.0, est_s[f][k] - delta);\n                                }\n                            }\n                        }\n                    } else {\n                        if (w_pred > 0 && deficit_count > 0) {\n                            double delta = w_pred / deficit_count;\n                            for (int k = 0; k < K; ++k) {\n                                if (d[task][k] > est_s[f][k]) {\n                                    est_s[f][k] = min(double(d[task][k]), est_s[f][k] + delta);\n                                }\n                            }\n                        }\n                    }\n                    \n                    for (int s : succ[task]) {\n                        --prereq_rem[s];\n                    }\n                    member_task[f] = -1;\n                }\n            }\n        }\n\n        vector<int> free_members;\n        for (int j = 0; j < M; ++j) {\n            if (member_task[j] == -1) free_members.push_back(j);\n        }\n\n        vector<int> ready_tasks;\n        for (int i = 0; i < N; ++i) {\n            if (task_status[i] == -1 && prereq_rem[i] == 0) {\n                ready_tasks.push_back(i);\n            }\n        }\n\n        if (free_members.empty() || ready_tasks.empty()) {\n            cout << \"0\\n\";\n            cout.flush();\n            continue;\n        }\n\n        sort(ready_tasks.begin(), ready_tasks.end(), [&](int a, int b) {\n            return out_degree[a] > out_degree[b];\n        });\n\n        vector<pair<int, int>> assignments;\n        for (int task : ready_tasks) {\n            if (free_members.empty()) break;\n            int best_member = -1;\n            double best_t = 1e18;\n            for (int j : free_members) {\n                double w = 0.0;\n                for (int k = 0; k < K; ++k) {\n                    if (d[task][k] > est_s[j][k]) {\n                        w += d[task][k] - est_s[j][k];\n                    }\n                }\n                double t_pred = max(1.0, w);\n                if (t_pred < best_t) {\n                    best_t = t_pred;\n                    best_member = j;\n                }\n            }\n            if (best_member != -1) {\n                task_status[task] = 0;\n                task_start_day[task] = day;\n                member_task[best_member] = task;\n                assignments.emplace_back(best_member, task);\n                free_members.erase(find(free_members.begin(), free_members.end(), best_member));\n            }\n        }\n\n        cout << assignments.size();\n        for (auto [member, task] : assignments) {\n            cout << ' ' << member + 1 << ' ' << task + 1;\n        }\n        cout << '\\n';\n        cout.flush();\n    }\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point {\n    int x, y;\n    Point() {}\n    Point(int x, int y) : x(x), y(y) {}\n};\n\nint manhattan(const Point& a, const Point& b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    // Read 1000 orders\n    vector<Point> restaurants(1000), destinations(1000);\n    for (int i = 0; i < 1000; ++i) {\n        cin >> restaurants[i].x >> restaurants[i].y >> destinations[i].x >> destinations[i].y;\n    }\n\n    const Point depot(400, 400);\n\n    // Step 1: Select 50 orders closest to depot\n    vector<int> order_cost(1000);\n    for (int i = 0; i < 1000; ++i) {\n        order_cost[i] = manhattan(depot, restaurants[i]) + manhattan(depot, destinations[i]);\n    }\n    vector<int> indices(1000);\n    iota(indices.begin(), indices.end(), 0);\n    sort(indices.begin(), indices.end(), [&](int i, int j) {\n        return order_cost[i] < order_cost[j];\n    });\n\n    vector<int> selected_orders;\n    for (int i = 0; i < 50; ++i) {\n        selected_orders.push_back(indices[i]);\n    }\n\n    // Create points for selected orders\n    vector<Point> points;\n    vector<pair<int, int>> point_info; // (order_index, type) type: 0=pickup, 1=delivery\n    for (int i = 0; i < 50; ++i) {\n        int order_idx = selected_orders[i];\n        points.push_back(restaurants[order_idx]);\n        point_info.push_back({i, 0});\n        points.push_back(destinations[order_idx]);\n        point_info.push_back({i, 1});\n    }\n\n    // Step 2: Initial route using nearest neighbor with precedence\n    vector<bool> picked(50, false), delivered(50, false);\n    Point cur = depot;\n    vector<int> sequence; // point indices in visit order\n\n    while (sequence.size() < 100) {\n        int best_idx = -1;\n        int best_dist = INT_MAX;\n\n        // Consider available pickups\n        for (int i = 0; i < 50; ++i) {\n            if (!picked[i]) {\n                int d = manhattan(cur, points[i * 2]);\n                if (d < best_dist) {\n                    best_dist = d;\n                    best_idx = i * 2;\n                }\n            }\n            // Consider available deliveries\n            if (picked[i] && !delivered[i]) {\n                int d = manhattan(cur, points[i * 2 + 1]);\n                if (d < best_dist) {\n                    best_dist = d;\n                    best_idx = i * 2 + 1;\n                }\n            }\n        }\n\n        sequence.push_back(best_idx);\n        cur = points[best_idx];\n        if (point_info[best_idx].second == 0) {\n            picked[point_info[best_idx].first] = true;\n        } else {\n            delivered[point_info[best_idx].first] = true;\n        }\n    }\n\n    // Step 3: Improve with 2-opt local search\n    const int n = 100;\n    vector<vector<int>> dist_mat(n, vector<int>(n));\n    vector<int> dist_to_depot(n);\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            dist_mat[i][j] = manhattan(points[i], points[j]);\n        }\n        dist_to_depot[i] = manhattan(points[i], depot);\n    }\n\n    auto is_feasible = [&](const vector<int>& seq) {\n        vector<int> first_pickup(50, -1);\n        vector<int> first_delivery(50, -1);\n        for (int idx = 0; idx < seq.size(); ++idx) {\n            int point_idx = seq[idx];\n            auto [order, type] = point_info[point_idx];\n            if (type == 0 && first_pickup[order] == -1) {\n                first_pickup[order] = idx;\n            }\n            if (type == 1 && first_delivery[order] == -1) {\n                first_delivery[order] = idx;\n            }\n        }\n        for (int i = 0; i < 50; ++i) {\n            if (first_pickup[i] > first_delivery[i]) {\n                return false;\n            }\n        }\n        return true;\n    };\n\n    vector<int> seq = sequence;\n    bool improved = true;\n    int passes = 0;\n    while (improved && passes < 100) {\n        improved = false;\n        passes++;\n        for (int i = 0; i < n - 1; ++i) {\n            for (int j = i + 1; j < n; ++j) {\n                int a = seq[i];\n                int b = seq[i + 1];\n                int c = seq[j];\n                int d = (j + 1 < n) ? seq[j + 1] : -1;\n\n                int old_len = dist_mat[a][b];\n                if (d == -1) old_len += dist_to_depot[c];\n                else old_len += dist_mat[c][d];\n\n                int new_len = dist_mat[a][c];\n                if (d == -1) new_len += dist_to_depot[b];\n                else new_len += dist_mat[b][d];\n\n                if (new_len < old_len) {\n                    vector<int> new_seq = seq;\n                    reverse(new_seq.begin() + i + 1, new_seq.begin() + j + 1);\n                    if (is_feasible(new_seq)) {\n                        seq = new_seq;\n                        improved = true;\n                        break;\n                    }\n                }\n            }\n            if (improved) break;\n        }\n    }\n\n    // Step 4: Output results\n    cout << 50 << \" \";\n    for (int i = 0; i < 50; ++i) {\n        cout << selected_orders[i] + 1 << \" \";\n    }\n    cout << \"\\n\";\n\n    cout << 102 << \" 400 400 \";\n    for (int idx : seq) {\n        cout << points[idx].x << \" \" << points[idx].y << \" \";\n    }\n    cout << \"400 400\\n\";\n\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Edge {\n    int u, v, d;\n};\n\nstruct DSU {\n    vector<int> parent, sz;\n    DSU(int n) : parent(n), sz(n, 1) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        if (parent[x] != x) parent[x] = find(parent[x]);\n        return parent[x];\n    }\n    bool unite(int x, int y) {\n        x = find(x), y = find(y);\n        if (x == y) return false;\n        if (sz[x] < sz[y]) swap(x, y);\n        parent[y] = x;\n        sz[x] += sz[y];\n        return true;\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(N), y(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> x[i] >> y[i];\n    }\n\n    const int M = 5 * (N - 1);   // 1995\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        int dx = x[u] - x[v];\n        int dy = y[u] - y[v];\n        double dist = sqrt(dx * dx + dy * dy);\n        int d = (int)(dist + 0.5);   // round to nearest integer\n        edges[i] = {u, v, d};\n    }\n\n    // Precompute for each edge whether it is a bridge in the suffix graph (edges i..M-1)\n    vector<bool> is_bridge(M, false);\n    for (int i = 0; i < M; ++i) {\n        // build adjacency for edges i..M-1\n        vector<vector<pair<int, int>>> adj(N);\n        for (int j = i; j < M; ++j) {\n            int u = edges[j].u, v = edges[j].v;\n            adj[u].emplace_back(v, j);\n            adj[v].emplace_back(u, j);\n        }\n\n        vector<int> disc(N, -1), low(N, -1);\n        int timer = 0;\n        vector<bool> bridge_this(M, false);\n\n        function<void(int, int)> dfs = [&](int v, int parent_edge) {\n            disc[v] = low[v] = timer++;\n            for (auto [to, id] : adj[v]) {\n                if (id == parent_edge) continue;\n                if (disc[to] == -1) {\n                    dfs(to, id);\n                    low[v] = min(low[v], low[to]);\n                    if (low[to] > disc[v]) {\n                        bridge_this[id] = true;\n                    }\n                } else {\n                    low[v] = min(low[v], disc[to]);\n                }\n            }\n        };\n\n        for (int v = 0; v < N; ++v) {\n            if (disc[v] == -1) {\n                dfs(v, -1);\n            }\n        }\n        is_bridge[i] = bridge_this[i];\n    }\n\n    DSU dsu(N);\n    for (int i = 0; i < M; ++i) {\n        int l;\n        cin >> l;\n        int u = edges[i].u, v = edges[i].v;\n        bool accept = false;\n        if (dsu.find(u) == dsu.find(v)) {\n            accept = false;   // would create a cycle\n        } else {\n            if (is_bridge[i]) {\n                accept = true;   // forced to keep connectivity\n            } else {\n                // accept if weight is at most twice the lower bound (mean)\n                if (l <= 2 * edges[i].d) {\n                    accept = true;\n                } else {\n                    accept = false;\n                }\n            }\n        }\n        cout << (accept ? 1 : 0) << endl;\n        if (accept) {\n            dsu.unite(u, v);\n        }\n    }\n    return 0;\n}","ahc008":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <string>\n#include <algorithm>\n#include <utility>\n\nusing namespace std;\n\nconst int MAXN = 30;\nconst int dirs[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N;\n    vector<pair<int, int>> pets(N);\n    vector<int> pet_types(N);\n    for (int i = 0; i < N; ++i) {\n        int x, y, t;\n        cin >> x >> y >> t;\n        pets[i] = {x - 1, y - 1};\n        pet_types[i] = t;\n    }\n    cin >> M;\n    vector<pair<int, int>> humans(M);\n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        humans[i] = {x - 1, y - 1};\n    }\n\n    // grid state\n    bool wall[MAXN][MAXN] = {false};\n    bool to_build[MAXN][MAXN] = {false};\n    int owner[MAXN][MAXN];\n\n    // compute Voronoi owner based on initial human positions\n    for (int x = 0; x < MAXN; ++x) {\n        for (int y = 0; y < MAXN; ++y) {\n            int best_dist = 1000000, best_idx = -1;\n            for (int i = 0; i < M; ++i) {\n                int d = abs(x - humans[i].first) + abs(y - humans[i].second);\n                if (d < best_dist) {\n                    best_dist = d;\n                    best_idx = i;\n                }\n            }\n            owner[x][y] = best_idx;\n        }\n    }\n\n    // mark cells that should become walls (boundary between regions)\n    for (int x = 0; x < MAXN; ++x) {\n        for (int y = 0; y < MAXN; ++y) {\n            // skip human cells\n            bool is_human = false;\n            for (int i = 0; i < M; ++i) {\n                if (humans[i].first == x && humans[i].second == y) {\n                    is_human = true;\n                    break;\n                }\n            }\n            if (is_human) continue;\n\n            // check if any neighbor has different owner\n            bool boundary = false;\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 >= MAXN || ny < 0 || ny >= MAXN) continue;\n                if (owner[nx][ny] != owner[x][y]) {\n                    boundary = true;\n                    break;\n                }\n            }\n            if (boundary) {\n                to_build[x][y] = true;\n            }\n        }\n    }\n\n    // main loop for 300 turns\n    for (int turn = 0; turn < 300; ++turn) {\n        string actions(M, '.');\n\n        // decide actions for each human\n        for (int i = 0; i < M; ++i) {\n            int sx = humans[i].first, sy = humans[i].second;\n\n            // BFS on passable cells (owner == i, not wall, not to_build)\n            vector<vector<int>> dist(MAXN, vector<int>(MAXN, -1));\n            vector<vector<pair<int, int>>> parent(MAXN, vector<pair<int, int>>(MAXN, {-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 + dirs[d][0], ny = y + dirs[d][1];\n                    if (nx < 0 || nx >= MAXN || ny < 0 || ny >= MAXN) continue;\n                    if (owner[nx][ny] != i) continue;\n                    if (wall[nx][ny] || to_build[nx][ny]) continue;\n                    if (dist[nx][ny] != -1) continue;\n                    dist[nx][ny] = dist[x][y] + 1;\n                    parent[nx][ny] = {x, y};\n                    q.push({nx, ny});\n                }\n            }\n\n            // find the farthest reachable wall cell (to avoid trapping the human)\n            int best_wall_x = -1, best_wall_y = -1;\n            int best_adj_x = -1, best_adj_y = -1;\n            int best_dist = -1;\n\n            for (int x = 0; x < MAXN; ++x) {\n                for (int y = 0; y < MAXN; ++y) {\n                    if (!to_build[x][y] || wall[x][y]) continue;\n                    if (owner[x][y] != i) continue;  // only walls owned by this human\n                    // check each neighbor that is passable\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 >= MAXN || ny < 0 || ny >= MAXN) continue;\n                        if (owner[nx][ny] != i) continue;\n                        if (wall[nx][ny] || to_build[nx][ny]) continue;\n                        if (dist[nx][ny] == -1) continue;  // unreachable\n                        if (dist[nx][ny] > best_dist) {\n                            best_dist = dist[nx][ny];\n                            best_wall_x = x;\n                            best_wall_y = y;\n                            best_adj_x = nx;\n                            best_adj_y = ny;\n                        }\n                    }\n                }\n            }\n\n            if (best_wall_x == -1) {\n                // no reachable wall cell \u2192 stay\n                actions[i] = '.';\n                continue;\n            }\n\n            // if already adjacent to the target wall cell, try to build\n            if (abs(sx - best_wall_x) + abs(sy - best_wall_y) == 1) {\n                bool safe = true;\n                // check that no pet is on the wall cell itself\n                for (const auto& p : pets) {\n                    if (p.first == best_wall_x && p.second == best_wall_y) {\n                        safe = false;\n                        break;\n                    }\n                }\n                // check that no pet is adjacent to the wall cell\n                if (safe) {\n                    for (int d = 0; d < 4; ++d) {\n                        int nx = best_wall_x + dirs[d][0], ny = best_wall_y + dirs[d][1];\n                        if (nx < 0 || nx >= MAXN || ny < 0 || ny >= MAXN) continue;\n                        for (const auto& p : pets) {\n                            if (p.first == nx && p.second == ny) {\n                                safe = false;\n                                break;\n                            }\n                        }\n                        if (!safe) break;\n                    }\n                }\n                if (safe) {\n                    // output build action\n                    if (best_wall_x == sx - 1 && best_wall_y == sy) actions[i] = 'u';\n                    else if (best_wall_x == sx + 1 && best_wall_y == sy) actions[i] = 'd';\n                    else if (best_wall_x == sx && best_wall_y == sy - 1) actions[i] = 'l';\n                    else if (best_wall_x == sx && best_wall_y == sy + 1) actions[i] = 'r';\n                    else actions[i] = '.';  // should not happen\n                } else {\n                    actions[i] = '.';  // not safe, wait\n                }\n            } else {\n                // move one step towards the adjacent cell of the target wall\n                pair<int, int> next = {best_adj_x, best_adj_y};\n                while (parent[next.first][next.second] != make_pair(sx, sy)) {\n                    next = parent[next.first][next.second];\n                }\n                // determine move character\n                if (next.first == sx - 1 && next.second == sy) actions[i] = 'U';\n                else if (next.first == sx + 1 && next.second == sy) actions[i] = 'D';\n                else if (next.first == sx && next.second == sy - 1) actions[i] = 'L';\n                else if (next.first == sx && next.second == sy + 1) actions[i] = 'R';\n                else actions[i] = '.';  // should not happen\n            }\n        }\n\n        // output actions for this turn\n        cout << actions << endl;\n        cout.flush();\n\n        // apply human actions to update internal state\n        for (int i = 0; i < M; ++i) {\n            char act = actions[i];\n            int x = humans[i].first, y = humans[i].second;\n            if (act == 'u' || act == 'd' || act == 'l' || act == 'r') {\n                // build wall\n                int wx = x, wy = y;\n                if (act == 'u') wx = x - 1;\n                else if (act == 'd') wx = x + 1;\n                else if (act == 'l') wy = y - 1;\n                else if (act == 'r') wy = y + 1;\n                wall[wx][wy] = true;\n                to_build[wx][wy] = false;\n            } else if (act == 'U' || act == 'D' || act == 'L' || act == 'R') {\n                // move\n                if (act == 'U') humans[i].first = x - 1;\n                else if (act == 'D') humans[i].first = x + 1;\n                else if (act == 'L') humans[i].second = y - 1;\n                else if (act == 'R') humans[i].second = y + 1;\n            }\n            // '.' does nothing\n        }\n\n        // read pet movements for this turn\n        vector<string> pet_moves(N);\n        for (int i = 0; i < N; ++i) {\n            cin >> pet_moves[i];\n        }\n\n        // update pet positions\n        for (int i = 0; i < N; ++i) {\n            int x = pets[i].first, y = pets[i].second;\n            for (char c : pet_moves[i]) {\n                if (c == 'U') --x;\n                else if (c == 'D') ++x;\n                else if (c == 'L') --y;\n                else if (c == 'R') ++y;\n                // '.' does nothing\n            }\n            pets[i] = {x, y};\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cstring>\n#include <algorithm>\nusing namespace std;\n\nconst int N = 20;                 // grid size\nconst int L = 200;                // maximum allowed length\nconst int STATES = N * N;         // number of cells\n\nint neighbor[STATES][4];          // -1 if wall, otherwise target cell id\ndouble V[STATES][L + 1];          // V[state][rem] : optimal expected score with rem steps left\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // ----- input -----\n    int si, sj, ti, tj;\n    double p;\n    cin >> si >> sj >> ti >> tj >> p;\n\n    vector<string> h(N);          // horizontal walls, 20 lines of 19 chars\n    for (int i = 0; i < N; ++i) cin >> h[i];\n    vector<string> v(N - 1);      // vertical walls, 19 lines of 20 chars\n    for (int i = 0; i < N - 1; ++i) cin >> v[i];\n\n    // ----- build neighbour table -----\n    memset(neighbor, -1, sizeof(neighbor));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int id = i * N + j;\n            // up\n            if (i > 0 && v[i - 1][j] == '0')\n                neighbor[id][0] = (i - 1) * N + j;\n            // down\n            if (i < N - 1 && v[i][j] == '0')\n                neighbor[id][1] = (i + 1) * N + j;\n            // left\n            if (j > 0 && h[i][j - 1] == '0')\n                neighbor[id][2] = i * N + (j - 1);\n            // right\n            if (j < N - 1 && h[i][j] == '0')\n                neighbor[id][3] = i * N + (j + 1);\n        }\n    }\n\n    int start_id = si * N + sj;\n    int goal_id  = ti * N + tj;\n\n    // ----- DP for optimal closed\u2011loop value -----\n    // initialise with zeros (rem = 0)\n    for (int s = 0; s < STATES; ++s)\n        for (int r = 0; r <= L; ++r)\n            V[s][r] = 0.0;\n\n    for (int rem = 1; rem <= L; ++rem) {\n        double reward_reach = 200.0 + rem;   // 401 - (200 - rem + 1)\n        for (int s = 0; s < STATES; ++s) {\n            if (s == goal_id) {               // already at goal \u2013 no further reward\n                V[s][rem] = 0.0;\n                continue;\n            }\n            double best = 0.0;\n            for (int a = 0; a < 4; ++a) {\n                int nb = neighbor[s][a];\n                bool wall = (nb == -1);\n                double stay_prob = p + (1 - p) * wall;\n                double move_prob = (1 - p) * (1 - wall);\n                double expected = stay_prob * V[s][rem - 1];\n                if (!wall) {\n                    if (nb == goal_id) {\n                        expected += move_prob * reward_reach;\n                    } else {\n                        expected += move_prob * V[nb][rem - 1];\n                    }\n                }\n                if (expected > best) best = expected;\n            }\n            V[s][rem] = best;\n        }\n    }\n\n    // ----- greedy construction of the memorized string -----\n    vector<double> bel(STATES, 0.0);\n    bel[start_id] = 1.0;\n    string ans;\n    const char dir_chars[] = \"UDLR\";   // index: 0:U, 1:D, 2:L, 3:R\n\n    for (int step = 1; step <= L; ++step) {\n        int rem = L - (step - 1);       // steps still available before this action\n        int best_action = 0;\n        double best_val = -1e100;\n\n        // evaluate each possible action\n        for (int a = 0; a < 4; ++a) {\n            double total = 0.0;\n            for (int s = 0; s < STATES; ++s) {\n                double prob = bel[s];\n                if (prob == 0.0) continue;\n                int nb = neighbor[s][a];\n                bool wall = (nb == -1);\n                double stay_prob = p + (1 - p) * wall;\n                double move_prob = (1 - p) * (1 - wall);\n                double val = stay_prob * V[s][rem - 1];\n                if (!wall) {\n                    if (nb == goal_id) {\n                        val += move_prob * (200.0 + rem);   // immediate reward\n                    } else {\n                        val += move_prob * V[nb][rem - 1];\n                    }\n                }\n                total += prob * val;\n            }\n            if (total > best_val) {\n                best_val = total;\n                best_action = a;\n            }\n        }\n\n        ans.push_back(dir_chars[best_action]);\n\n        // update belief distribution after performing best_action\n        vector<double> new_bel(STATES, 0.0);\n        for (int s = 0; s < STATES; ++s) {\n            double prob = bel[s];\n            if (prob == 0.0) continue;\n            int nb = neighbor[s][best_action];\n            bool wall = (nb == -1);\n            double stay_prob = p + (1 - p) * wall;\n            double move_prob = (1 - p) * (1 - wall);\n            // staying (forget or wall)\n            new_bel[s] += prob * stay_prob;\n            if (!wall) {\n                if (nb != goal_id) {   // moving to goal terminates the process\n                    new_bel[nb] += prob * move_prob;\n                }\n                // mass that reaches goal is discarded\n            }\n        }\n        bel.swap(new_bel);\n    }\n\n    cout << ans << endl;\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30;\nconst int D = 4; // 0: left, 1: up, 2: right, 3: down\nconst int di[D] = {0, -1, 0, 1};\nconst int dj[D] = {-1, 0, 1, 0};\n\n// to[t][d] = exit direction when entering from d, or -1 if impossible\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\nint type[N][N];\nint rot[N][N];\nint best_rot[N][N];\nint best_score = 0;\n\ninline int get_exit(int t, int r, int d) {\n    int d_in = ((d - r) + 4) & 3;\n    int e = to[t][d_in];\n    if (e == -1) return -1;\n    return (e + r) & 3;\n}\n\nint compute_score(const int rot[N][N]) {\n    int status[N][N][D] = {0}; // 0: unvisited, 1: visiting, 2: processed\n    vector<int> cycles;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            for (int d = 0; d < D; ++d) {\n                if (status[i][j][d]) continue;\n                int t = type[i][j];\n                int r = rot[i][j];\n                if (get_exit(t, r, d) == -1) {\n                    status[i][j][d] = 2;\n                    continue;\n                }\n\n                vector<array<int, 3>> path;\n                int ci = i, cj = j, cd = d;\n                while (true) {\n                    if (status[ci][cj][cd] == 2) {\n                        for (auto& s : path) status[s[0]][s[1]][s[2]] = 2;\n                        break;\n                    }\n                    if (status[ci][cj][cd] == 1) {\n                        // cycle found\n                        int idx = -1;\n                        for (int k = 0; k < (int)path.size(); ++k) {\n                            if (path[k][0] == ci && path[k][1] == cj && path[k][2] == cd) {\n                                idx = k;\n                                break;\n                            }\n                        }\n                        int len = path.size() - idx;\n                        cycles.push_back(len);\n                        for (auto& s : path) status[s[0]][s[1]][s[2]] = 2;\n                        break;\n                    }\n                    status[ci][cj][cd] = 1;\n                    path.push_back({ci, cj, cd});\n\n                    // compute next state\n                    int t2 = type[ci][cj];\n                    int r2 = rot[ci][cj];\n                    int d2 = get_exit(t2, r2, cd);\n                    if (d2 == -1) {\n                        for (auto& s : path) status[s[0]][s[1]][s[2]] = 2;\n                        break;\n                    }\n                    int ni = ci + di[d2];\n                    int nj = cj + dj[d2];\n                    if (ni < 0 || ni >= N || nj < 0 || nj >= N) {\n                        for (auto& s : path) status[s[0]][s[1]][s[2]] = 2;\n                        break;\n                    }\n                    int nd = (d2 + 2) & 3;\n                    if (get_exit(type[ni][nj], rot[ni][nj], nd) == -1) {\n                        for (auto& s : path) status[s[0]][s[1]][s[2]] = 2;\n                        break;\n                    }\n                    ci = ni; cj = nj; cd = nd;\n                }\n            }\n        }\n    }\n\n    sort(cycles.rbegin(), cycles.rend());\n    if (cycles.size() < 2) return 0;\n    return cycles[0] * cycles[1];\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // read input\n    for (int i = 0; i < N; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; ++j) {\n            type[i][j] = s[j] - '0';\n        }\n    }\n\n    // random number generator\n    random_device rd;\n    mt19937 rng(rd());\n    uniform_real_distribution<double> uni(0.0, 1.0);\n    uniform_int_distribution<int> rand_tile(0, N-1);\n    uniform_int_distribution<int> rand_rot(0, 3);\n\n    // initialize rotations randomly\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            rot[i][j] = rand_rot(rng);\n\n    int current_score = compute_score(rot);\n    best_score = current_score;\n    memcpy(best_rot, rot, sizeof(rot));\n\n    // simulated annealing parameters\n    const int max_iter = 20000;\n    const double T0 = 1000.0;\n    double T = T0;\n\n    for (int iter = 0; iter < max_iter; ++iter) {\n        // pick a random tile\n        int i = rand_tile(rng);\n        int j = rand_tile(rng);\n        int old_r = rot[i][j];\n        int new_r = (old_r + 1 + rand_rot(rng)) % 4; // different rotation\n        rot[i][j] = new_r;\n\n        int new_score = compute_score(rot);\n        double delta = new_score - current_score;\n        if (delta > 0 || uni(rng) < exp(delta / T)) {\n            current_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            rot[i][j] = old_r; // revert\n        }\n\n        // cool down\n        T = T0 * (1.0 - iter / (double)max_iter);\n    }\n\n    // output best rotations as a string of 900 characters\n    string ans;\n    ans.reserve(N * N);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            ans += char('0' + best_rot[i][j]);\n    cout << ans << endl;\n\n    return 0;\n}","ahc011":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <cstring>\n#include <stack>\n\nusing namespace std;\n\nint N, T;\nint board[10][10];\nint empty_r, empty_c;\nint total_tiles; // N*N-1\n\n// precomputed bits for patterns 0..15\nbool has_up[16], has_down[16], has_left[16], has_right[16];\n\nvoid precompute_bits() {\n    for (int p = 0; p < 16; ++p) {\n        has_left[p]  = p & 1;\n        has_up[p]    = p & 2;\n        has_right[p] = p & 4;\n        has_down[p]  = p & 8;\n    }\n}\n\n// convert hex char to integer\nint hex_to_int(char c) {\n    if ('0' <= c && c <= '9') return c - '0';\n    return 10 + c - 'a';\n}\n\n// compute size of largest tree in the current board\nint compute_tree_size(int b[10][10]) {\n    bool vis[10][10] = {false};\n    int max_size = 0;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (b[i][j] == 0 || vis[i][j]) continue;\n\n            // DFS stack (encoded as i*N + j)\n            int stack[100];\n            int top = 0;\n            stack[top++] = i * N + j;\n            vis[i][j] = true;\n\n            int vertices = 0, edges = 0;\n            while (top) {\n                int pos = stack[--top];\n                int x = pos / N, y = pos % N;\n                ++vertices;\n                int p = b[x][y];\n\n                // up\n                if (has_up[p] && x > 0 && b[x-1][y] && has_down[b[x-1][y]]) {\n                    if (!vis[x-1][y]) {\n                        ++edges;\n                        vis[x-1][y] = true;\n                        stack[top++] = (x-1)*N + y;\n                    }\n                }\n                // down\n                if (has_down[p] && x+1 < N && b[x+1][y] && has_up[b[x+1][y]]) {\n                    if (!vis[x+1][y]) {\n                        ++edges;\n                        vis[x+1][y] = true;\n                        stack[top++] = (x+1)*N + y;\n                    }\n                }\n                // left\n                if (has_left[p] && y > 0 && b[x][y-1] && has_right[b[x][y-1]]) {\n                    if (!vis[x][y-1]) {\n                        ++edges;\n                        vis[x][y-1] = true;\n                        stack[top++] = x*N + (y-1);\n                    }\n                }\n                // right\n                if (has_right[p] && y+1 < N && b[x][y+1] && has_left[b[x][y+1]]) {\n                    if (!vis[x][y+1]) {\n                        ++edges;\n                        vis[x][y+1] = true;\n                        stack[top++] = x*N + (y+1);\n                    }\n                }\n            }\n\n            if (edges == vertices - 1) {\n                max_size = max(max_size, vertices);\n            }\n        }\n    }\n    return max_size;\n}\n\n// simulated annealing solver\nstring solve() {\n    precompute_bits();\n    total_tiles = N * N - 1;\n\n    // find initial empty position\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (board[i][j] == 0) {\n                empty_r = i;\n                empty_c = j;\n            }\n\n    // current state\n    int cur_board[10][10];\n    memcpy(cur_board, board, sizeof(board));\n    int cur_er = empty_r, cur_ec = empty_c;\n    int cur_S = compute_tree_size(cur_board);\n    string cur_moves = \"\";\n    int steps = 0;\n\n    // best state\n    int best_S = cur_S;\n    string best_moves = \"\";\n    int best_score;\n    if (cur_S == total_tiles)\n        best_score = (int)round(500000.0 * (2.0 - 0.0 / T));\n    else\n        best_score = (int)round(500000.0 * cur_S / total_tiles);\n\n    // SA parameters\n    double temp = 5.0;\n    const double cooling = 0.99995;\n    const double min_temp = 1e-3;\n\n    // random generators\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> dir_dist(0, 3);\n    uniform_real_distribution<double> prob_dist(0.0, 1.0);\n\n    // direction vectors and corresponding move characters\n    const int dr[4] = {-1, 1, 0, 0};\n    const int dc[4] = {0, 0, -1, 1};\n    const char move_char[4] = {'U', 'D', 'L', 'R'};\n\n    auto start_time = chrono::steady_clock::now();\n    const double time_limit = 2.9; // seconds\n    int iteration = 0;\n\n    while (steps < T) {\n        // time check every 20000 iterations\n        if ((iteration & 20000) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > time_limit) break;\n        }\n        ++iteration;\n\n        int dir = dir_dist(rng);\n        int nr = cur_er + dr[dir];\n        int nc = cur_ec + dc[dir];\n        if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n\n        // perform move\n        swap(cur_board[cur_er][cur_ec], cur_board[nr][nc]);\n        int new_S = compute_tree_size(cur_board);\n        double delta = new_S - cur_S;\n        bool accept = false;\n\n        if (delta > 0)\n            accept = true;\n        else if (temp > 1e-9) {\n            double prob = exp(delta / temp);\n            if (prob_dist(rng) < prob)\n                accept = true;\n        }\n\n        if (accept) {\n            cur_moves += move_char[dir];\n            ++steps;\n            cur_er = nr;\n            cur_ec = nc;\n            cur_S = new_S;\n\n            // if we reached a full tree, we are done (first full tree gives minimal K)\n            if (cur_S == total_tiles) {\n                best_moves = cur_moves;\n                break;\n            }\n\n            // otherwise update best score if improved\n            int K = steps;\n            int score;\n            if (cur_S == total_tiles)\n                score = (int)round(500000.0 * (2.0 - (double)K / T));\n            else\n                score = (int)round(500000.0 * cur_S / total_tiles);\n            if (score > best_score) {\n                best_score = score;\n                best_S = cur_S;\n                best_moves = cur_moves;\n            }\n        } else {\n            // revert move\n            swap(cur_board[cur_er][cur_ec], cur_board[nr][nc]);\n        }\n\n        // cool down\n        temp *= cooling;\n        if (temp < min_temp) temp = min_temp;\n    }\n\n    return best_moves;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> T;\n    for (int i = 0; i < N; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; ++j) {\n            board[i][j] = hex_to_int(s[j]);\n        }\n    }\n\n    string ans = solve();\n    cout << ans << endl;\n\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\nusing int64 = long long;\n\nstruct Line {\n    int64 px, py, qx, qy;\n    int64 dx, dy;\n};\n\nstruct ArrayHash {\n    size_t operator()(const array<uint64_t,2>& a) const {\n        return a[0] ^ (a[1] * 0x9e3779b97f4a7c15ULL);\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, K;\n    cin >> N >> K;\n    int a[11] = {0};\n    for (int d = 1; d <= 10; ++d) cin >> a[d];\n    vector<int64> xs(N), ys(N);\n    for (int i = 0; i < N; ++i) cin >> xs[i] >> ys[i];\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> coord_dist(-20000, 20000);\n    uniform_int_distribution<int> delta_dist(-5, 5);\n\n    // Helper to check that a line does not pass through any strawberry\n    auto is_valid_line = [&](const Line& line) -> bool {\n        if (line.px == line.qx && line.py == line.qy) return false;\n        for (int i = 0; i < N; ++i) {\n            int64 cross = line.dx * (ys[i] - line.py) - line.dy * (xs[i] - line.px);\n            if (cross == 0) return false;\n        }\n        return true;\n    };\n\n    // Helper to check that the line actually cuts the cake (distance < 10000)\n    auto line_cuts_circle = [&](const Line& line) -> bool {\n        int64 num = abs(line.qx * line.py - line.qy * line.px);\n        int64 len2 = line.dx * line.dx + line.dy * line.dy;\n        return num * num < 10000LL * 10000LL * len2;\n    };\n\n    // Generate initial K lines\n    vector<Line> lines(K);\n    for (int i = 0; i < K; ++i) {\n        while (true) {\n            Line line;\n            line.px = coord_dist(rng);\n            line.py = coord_dist(rng);\n            line.qx = coord_dist(rng);\n            line.qy = coord_dist(rng);\n            line.dx = line.qx - line.px;\n            line.dy = line.qy - line.py;\n            if (!is_valid_line(line)) continue;\n            if (!line_cuts_circle(line)) continue;\n            lines[i] = line;\n            break;\n        }\n    }\n\n    // Compute initial patterns and group counts\n    vector<array<uint64_t,2>> point_pat(N);\n    unordered_map<array<uint64_t,2>, int, ArrayHash> pat_cnt;\n    for (int i = 0; i < N; ++i) {\n        array<uint64_t,2> pat = {0, 0};\n        for (int l = 0; l < K; ++l) {\n            int side = (lines[l].dx * (ys[i] - lines[l].py) -\n                        lines[l].dy * (xs[i] - lines[l].px)) > 0 ? 1 : 0;\n            if (l < 64)\n                pat[0] |= (uint64_t(side) << l);\n            else\n                pat[1] |= (uint64_t(side) << (l - 64));\n        }\n        point_pat[i] = pat;\n        pat_cnt[pat]++;\n    }\n\n    int b[11] = {0};\n    for (auto& [pat, cnt] : pat_cnt) {\n        if (cnt >= 1 && cnt <= 10) b[cnt]++;\n    }\n\n    int current_score = 0;\n    for (int d = 1; d <= 10; ++d) current_score += min(a[d], b[d]);\n\n    // Simulated annealing parameters\n    double T = 50.0;\n    const double cooling = 0.9995;\n    const double large_prob = 0.01;\n    auto start_time = chrono::steady_clock::now();\n    const double time_limit = 2.8;  // seconds\n\n    for (int iter = 0; ; ++iter) {\n        // Time check every 1000 iterations\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 > time_limit) break;\n        }\n\n        int l = rng() % K;\n        bool large = (rng() % 100) < 1;\n\n        Line new_line;\n        bool valid = false;\n\n        if (!large) { // small perturbation\n            new_line = lines[l];\n            int which = rng() % 2;\n            if (which == 0) {\n                new_line.px += delta_dist(rng);\n                new_line.py += delta_dist(rng);\n            } else {\n                new_line.qx += delta_dist(rng);\n                new_line.qy += delta_dist(rng);\n            }\n            if (new_line.px == new_line.qx && new_line.py == new_line.qy) continue;\n            new_line.dx = new_line.qx - new_line.px;\n            new_line.dy = new_line.qy - new_line.py;\n            valid = true;\n            for (int i = 0; i < N; ++i) {\n                int64 cross = new_line.dx * (ys[i] - new_line.py) -\n                              new_line.dy * (xs[i] - new_line.px);\n                if (cross == 0) { valid = false; break; }\n            }\n        } else { // large change: completely new line\n            while (true) {\n                new_line.px = coord_dist(rng);\n                new_line.py = coord_dist(rng);\n                new_line.qx = coord_dist(rng);\n                new_line.qy = coord_dist(rng);\n                new_line.dx = new_line.qx - new_line.px;\n                new_line.dy = new_line.qy - new_line.py;\n                if (is_valid_line(new_line)) {\n                    valid = true;\n                    break;\n                }\n            }\n        }\n        if (!valid) continue;\n\n        // Apply changes incrementally\n        vector<pair<int, array<uint64_t,2>>> changed; // point index, old pattern\n\n        for (int i = 0; i < N; ++i) {\n            int64 cross = new_line.dx * (ys[i] - new_line.py) -\n                          new_line.dy * (xs[i] - new_line.px);\n            int new_side = cross > 0 ? 1 : 0;\n\n            // current side from pattern\n            uint64_t& low = point_pat[i][0];\n            uint64_t& high = point_pat[i][1];\n            int old_side;\n            if (l < 64) old_side = (low >> l) & 1;\n            else old_side = (high >> (l - 64)) & 1;\n\n            if (old_side == new_side) continue;\n\n            array<uint64_t,2> old_pat = {low, high};\n\n            // toggle the bit for line l\n            if (l < 64) low ^= (1ULL << l);\n            else high ^= (1ULL << (l - 64));\n            array<uint64_t,2> new_pat = {low, high};\n\n            // update map and b for old_pat -> new_pat\n            // decrement old_pat\n            auto it = pat_cnt.find(old_pat);\n            int c_old = it->second;\n            if (c_old >= 1 && c_old <= 10) b[c_old]--;\n            if (--c_old == 0) pat_cnt.erase(it);\n            else it->second = c_old;\n\n            // increment new_pat\n            auto it2 = pat_cnt.find(new_pat);\n            if (it2 != pat_cnt.end()) {\n                int c_new = it2->second;\n                if (c_new >= 1 && c_new <= 10) b[c_new]--;\n                it2->second = c_new + 1;\n                c_new++;\n                if (c_new >= 1 && c_new <= 10) b[c_new]++;\n            } else {\n                pat_cnt[new_pat] = 1;\n                if (1 <= 10) b[1]++;\n            }\n\n            changed.emplace_back(i, old_pat);\n        }\n\n        // Compute new score\n        int new_score = 0;\n        for (int d = 1; d <= 10; ++d) new_score += min(a[d], b[d]);\n\n        // Acceptance test\n        bool accept = false;\n        if (new_score >= current_score) {\n            accept = true;\n        } else {\n            double delta = new_score - current_score;\n            double prob = exp(delta / T);\n            uniform_real_distribution<double> real_dist(0.0, 1.0);\n            if (real_dist(rng) < prob) accept = true;\n        }\n\n        if (accept) {\n            lines[l] = new_line;\n            current_score = new_score;\n        } else {\n            // Revert all changes\n            for (auto& p : changed) {\n                int i = p.first;\n                array<uint64_t,2> old_pat = p.second;\n                array<uint64_t,2> new_pat = point_pat[i]; // current\n\n                // decrement new_pat\n                auto it = pat_cnt.find(new_pat);\n                int c_new = it->second;\n                if (c_new >= 1 && c_new <= 10) b[c_new]--;\n                if (--c_new == 0) pat_cnt.erase(it);\n                else it->second = c_new;\n\n                // increment old_pat\n                auto it2 = pat_cnt.find(old_pat);\n                if (it2 != pat_cnt.end()) {\n                    int c_old = it2->second;\n                    if (c_old >= 1 && c_old <= 10) b[c_old]--;\n                    it2->second = c_old + 1;\n                    c_old++;\n                    if (c_old >= 1 && c_old <= 10) b[c_old]++;\n                } else {\n                    pat_cnt[old_pat] = 1;\n                    if (1 <= 10) b[1]++;\n                }\n\n                point_pat[i] = old_pat;\n            }\n        }\n\n        T *= cooling;\n    }\n\n    // Output the final lines\n    cout << K << \"\\n\";\n    for (int i = 0; i < K; ++i) {\n        cout << lines[i].px << \" \" << lines[i].py << \" \"\n             << lines[i].qx << \" \" << lines[i].qy << \"\\n\";\n    }\n\n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <array>\n#include <random>\n#include <cmath>\n#include <chrono>\n#include <algorithm>\n\nusing namespace std;\n\nstruct MoveCandidate {\n    array<int, 8> pts;   // four points in cyclic order, starting with new dot\n    double score;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n\n    const int c = (N - 1) / 2;\n    vector<vector<int>> w(N, vector<int>(N));\n    long long totalS = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int dx = i - c, dy = j - c;\n            w[i][j] = dx * dx + dy * dy + 1;\n            totalS += w[i][j];\n        }\n    }\n\n    vector<pair<int, int>> init(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> init[i].first >> init[i].second;\n    }\n\n    const int TRIALS = 3;                 // number of independent greedy runs\n    vector<array<int, 8>> best_ops;\n    long long best_score = -1;\n\n    for (int trial = 0; trial < TRIALS; ++trial) {\n        // state\n        vector<vector<char>> dot(N, vector<char>(N, 0));\n        for (auto& p : init) dot[p.first][p.second] = 1;\n\n        // edge usage\n        vector<vector<char>> h_edge(N, vector<char>(N, 0));   // horizontal (x,y)-(x+1,y)\n        vector<vector<char>> v_edge(N, vector<char>(N, 0));   // vertical   (x,y)-(x,y+1)\n        vector<vector<char>> d1_edge(N, vector<char>(N, 0));  // diagonal up-right (x,y)-(x+1,y+1)\n        vector<vector<char>> d2_edge(N, vector<char>(N, 0));  // diagonal down-right (x,y)-(x+1,y-1)\n\n        vector<array<int, 8>> ops;   // performed operations\n\n        mt19937 rng(chrono::steady_clock::now().time_since_epoch().count() + trial);\n        uniform_real_distribution<double> noise(0.0, 0.5);\n\n        while (true) {\n            vector<MoveCandidate> candidates;\n            double max_score = -1.0;\n\n            for (int x = 0; x < N; ++x) {\n                for (int y = 0; y < N; ++y) {\n                    if (dot[x][y]) continue;\n                    int pw = w[x][y];\n\n                    // ---------- unit squares ----------\n                    // lower-left\n                    if (x + 1 < N && y + 1 < N) {\n                        if (dot[x+1][y] && dot[x][y+1] && dot[x+1][y+1]) {\n                            if (!h_edge[x][y] && !h_edge[x][y+1] && !v_edge[x][y] && !v_edge[x+1][y]) {\n                                array<int,8> pts = {x, y, x+1, y, x+1, y+1, x, y+1};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                    // lower-right\n                    if (x - 1 >= 0 && y + 1 < N) {\n                        if (dot[x-1][y] && dot[x-1][y+1] && dot[x][y+1]) {\n                            if (!h_edge[x-1][y] && !h_edge[x-1][y+1] && !v_edge[x-1][y] && !v_edge[x][y]) {\n                                array<int,8> pts = {x, y, x, y+1, x-1, y+1, x-1, y};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                    // upper-left\n                    if (x + 1 < N && y - 1 >= 0) {\n                        if (dot[x][y-1] && dot[x+1][y-1] && dot[x+1][y]) {\n                            if (!h_edge[x][y-1] && !h_edge[x][y] && !v_edge[x][y-1] && !v_edge[x+1][y-1]) {\n                                array<int,8> pts = {x, y, x+1, y, x+1, y-1, x, y-1};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                    // upper-right\n                    if (x - 1 >= 0 && y - 1 >= 0) {\n                        if (dot[x-1][y-1] && dot[x][y-1] && dot[x-1][y]) {\n                            if (!h_edge[x-1][y-1] && !h_edge[x-1][y] && !v_edge[x-1][y-1] && !v_edge[x][y-1]) {\n                                array<int,8> pts = {x, y, x-1, y, x-1, y-1, x, y-1};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n\n                    // ---------- unit diamonds (45\u00b0 rotated squares) ----------\n                    // case A : p is leftmost corner (lx,ly)\n                    if (x <= N-3 && y >= 1 && y <= N-2) {\n                        int lx = x, ly = y;\n                        if (dot[lx+1][ly+1] && dot[lx+2][ly] && dot[lx+1][ly-1]) {\n                            if (!d1_edge[lx][ly] && !d2_edge[lx+1][ly+1] && !d1_edge[lx+1][ly-1] && !d2_edge[lx][ly]) {\n                                array<int,8> pts = {lx, ly, lx+1, ly+1, lx+2, ly, lx+1, ly-1}; // A,B,C,D\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                    // case B : p is top corner (lx+1,ly+1)\n                    if (x >= 1 && x <= N-2 && y >= 2 && y <= N-1) {\n                        int lx = x-1, ly = y-1;\n                        if (dot[lx][ly] && dot[lx+2][ly] && dot[lx+1][ly-1]) {\n                            if (!d1_edge[lx][ly] && !d2_edge[lx+1][ly+1] && !d1_edge[lx+1][ly-1] && !d2_edge[lx][ly]) {\n                                // order B,C,D,A\n                                array<int,8> pts = {lx+1, ly+1, lx+2, ly, lx+1, ly-1, lx, ly};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                    // case C : p is rightmost corner (lx+2,ly)\n                    if (x >= 2 && y >= 1 && y <= N-2) {\n                        int lx = x-2, ly = y;\n                        if (dot[lx][ly] && dot[lx+1][ly+1] && dot[lx+1][ly-1]) {\n                            if (!d1_edge[lx][ly] && !d2_edge[lx+1][ly+1] && !d1_edge[lx+1][ly-1] && !d2_edge[lx][ly]) {\n                                // order C,D,A,B\n                                array<int,8> pts = {lx+2, ly, lx+1, ly-1, lx, ly, lx+1, ly+1};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                    // case D : p is bottom corner (lx+1,ly-1)\n                    if (x >= 1 && x <= N-2 && y >= 0 && y <= N-3) {\n                        int lx = x-1, ly = y+1;\n                        if (dot[lx][ly] && dot[lx+1][ly+1] && dot[lx+2][ly]) {\n                            if (!d1_edge[lx][ly] && !d2_edge[lx+1][ly+1] && !d1_edge[lx+1][ly-1] && !d2_edge[lx][ly]) {\n                                // order D,A,B,C\n                                array<int,8> pts = {lx+1, ly-1, lx, ly, lx+1, ly+1, lx+2, ly};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (candidates.empty()) break;\n\n            // collect all candidates with maximal score\n            vector<int> best_idx;\n            for (size_t i = 0; i < candidates.size(); ++i) {\n                if (candidates[i].score == max_score) best_idx.push_back(i);\n            }\n            // choose one uniformly at random\n            int chosen = best_idx[uniform_int_distribution<int>(0, best_idx.size()-1)(rng)];\n            MoveCandidate& mv = candidates[chosen];\n\n            // apply the move\n            int x1 = mv.pts[0], y1 = mv.pts[1];\n            dot[x1][y1] = 1;\n\n            // determine shape and mark edges\n            int minx = mv.pts[0], maxx = mv.pts[0], miny = mv.pts[1], maxy = mv.pts[1];\n            for (int i = 0; i < 4; ++i) {\n                int px = mv.pts[2*i], py = mv.pts[2*i+1];\n                if (px < minx) minx = px;\n                if (px > maxx) maxx = px;\n                if (py < miny) miny = py;\n                if (py > maxy) maxy = py;\n            }\n            if (maxx - minx == 1 && maxy - miny == 1) {   // unit square\n                h_edge[minx][miny] = 1;\n                h_edge[minx][maxy] = 1;\n                v_edge[minx][miny] = 1;\n                v_edge[maxx][miny] = 1;\n            } else {                                       // unit diamond\n                // recover lx,ly from the leftmost point (which has min x)\n                int lx = minx, ly = -1;\n                for (int i = 0; i < 4; ++i) {\n                    if (mv.pts[2*i] == lx) {\n                        ly = mv.pts[2*i+1];\n                        break;\n                    }\n                }\n                // mark the four diagonal edges\n                d1_edge[lx][ly] = 1;          // A-B\n                d2_edge[lx+1][ly+1] = 1;      // B-C\n                d1_edge[lx+1][ly-1] = 1;      // C-D\n                d2_edge[lx][ly] = 1;          // D-A\n            }\n\n            ops.push_back(mv.pts);\n        }\n\n        // compute score for this trial\n        long long sum_w = 0;\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                if (dot[i][j]) sum_w += w[i][j];\n\n        double factor = (double)(N * N) / M;\n        double ratio = (double)sum_w / totalS;\n        long long score = llround(1e6 * factor * ratio);\n\n        if (score > best_score) {\n            best_score = score;\n            best_ops = ops;\n        }\n    }\n\n    // output\n    cout << best_ops.size() << \"\\n\";\n    for (auto& op : best_ops) {\n        for (int i = 0; i < 8; ++i) {\n            if (i) cout << \" \";\n            cout << op[i];\n        }\n        cout << \"\\n\";\n    }\n\n    return 0;\n}","ahc015":"#include <iostream>\n#include <vector>\n#include <array>\n#include <queue>\n#include <utility>\n#include <algorithm>\n#include <cmath>\n#include <iomanip>\n\nusing namespace std;\n\n// global flavors (1-indexed)\nvector<int> flavors(101);\n\n// 10x10 grid: 0 = empty, 1..3 = flavor\nusing Grid = array<array<int, 10>, 10>;\n\n// ------------------------------------------------------------\n// tilt simulation\nGrid tilt(const Grid& g, char dir) {\n    Grid ng = {}; // zero-initialized\n    if (dir == 'F') {\n        for (int c = 0; c < 10; ++c) {\n            int idx = 0;\n            for (int r = 0; r < 10; ++r) {\n                if (g[r][c] != 0) {\n                    ng[idx++][c] = g[r][c];\n                }\n            }\n        }\n    } else if (dir == 'B') {\n        for (int c = 0; c < 10; ++c) {\n            int idx = 9;\n            for (int r = 9; r >= 0; --r) {\n                if (g[r][c] != 0) {\n                    ng[idx--][c] = g[r][c];\n                }\n            }\n        }\n    } else if (dir == 'L') {\n        for (int r = 0; r < 10; ++r) {\n            int idx = 0;\n            for (int c = 0; c < 10; ++c) {\n                if (g[r][c] != 0) {\n                    ng[r][idx++] = g[r][c];\n                }\n            }\n        }\n    } else if (dir == 'R') {\n        for (int r = 0; r < 10; ++r) {\n            int idx = 9;\n            for (int c = 9; c >= 0; --c) {\n                if (g[r][c] != 0) {\n                    ng[r][idx--] = g[r][c];\n                }\n            }\n        }\n    }\n    return ng;\n}\n\n// ------------------------------------------------------------\n// compute sum of squares of connected components\nint compute_sum_squares(const Grid& g) {\n    bool visited[10][10] = {};\n    int sum = 0;\n    for (int r = 0; r < 10; ++r) {\n        for (int c = 0; c < 10; ++c) {\n            if (g[r][c] != 0 && !visited[r][c]) {\n                int flavor = g[r][c];\n                int size = 0;\n                queue<pair<int, int>> q;\n                q.push({r, c});\n                visited[r][c] = true;\n                while (!q.empty()) {\n                    auto [x, y] = q.front(); q.pop();\n                    ++size;\n                    // four neighbors\n                    if (x > 0 && !visited[x-1][y] && g[x-1][y] == flavor) {\n                        visited[x-1][y] = true;\n                        q.push({x-1, y});\n                    }\n                    if (x < 9 && !visited[x+1][y] && g[x+1][y] == flavor) {\n                        visited[x+1][y] = true;\n                        q.push({x+1, y});\n                    }\n                    if (y > 0 && !visited[x][y-1] && g[x][y-1] == flavor) {\n                        visited[x][y-1] = true;\n                        q.push({x, y-1});\n                    }\n                    if (y < 9 && !visited[x][y+1] && g[x][y+1] == flavor) {\n                        visited[x][y+1] = true;\n                        q.push({x, y+1});\n                    }\n                }\n                sum += size * size;\n            }\n        }\n    }\n    return sum;\n}\n\n// ------------------------------------------------------------\n// compute total spread (sum of squared distances to centroid) for tie\u2011breaking\ndouble compute_spread(const Grid& g) {\n    vector<int> cnt(4, 0);\n    vector<double> sum_r(4, 0.0), sum_c(4, 0.0);\n    vector<double> sum_r2(4, 0.0), sum_c2(4, 0.0);\n    for (int r = 0; r < 10; ++r) {\n        for (int c = 0; c < 10; ++c) {\n            int f = g[r][c];\n            if (f != 0) {\n                cnt[f]++;\n                sum_r[f] += r;\n                sum_c[f] += c;\n                sum_r2[f] += r * r;\n                sum_c2[f] += c * c;\n            }\n        }\n    }\n    double total = 0.0;\n    for (int f = 1; f <= 3; ++f) {\n        if (cnt[f] > 0) {\n            double mean_r = sum_r[f] / cnt[f];\n            double mean_c = sum_c[f] / cnt[f];\n            total += (sum_r2[f] + sum_c2[f]) -\n                     (sum_r[f] * sum_r[f] + sum_c[f] * sum_c[f]) / cnt[f];\n        }\n    }\n    return total;\n}\n\n// ------------------------------------------------------------\n// recursive expectimax for remaining \u2264 3 candies\ndouble expected_score(const Grid& grid, int next_idx) {\n    if (next_idx > 100) {\n        return compute_sum_squares(grid);\n    }\n\n    // collect empty cells\n    vector<pair<int, int>> empties;\n    for (int r = 0; r < 10; ++r)\n        for (int c = 0; c < 10; ++c)\n            if (grid[r][c] == 0)\n                empties.emplace_back(r, c);\n\n    int E = empties.size();\n    double total = 0.0;\n\n    for (auto [r, c] : empties) {\n        // place the next candy\n        Grid g2 = grid;\n        g2[r][c] = flavors[next_idx];\n\n        // choose the best direction for this placement\n        double best = -1.0;\n        for (char dir : {'F', 'B', 'L', 'R'}) {\n            Grid g3 = tilt(g2, dir);\n            double val = expected_score(g3, next_idx + 1);\n            if (val > best) best = val;\n        }\n        total += best;\n    }\n    return total / E;\n}\n\n// ------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // read all flavors\n    for (int i = 1; i <= 100; ++i) {\n        cin >> flavors[i];\n    }\n\n    Grid grid = {};  // initially empty\n\n    for (int t = 1; t <= 100; ++t) {\n        int p;\n        cin >> p;\n\n        // place the t\u2011th candy in the p\u2011th empty cell (row\u2011major order)\n        int cnt = 0;\n        int r_place = -1, c_place = -1;\n        for (int r = 0; r < 10; ++r) {\n            for (int c = 0; c < 10; ++c) {\n                if (grid[r][c] == 0) {\n                    ++cnt;\n                    if (cnt == p) {\n                        r_place = r;\n                        c_place = c;\n                        break;\n                    }\n                }\n            }\n            if (cnt == p) break;\n        }\n        grid[r_place][c_place] = flavors[t];\n\n        // last tilt does nothing \u2013 output any direction and finish\n        if (t == 100) {\n            cout << 'F' << endl;\n            return 0;\n        }\n\n        int remaining = 100 - t;  // candies still to be placed after this step\n        char best_dir;\n        Grid best_grid;\n\n        if (remaining <= 3) {\n            // deep evaluation using expectimax\n            double best_val = -1.0;\n            for (char dir : {'F', 'B', 'L', 'R'}) {\n                Grid after_tilt = tilt(grid, dir);\n                double val = expected_score(after_tilt, t + 1);\n                if (val > best_val) {\n                    best_val = val;\n                    best_dir = dir;\n                    best_grid = after_tilt;\n                }\n            }\n        } else {\n            // greedy: maximise immediate sum of squares, tie\u2011break by lower spread\n            int best_sum_sq = -1;\n            double best_spread = 1e9;\n            for (char dir : {'F', 'B', 'L', 'R'}) {\n                Grid after_tilt = tilt(grid, dir);\n                int sum_sq = compute_sum_squares(after_tilt);\n                double spread = compute_spread(after_tilt);\n                if (sum_sq > best_sum_sq ||\n                    (sum_sq == best_sum_sq && spread < best_spread)) {\n                    best_sum_sq = sum_sq;\n                    best_spread = spread;\n                    best_dir = dir;\n                    best_grid = after_tilt;\n                }\n            }\n        }\n\n        cout << best_dir << endl;\n        grid = best_grid;\n    }\n\n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <string>\n#include <cmath>\n#include <cassert>\n\nusing namespace std;\n\nint main() {\n    // Problem parameters\n    int M;\n    double epsilon;\n    cin >> M >> epsilon;\n\n    // Fixed design choices\n    const int N = 30;                     // number of vertices\n    const int T = N * (N - 1) / 2;        // number of possible edges\n    const int TRIALS = 100;               // number of noise trials for precomputation\n\n    // ------------------------------------------------------------\n    // 1. Precompute all vertex pairs in lexicographic order\n    // ------------------------------------------------------------\n    vector<pair<int, int>> pairs;\n    pairs.reserve(T);\n    for (int i = 0; i < N; ++i)\n        for (int j = i + 1; j < N; ++j)\n            pairs.emplace_back(i, j);\n    assert(pairs.size() == T);\n\n    // ------------------------------------------------------------\n    // 2. Generate the M graphs G_0 ... G_{M-1}\n    // ------------------------------------------------------------\n    // Random generator for graph construction (deterministic seed)\n    mt19937 rng_graph(12345);\n    uniform_real_distribution<double> dist_graph(0.0, 1.0);\n\n    // Storage: adjacency matrices and the output strings\n    vector<vector<vector<bool>>> adj(M, vector<vector<bool>>(N, vector<bool>(N, false)));\n    vector<string> graph_strings(M);\n\n    for (int idx = 0; idx < M; ++idx) {\n        double p = (M > 1) ? double(idx) / (M - 1) : 0.0;   // edge probability for this graph\n        string s(T, '0');\n        for (int e = 0; e < T; ++e) {\n            auto [u, v] = pairs[e];\n            if (dist_graph(rng_graph) < p) {\n                adj[idx][u][v] = true;\n                s[e] = '1';\n            }\n        }\n        graph_strings[idx] = s;\n    }\n\n    // ------------------------------------------------------------\n    // 3. Output the chosen N and the M graphs\n    // ------------------------------------------------------------\n    cout << N << endl;\n    for (int i = 0; i < M; ++i)\n        cout << graph_strings[i] << endl;\n    cout.flush();\n\n    // ------------------------------------------------------------\n    // 4. Precompute mean and variance of sorted degree sequences\n    //    under the noise model (edge flips with probability epsilon)\n    // ------------------------------------------------------------\n    // Random generator for noise simulation (different seed)\n    mt19937 rng_noise(54321);\n    uniform_real_distribution<double> dist_noise(0.0, 1.0);\n\n    // Means and variances for each graph and each sorted position\n    vector<vector<double>> mean_deg(M, vector<double>(N, 0.0));\n    vector<vector<double>> var_deg(M, vector<double>(N, 0.0));\n\n    for (int g = 0; g < M; ++g) {\n        vector<double> sum(N, 0.0), sum_sq(N, 0.0);\n        for (int trial = 0; trial < TRIALS; ++trial) {\n            vector<int> deg(N, 0);\n            for (int e = 0; e < T; ++e) {\n                auto [u, v] = pairs[e];\n                bool present = adj[g][u][v];\n                // flip with probability epsilon\n                if (dist_noise(rng_noise) < epsilon)\n                    present = !present;\n                if (present) {\n                    deg[u]++;\n                    deg[v]++;\n                }\n            }\n            sort(deg.begin(), deg.end());\n            for (int j = 0; j < N; ++j) {\n                sum[j] += deg[j];\n                sum_sq[j] += deg[j] * deg[j];\n            }\n        }\n        for (int j = 0; j < N; ++j) {\n            mean_deg[g][j] = sum[j] / TRIALS;\n            double variance = sum_sq[j] / TRIALS - mean_deg[g][j] * mean_deg[g][j];\n            // avoid zero variance (can happen for empty/complete graphs with very low noise)\n            if (variance < 1e-9) variance = 1e-9;\n            var_deg[g][j] = variance;\n        }\n    }\n\n    // ------------------------------------------------------------\n    // 5. Process the 100 queries\n    // ------------------------------------------------------------\n    for (int q = 0; q < 100; ++q) {\n        string H_str;\n        cin >> H_str;\n        assert(H_str.size() == T);\n\n        // Compute degree sequence of H\n        vector<int> deg_H(N, 0);\n        for (int e = 0; e < T; ++e) {\n            if (H_str[e] == '1') {\n                auto [u, v] = pairs[e];\n                deg_H[u]++;\n                deg_H[v]++;\n            }\n        }\n        sort(deg_H.begin(), deg_H.end());\n\n        // Find the graph with smallest chi\u2011squared distance\n        int best_graph = 0;\n        double best_dist = 1e100;\n        for (int g = 0; g < M; ++g) {\n            double dist = 0.0;\n            for (int j = 0; j < N; ++j) {\n                double diff = deg_H[j] - mean_deg[g][j];\n                dist += (diff * diff) / var_deg[g][j];\n            }\n            if (dist < best_dist) {\n                best_dist = dist;\n                best_graph = g;\n            }\n        }\n\n        cout << best_graph << endl;\n        cout.flush();\n    }\n\n    return 0;\n}","ahc017":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <random>\n#include <cmath>\n#include <numeric>\n#include <tuple>\n#include <chrono>\n#include <cassert>\n\nusing namespace std;\n\ntypedef long double ld;\nconst ld INF = 1e18L;\n\nstruct Edge {\n    int u, v;\n    long long w;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n    vector<Edge> edges(M);\n    vector<vector<pair<int, pair<int, long long>>>> adj(N); // to, (edge_id, weight)\n    for (int i = 0; i < M; ++i) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        --u; --v;\n        edges[i] = {u, v, w};\n        adj[u].push_back({v, {i, w}});\n        adj[v].push_back({u, {i, w}});\n    }\n    // read and ignore coordinates\n    for (int i = 0; i < N; ++i) {\n        int x, y; cin >> x >> y;\n    }\n\n    // ------------------------------------------------------------\n    // 1. Edge betweenness centrality (weighted Brandes)\n    vector<ld> edge_betweenness(M, 0.0L);\n\n    for (int s = 0; s < N; ++s) {\n        vector<double> dist(N, INF);\n        vector<ld> sigma(N, 0.0L);\n        vector<vector<pair<int, int>>> pred(N); // (predecessor vertex, edge_id)\n\n        dist[s] = 0.0;\n        sigma[s] = 1.0;\n        priority_queue<pair<double, int>,\n                       vector<pair<double, int>>,\n                       greater<>> pq;\n        pq.push({0.0, s});\n\n        while (!pq.empty()) {\n            auto [d, v] = pq.top(); pq.pop();\n            if (d > dist[v]) continue;          // outdated entry\n            for (auto [to, info] : adj[v]) {\n                int eid = info.first;\n                long long w = info.second;\n                double nd = d + w;\n                if (nd < dist[to]) {\n                    dist[to] = nd;\n                    sigma[to] = sigma[v];\n                    pred[to].clear();\n                    pred[to].push_back({v, eid});\n                    pq.push({nd, to});\n                } else if (nd == dist[to]) {\n                    sigma[to] += sigma[v];\n                    pred[to].push_back({v, eid});\n                }\n            }\n        }\n\n        // order vertices by decreasing distance\n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(),\n             [&](int i, int j) { return dist[i] > dist[j]; });\n\n        vector<ld> delta(N, 0.0L);\n        for (int v : order) {\n            if (v == s) continue;\n            for (auto [u, eid] : pred[v]) {\n                ld coeff = sigma[u] / sigma[v];\n                edge_betweenness[eid] += coeff * (1.0L + delta[v]);\n                delta[u] += coeff * (1.0L + delta[v]);\n            }\n        }\n    }\n\n    // ------------------------------------------------------------\n    // 2. Normalise weights to [0,1]\n    ld max_ebc = 0.0L;\n    for (ld val : edge_betweenness)\n        if (val > max_ebc) max_ebc = val;\n    vector<ld> w_norm(M);\n    if (max_ebc == 0.0L) {\n        for (int i = 0; i < M; ++i) w_norm[i] = 1.0L;\n    } else {\n        for (int i = 0; i < M; ++i) w_norm[i] = edge_betweenness[i] / max_ebc;\n    }\n\n    // ------------------------------------------------------------\n    // 3. Greedy initial assignment (balance sum of weights)\n    vector<int> day_of(M, -1);\n    vector<int> cnt(D, 0);\n    vector<ld> sum_w(D, 0.0L);\n\n    vector<int> order_edges(M);\n    iota(order_edges.begin(), order_edges.end(), 0);\n    sort(order_edges.begin(), order_edges.end(),\n         [&](int i, int j) { return w_norm[i] > w_norm[j]; });\n\n    for (int e : order_edges) {\n        int best_day = -1;\n        ld best_sum = INF;\n        for (int d = 0; d < D; ++d) {\n            if (cnt[d] < K && sum_w[d] < best_sum) {\n                best_sum = sum_w[d];\n                best_day = d;\n            }\n        }\n        assert(best_day != -1);\n        day_of[e] = best_day;\n        cnt[best_day]++;\n        sum_w[best_day] += w_norm[e];\n    }\n\n    // ------------------------------------------------------------\n    // 4. Simulated Annealing \u2013 minimise sum of squares of daily weight sums\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> edge_dist(0, M-1);\n    uniform_real_distribution<ld> real_dist(0.0L, 1.0L);\n\n    ld total_cost = 0.0L;\n    for (int d = 0; d < D; ++d)\n        total_cost += sum_w[d] * sum_w[d];\n\n    const int ITER = 2000000;\n    ld T = 10.0L;\n    const ld cooling = 0.999998L;   // after 2e6 steps T ~ 0.2\n\n    for (int iter = 0; iter < ITER; ++iter) {\n        int e = edge_dist(rng);\n        int f = edge_dist(rng);\n        if (e == f) continue;\n        int a = day_of[e];\n        int b = day_of[f];\n        if (a == b) continue;\n\n        ld we = w_norm[e];\n        ld wf = w_norm[f];\n        ld sum_a = sum_w[a];\n        ld sum_b = sum_w[b];\n        ld new_a = sum_a - we + wf;\n        ld new_b = sum_b - wf + we;\n\n        ld old_contrib = sum_a * sum_a + sum_b * sum_b;\n        ld new_contrib = new_a * new_a + new_b * new_b;\n        ld delta = new_contrib - old_contrib;\n\n        if (delta < 0 || exp(-delta / T) > real_dist(rng)) {\n            day_of[e] = b;\n            day_of[f] = a;\n            sum_w[a] = new_a;\n            sum_w[b] = new_b;\n            total_cost += delta;\n        }\n        T *= cooling;\n    }\n\n    // ------------------------------------------------------------\n    // 5. Output (convert to 1\u2011based days)\n    for (int i = 0; i < M; ++i)\n        cout << day_of[i] + 1 << \" \\n\"[i == M-1];\n\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAXD = 14;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    int D;\n    cin >> D;\n    vector<string> f1(D), r1(D), f2(D), r2(D);\n    for (int i = 0; i < D; ++i) cin >> f1[i];\n    for (int i = 0; i < D; ++i) cin >> r1[i];\n    for (int i = 0; i < D; ++i) cin >> f2[i];\n    for (int i = 0; i < D; ++i) cin >> r2[i];\n    \n    // Convert to boolean arrays for quick access\n    bool f1b[D][D] = {}, r1b[D][D] = {};\n    bool f2b[D][D] = {}, r2b[D][D] = {};\n    for (int z = 0; z < D; ++z) {\n        for (int x = 0; x < D; ++x) {\n            f1b[z][x] = (f1[z][x] == '1');\n            f2b[z][x] = (f2[z][x] == '1');\n        }\n        for (int y = 0; y < D; ++y) {\n            r1b[z][y] = (r1[z][y] == '1');\n            r2b[z][y] = (r2[z][y] == '1');\n        }\n    }\n    \n    // ---------- build object 1 (minimal) ----------\n    bool obj1[D][D][D] = {};\n    for (int z = 0; z < D; ++z) {\n        vector<int> X, Y;\n        for (int x = 0; x < D; ++x) if (f1b[z][x]) X.push_back(x);\n        for (int y = 0; y < D; ++y) if (r1b[z][y]) Y.push_back(y);\n        int a = X.size(), b = Y.size();\n        if (a >= b) {\n            for (int i = 0; i < b; ++i) obj1[X[i]][Y[i]][z] = true;\n            for (int i = b; i < a; ++i) obj1[X[i]][Y[0]][z] = true;\n        } else {\n            for (int i = 0; i < a; ++i) obj1[X[i]][Y[i]][z] = true;\n            for (int i = a; i < b; ++i) obj1[X[0]][Y[i]][z] = true;\n        }\n    }\n    \n    // ---------- build object 2 (minimal, with maximum overlap) ----------\n    bool obj2[D][D][D] = {};\n    for (int z = 0; z < D; ++z) {\n        vector<int> X2, Y2;\n        for (int x = 0; x < D; ++x) if (f2b[z][x]) X2.push_back(x);\n        for (int y = 0; y < D; ++y) if (r2b[z][y]) Y2.push_back(y);\n        int a = X2.size(), b = Y2.size();\n        \n        // cells of object1 on this layer\n        set<pair<int,int>> P1;\n        for (int x = 0; x < D; ++x)\n            for (int y = 0; y < D; ++y)\n                if (obj1[x][y][z]) P1.insert({x, y});\n        \n        // weight matrix: 1 if cell is common with obj1, else 0\n        vector<vector<int>> w(a, vector<int>(b, 0));\n        for (int i = 0; i < a; ++i) {\n            int x = X2[i];\n            for (int j = 0; j < b; ++j) {\n                int y = Y2[j];\n                if (P1.count({x, y})) w[i][j] = 1;\n            }\n        }\n        \n        int k = min(a, b);\n        const int INF = -1e9;\n        \n        // DP for maximum weight matching of size k\n        vector<vector<pair<int,int>>> dp(a+1, vector<pair<int,int>>(1<<b, {INF, 0}));\n        vector<vector<pair<int,int>>> best(a+1, vector<pair<int,int>>(1<<b, {-1, -1}));\n        dp[0][0] = {0, 0};\n        best[0][0] = {-2, -2};   // start marker\n        \n        for (int i = 0; i < a; ++i) {\n            for (int mask = 0; mask < (1<<b); ++mask) {\n                if (dp[i][mask].first == INF) continue;\n                // skip this x\n                if (dp[i][mask].first > dp[i+1][mask].first ||\n                    (dp[i][mask].first == dp[i+1][mask].first && dp[i][mask].second > dp[i+1][mask].second)) {\n                    dp[i+1][mask] = dp[i][mask];\n                    best[i+1][mask] = {mask, -1};\n                }\n                // match to a free y\n                for (int j = 0; j < b; ++j) {\n                    if (mask & (1<<j)) continue;\n                    int nmask = mask | (1<<j);\n                    int nw = dp[i][mask].first + w[i][j];\n                    int nm = dp[i][mask].second + 1;\n                    if (nw > dp[i+1][nmask].first ||\n                        (nw == dp[i+1][nmask].first && nm > dp[i+1][nmask].second)) {\n                        dp[i+1][nmask] = {nw, nm};\n                        best[i+1][nmask] = {mask, j};\n                    }\n                }\n            }\n        }\n        \n        // recover the best matching of size exactly k\n        int best_mask = -1, best_weight = -1;\n        for (int mask = 0; mask < (1<<b); ++mask) {\n            if (dp[a][mask].second == k && dp[a][mask].first > best_weight) {\n                best_weight = dp[a][mask].first;\n                best_mask = mask;\n            }\n        }\n        \n        vector<bool> x_matched(a, false);\n        vector<int> y_for_x(a, -1);\n        if (best_mask != -1) {\n            int mask = best_mask;\n            for (int i = a; i > 0; --i) {\n                auto p = best[i][mask];\n                int prev_mask = p.first;\n                int y_used = p.second;\n                if (y_used != -1) {\n                    x_matched[i-1] = true;\n                    y_for_x[i-1] = y_used;\n                }\n                mask = prev_mask;\n            }\n        }\n        \n        // build P2 (set of (x,y) for object2)\n        set<pair<int,int>> P2;\n        for (int i = 0; i < a; ++i) {\n            if (x_matched[i]) {\n                int x = X2[i], y = Y2[y_for_x[i]];\n                P2.insert({x, y});\n            }\n        }\n        // add extra edges to cover uncovered vertices\n        if (a > b) {\n            for (int i = 0; i < a; ++i) {\n                if (!x_matched[i]) {\n                    int x = X2[i];\n                    int chosen_y = -1;\n                    for (int j = 0; j < b; ++j) {\n                        if (w[i][j] == 1) {\n                            chosen_y = Y2[j];\n                            break;\n                        }\n                    }\n                    if (chosen_y == -1) chosen_y = Y2[0];\n                    P2.insert({x, chosen_y});\n                }\n            }\n        } else if (b > a) {\n            vector<bool> y_matched(b, false);\n            for (int i = 0; i < a; ++i)\n                if (x_matched[i]) y_matched[y_for_x[i]] = true;\n            for (int j = 0; j < b; ++j) {\n                if (!y_matched[j]) {\n                    int y = Y2[j];\n                    int chosen_x = -1;\n                    for (int i = 0; i < a; ++i) {\n                        if (w[i][j] == 1) {\n                            chosen_x = X2[i];\n                            break;\n                        }\n                    }\n                    if (chosen_x == -1) chosen_x = X2[0];\n                    P2.insert({chosen_x, y});\n                }\n            }\n        }\n        // place the cells\n        for (auto& p : P2) obj2[p.first][p.second][z] = true;\n    }\n    \n    // ---------- common cells and their connected components ----------\n    bool common[D][D][D] = {};\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                common[x][y][z] = obj1[x][y][z] && obj2[x][y][z];\n    \n    int comp[D][D][D];\n    memset(comp, -1, sizeof(comp));\n    int num_components = 0;\n    const int dx[6] = {1,-1,0,0,0,0};\n    const int dy[6] = {0,0,1,-1,0,0};\n    const int dz[6] = {0,0,0,0,1,-1};\n    \n    for (int x = 0; x < D; ++x)\n        for (int y = 0; y < D; ++y)\n            for (int z = 0; z < D; ++z)\n                if (common[x][y][z] && comp[x][y][z] == -1) {\n                    queue<tuple<int,int,int>> q;\n                    q.push({x, y, z});\n                    comp[x][y][z] = num_components;\n                    while (!q.empty()) {\n                        auto [cx, cy, cz] = q.front(); q.pop();\n                        for (int d = 0; d < 6; ++d) {\n                            int nx = cx + dx[d];\n                            int ny = cy + dy[d];\n                            int nz = cz + dz[d];\n                            if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D &&\n                                common[nx][ny][nz] && comp[nx][ny][nz] == -1) {\n                                comp[nx][ny][nz] = num_components;\n                                q.push({nx, ny, nz});\n                            }\n                        }\n                    }\n                    ++num_components;\n                }\n    \n    // ---------- assign block IDs ----------\n    vector<vector<vector<int>>> b1(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    vector<vector<vector<int>>> b2(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    int cur_id = 1;\n    \n    // shared blocks (one per component)\n    vector<int> comp_id(num_components);\n    for (int i = 0; i < num_components; ++i) comp_id[i] = cur_id++;\n    \n    // unit blocks for object1 (non\u2011common cells)\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 (obj1[x][y][z] && !common[x][y][z])\n                    b1[x][y][z] = cur_id++;\n    \n    // unit blocks for object2 (non\u2011common cells)\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 (obj2[x][y][z] && !common[x][y][z])\n                    b2[x][y][z] = cur_id++;\n    \n    // common cells get the shared block ID in both objects\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 (common[x][y][z]) {\n                    int id = comp_id[comp[x][y][z]];\n                    b1[x][y][z] = id;\n                    b2[x][y][z] = id;\n                }\n    \n    // ---------- output ----------\n    int total_blocks = cur_id - 1;\n    cout << total_blocks << \"\\n\";\n    // b1\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                cout << b1[x][y][z];\n                if (x == D-1 && y == D-1 && z == D-1) cout << \"\\n\";\n                else cout << \" \";\n            }\n    // b2\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                cout << b2[x][y][z];\n                if (x == D-1 && y == D-1 && z == D-1) cout << \"\\n\";\n                else cout << \" \";\n            }\n    \n    return 0;\n}","ahc020":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <climits>\n#include <numeric>\n\nusing namespace std;\ntypedef long long ll;\n\nstruct Candidate {\n    int type;      // 0: active vertex, 1: inactive vertex\n    int idx;       // vertex index\n    int new_P;     // new output strength\n    ll cost;       // total cost of the action\n    int count;     // number of newly covered residents\n    int first_idx; // first index in sorted_res[idx] to cover\n    int last_idx;  // last index (exclusive) in sorted_res[idx] to cover\n};\n\n// integer ceil(sqrt(x))\nint ceil_sqrt(ll x) {\n    int r = sqrt(x);\n    while ((ll)r * r < x) ++r;\n    return r;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\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\n    vector<int> u(M), v(M), w(M);\n    vector<vector<pair<int, int>>> adj(N); // (neighbor, edge index)\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]].emplace_back(v[j], j);\n        adj[v[j]].emplace_back(u[j], j);\n    }\n\n    vector<int> a(K), b(K);\n    for (int k = 0; k < K; ++k) cin >> a[k] >> b[k];\n\n    // squared distances from vertices to residents\n    vector<vector<ll>> dist2(N, vector<ll>(K));\n    for (int i = 0; i < N; ++i) {\n        for (int k = 0; k < K; ++k) {\n            ll dx = x[i] - a[k];\n            ll dy = y[i] - b[k];\n            dist2[i][k] = dx * dx + dy * dy;\n        }\n    }\n\n    // for each vertex, residents sorted by distance\n    vector<vector<int>> sorted_res(N);\n    for (int i = 0; i < N; ++i) {\n        sorted_res[i].resize(K);\n        iota(sorted_res[i].begin(), sorted_res[i].end(), 0);\n        sort(sorted_res[i].begin(), sorted_res[i].end(),\n             [&](int k1, int k2) { return dist2[i][k1] < dist2[i][k2]; });\n    }\n\n    // state\n    vector<bool> covered(K, false);\n    int covered_cnt = 0;\n    vector<int> P(N, 0);\n    vector<int> next_uncovered(N, 0); // for active vertices\n    vector<bool> is_vertex_active(N, false);\n    is_vertex_active[0] = true; // station 1 (index 0)\n    vector<bool> is_edge_on(M, false);\n\n    // main loop\n    while (covered_cnt < K) {\n        // Dijkstra to compute additional connection costs\n        vector<ll> dist_conn(N, LLONG_MAX);\n        vector<int> prev_vertex(N, -1), prev_edge(N, -1);\n        priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<>> pq;\n        for (int i = 0; i < N; ++i) {\n            if (is_vertex_active[i]) {\n                dist_conn[i] = 0;\n                pq.emplace(0, i);\n            }\n        }\n        while (!pq.empty()) {\n            auto [d, u_idx] = pq.top(); pq.pop();\n            if (d != dist_conn[u_idx]) continue;\n            for (auto [v_idx, e_idx] : adj[u_idx]) {\n                ll cost = is_edge_on[e_idx] ? 0 : w[e_idx];\n                if (dist_conn[u_idx] + cost < dist_conn[v_idx]) {\n                    dist_conn[v_idx] = dist_conn[u_idx] + cost;\n                    prev_vertex[v_idx] = u_idx;\n                    prev_edge[v_idx] = e_idx;\n                    pq.emplace(dist_conn[v_idx], v_idx);\n                }\n            }\n        }\n\n        // evaluate all possible actions\n        Candidate best;\n        bool found = false;\n\n        // actions on active vertices\n        for (int i = 0; i < N; ++i) {\n            if (!is_vertex_active[i]) continue;\n            // move to first uncovered resident\n            while (next_uncovered[i] < K && covered[sorted_res[i][next_uncovered[i]]])\n                ++next_uncovered[i];\n            if (next_uncovered[i] == K) continue;\n\n            int first = next_uncovered[i];\n            int k = sorted_res[i][first];\n            ll d2 = dist2[i][k];\n            int new_P = ceil_sqrt(d2);\n            if (new_P > 5000) continue;\n            ll new_P2 = (ll)new_P * new_P;\n            ll old_P2 = (ll)P[i] * P[i];\n\n            // count newly covered residents\n            int cnt = 0;\n            int last = first;\n            for (int j = first; j < K; ++j) {\n                int res = sorted_res[i][j];\n                if (dist2[i][res] > new_P2) break;\n                if (!covered[res]) ++cnt;\n                last = j + 1;\n            }\n            if (cnt == 0) continue;\n\n            ll cost_inc = new_P2 - old_P2;\n            if (!found || (ll)cost_inc * best.count < (ll)best.cost * cnt) {\n                best = {0, i, new_P, cost_inc, cnt, first, last};\n                found = true;\n            }\n        }\n\n        // actions on inactive vertices\n        for (int i = 0; i < N; ++i) {\n            if (is_vertex_active[i]) continue;\n            if (dist_conn[i] == LLONG_MAX) continue; // should not happen\n\n            // first uncovered resident\n            int first = 0;\n            while (first < K && covered[sorted_res[i][first]]) ++first;\n            if (first == K) continue;\n\n            int k = sorted_res[i][first];\n            ll d2 = dist2[i][k];\n            int new_P = ceil_sqrt(d2);\n            if (new_P > 5000) continue;\n            ll new_P2 = (ll)new_P * new_P;\n\n            int cnt = 0;\n            int last = first;\n            for (int j = first; j < K; ++j) {\n                int res = sorted_res[i][j];\n                if (dist2[i][res] > new_P2) break;\n                if (!covered[res]) ++cnt;\n                last = j + 1;\n            }\n            if (cnt == 0) continue;\n\n            ll total_cost = dist_conn[i] + new_P2;\n            if (!found || (ll)total_cost * best.count < (ll)best.cost * cnt) {\n                best = {1, i, new_P, total_cost, cnt, first, last};\n                found = true;\n            }\n        }\n\n        if (!found) break; // should not happen\n\n        // apply the best action\n        if (best.type == 0) { // active vertex\n            int i = best.idx;\n            P[i] = best.new_P;\n            for (int j = best.first_idx; j < best.last_idx; ++j) {\n                int res = sorted_res[i][j];\n                if (!covered[res]) {\n                    covered[res] = true;\n                    ++covered_cnt;\n                }\n            }\n            next_uncovered[i] = best.last_idx;\n        } else { // inactive vertex\n            int j = best.idx;\n            // turn on edges along the shortest path\n            int cur = j;\n            while (!is_vertex_active[cur]) {\n                int e = prev_edge[cur];\n                if (!is_edge_on[e]) is_edge_on[e] = true;\n                int prev = prev_vertex[cur];\n                is_vertex_active[cur] = true;\n                next_uncovered[cur] = 0; // newly activated, P=0 initially\n                P[cur] = 0;\n                cur = prev;\n            }\n            P[j] = best.new_P;\n            for (int idx = best.first_idx; idx < best.last_idx; ++idx) {\n                int res = sorted_res[j][idx];\n                if (!covered[res]) {\n                    covered[res] = true;\n                    ++covered_cnt;\n                }\n            }\n            next_uncovered[j] = best.last_idx;\n        }\n    }\n\n    // output\n    for (int i = 0; i < N; ++i) {\n        cout << P[i] << (i + 1 == N ? \"\\n\" : \" \");\n    }\n    for (int j = 0; j < M; ++j) {\n        cout << (is_edge_on[j] ? 1 : 0) << (j + 1 == M ? \"\\n\" : \" \");\n    }\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30; // fixed pyramid size\n\nint main() {\n    // read input\n    vector<vector<int>> a(N);\n    for (int x = 0; x < N; ++x) {\n        a[x].resize(x + 1);\n        for (int y = 0; y <= x; ++y) {\n            cin >> a[x][y];\n        }\n    }\n\n    vector<array<int, 4>> ops; // stores swaps (x1,y1,x2,y2)\n\n    // swap two adjacent balls and record the operation\n    auto do_swap = [&](int x1, int y1, int x2, int y2) {\n        swap(a[x1][y1], a[x2][y2]);\n        ops.push_back({x1, y1, x2, y2});\n    };\n\n    // sift down a value starting from (x,y) until heap property holds\n    auto sift = [&](int x, int y) {\n        while (x < N - 1) { // while not a leaf\n            int x_left = x + 1, y_left = y;      // left child\n            int x_right = x + 1, y_right = y + 1; // right child\n            // choose the child with the smaller value\n            int nx, ny;\n            if (a[x_left][y_left] <= a[x_right][y_right]) {\n                nx = x_left; ny = y_left;\n            } else {\n                nx = x_right; ny = y_right;\n            }\n            if (a[x][y] > a[nx][ny]) {\n                do_swap(x, y, nx, ny);\n                x = nx; y = ny; // continue sifting with the moved value\n            } else {\n                break;\n            }\n        }\n    };\n\n    // process rows from bottom to top, each node exactly once\n    for (int x = N - 2; x >= 0; --x) {\n        for (int y = 0; y <= x; ++y) {\n            sift(x, y);\n        }\n    }\n\n    // output\n    cout << ops.size() << '\\n';\n    for (auto& sw : ops) {\n        cout << sw[0] << ' ' << sw[1] << ' ' << sw[2] << ' ' << sw[3] << '\\n';\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int D = 9;               // fixed as per problem\nint entrance_r = 0, entrance_c = (D - 1) / 2;   // (0,4)\n\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\n\nbool obstacle[D][D] = {false};\nbool occupied[D][D] = {false};\nint container_num[D][D];       // -1 if no container\n\nint dist[D][D];                // BFS distance from entrance\nint rank[D][D];                // index in the sorted order (0..M-1)\nvector<pair<int, int>> order;  // free squares sorted by (dist, row, col)\nint M;                         // number of containers\n\n// ---------- preprocessing ----------\nvoid compute_bfs_distances() {\n    for (int i = 0; i < D; ++i)\n        for (int j = 0; j < D; ++j)\n            dist[i][j] = -1;\n\n    queue<pair<int, int>> q;\n    dist[entrance_r][entrance_c] = 0;\n    q.push({entrance_r, entrance_c});\n\n    while (!q.empty()) {\n        auto [r, c] = q.front(); q.pop();\n        for (int d = 0; d < 4; ++d) {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n            if (obstacle[nr][nc]) continue;\n            if (dist[nr][nc] == -1) {\n                dist[nr][nc] = dist[r][c] + 1;\n                q.push({nr, nc});\n            }\n        }\n    }\n}\n\nvoid build_order() {\n    order.clear();\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            if (i == entrance_r && j == entrance_c) continue;\n            if (obstacle[i][j]) continue;\n            order.push_back({i, j});\n        }\n    }\n    sort(order.begin(), order.end(),\n         [](const auto& a, const auto& b) {\n             int da = dist[a.first][a.second];\n             int db = dist[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    M = order.size();\n    for (int i = 0; i < D; ++i)\n        for (int j = 0; j < D; ++j)\n            rank[i][j] = -1;\n    for (int i = 0; i < M; ++i) {\n        auto [r, c] = order[i];\n        rank[r][c] = i;\n    }\n}\n\n// ---------- helper for articulation test ----------\n// temporarily block (br,bc) and count reachable empty squares from entrance\nint count_reachable_without(int br, int bc, bool is_empty[D][D]) {\n    bool original = is_empty[br][bc];\n    is_empty[br][bc] = false;          // block the square\n\n    bool visited[D][D] = {false};\n    int cnt = 0;\n    queue<pair<int, int>> q;\n    q.push({entrance_r, entrance_c});\n    visited[entrance_r][entrance_c] = true;\n    ++cnt;\n\n    while (!q.empty()) {\n        auto [r, c] = q.front(); q.pop();\n        for (int d = 0; d < 4; ++d) {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n            if (!is_empty[nr][nc]) continue;\n            if (!visited[nr][nc]) {\n                visited[nr][nc] = true;\n                q.push({nr, nc});\n                ++cnt;\n            }\n        }\n    }\n\n    is_empty[br][bc] = original;       // restore\n    return cnt;\n}\n\n// ---------- main ----------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> D >> N;                     // D is always 9, but we read it\n\n    // read obstacles\n    for (int i = 0; i < N; ++i) {\n        int r, c;\n        cin >> r >> c;\n        obstacle[r][c] = true;\n    }\n\n    // preprocessing\n    compute_bfs_distances();\n    build_order();\n\n    // initialise container numbers\n    for (int i = 0; i < D; ++i)\n        for (int j = 0; j < D; ++j)\n            container_num[i][j] = -1;\n\n    // ---------- placement phase ----------\n    for (int step = 0; step < M; ++step) {\n        int t;\n        cin >> t;\n\n        // build current empty mask (entrance + all non\u2011occupied, non\u2011obstacle)\n        bool is_empty[D][D] = {false};\n        for (int i = 0; i < D; ++i)\n            for (int j = 0; j < D; ++j) {\n                if (obstacle[i][j]) is_empty[i][j] = false;\n                else if (occupied[i][j]) is_empty[i][j] = false;\n                else is_empty[i][j] = true;      // includes entrance\n            }\n\n        // collect all reachable empty squares (except entrance)\n        vector<pair<int, int>> reachable;\n        bool visited[D][D] = {false};\n        queue<pair<int, int>> q;\n        q.push({entrance_r, entrance_c});\n        visited[entrance_r][entrance_c] = true;\n\n        while (!q.empty()) {\n            auto [r, c] = q.front(); q.pop();\n            if (!(r == entrance_r && c == entrance_c))\n                reachable.push_back({r, c});\n            for (int d = 0; d < 4; ++d) {\n                int nr = r + dr[d], nc = c + dc[d];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (!is_empty[nr][nc]) continue;\n                if (!visited[nr][nc]) {\n                    visited[nr][nc] = true;\n                    q.push({nr, nc});\n                }\n            }\n        }\n\n        // among reachable squares, keep only those that are not articulation points\n        vector<pair<int, int>> safe;\n        int total_empty = reachable.size() + 1;   // +1 for entrance\n        for (auto& s : reachable) {\n            int r = s.first, c = s.second;\n            int cnt = count_reachable_without(r, c, is_empty);\n            if (cnt == total_empty - 1)          // graph stays connected\n                safe.push_back(s);\n        }\n\n        // choose a square\n        pair<int, int> chosen;\n        if (!safe.empty()) {\n            // pick the safe square whose rank is closest to t\n            int best_diff = 1e9, best_dist = 1e9;\n            for (auto& s : safe) {\n                int r = s.first, c = s.second;\n                int rnk = rank[r][c];\n                int diff = abs(rnk - t);\n                int d = dist[r][c];\n                if (diff < best_diff || (diff == best_diff && d < best_dist)) {\n                    best_diff = diff;\n                    best_dist = d;\n                    chosen = s;\n                }\n            }\n        } else {\n            // fallback \u2013 should never happen, but choose the closest reachable square\n            int best_dist = 1e9;\n            for (auto& s : reachable) {\n                int d = dist[s.first][s.second];\n                if (d < best_dist) {\n                    best_dist = d;\n                    chosen = s;\n                }\n            }\n        }\n\n        // output placement\n        cout << chosen.first << \" \" << chosen.second << endl;\n\n        // update state\n        occupied[chosen.first][chosen.second] = true;\n        container_num[chosen.first][chosen.second] = t;\n    }\n\n    // ---------- retrieval phase ----------\n    int remaining = M;\n    while (remaining > 0) {\n        // rebuild empty mask\n        bool is_empty[D][D] = {false};\n        for (int i = 0; i < D; ++i)\n            for (int j = 0; j < D; ++j) {\n                if (obstacle[i][j]) is_empty[i][j] = false;\n                else if (occupied[i][j]) is_empty[i][j] = false;\n                else is_empty[i][j] = true;\n            }\n\n        // find all containers adjacent to an empty square\n        vector<pair<int, int>> accessible;\n        for (int i = 0; i < D; ++i) {\n            for (int j = 0; j < D; ++j) {\n                if (!occupied[i][j]) continue;\n                bool adj = false;\n                for (int d = 0; d < 4; ++d) {\n                    int ni = i + dr[d], nj = j + dc[d];\n                    if (ni < 0 || ni >= D || nj < 0 || nj >= D) continue;\n                    if (is_empty[ni][nj]) {\n                        adj = true;\n                        break;\n                    }\n                }\n                if (adj) accessible.push_back({i, j});\n            }\n        }\n\n        // choose the one with the smallest number\n        auto best = accessible[0];\n        int best_num = container_num[best.first][best.second];\n        for (auto& p : accessible) {\n            int num = container_num[p.first][p.second];\n            if (num < best_num) {\n                best_num = num;\n                best = p;\n            }\n        }\n\n        // output retrieval\n        cout << best.first << \" \" << best.second << endl;\n\n        // remove it\n        occupied[best.first][best.second] = false;\n        container_num[best.first][best.second] = -1;\n        --remaining;\n    }\n\n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <utility>\n#include <algorithm>\nusing namespace std;\n\nconst int MAXN = 50;\nconst int MAXM = 100;\n\nint n, m;\nint cur[MAXN][MAXN];\nint colorCount[MAXM+1] = {0};          // 0..100\nint edgeCount[MAXM+1][MAXM+1] = {0};   // only upper triangular used\nbool required[MAXM+1][MAXM+1] = {false};\nbool allowed[MAXM+1] = {false};        // colors that may touch 0\n\nconst int dx[4] = {1, -1, 0, 0};\nconst int dy[4] = {0, 0, 1, -1};\n\n// Check if we can safely recolor (i,j) to 0\nbool isRemovable(int i, int j) {\n    int c = cur[i][j];\n    if (c == 0) return false;\n    if (!allowed[c]) return false;\n    if (colorCount[c] <= 1) return false;\n\n    int cnt[MAXM+1] = {0};   // count of neighbor colors (0..m)\n    bool adj_to_0 = false;\n    int same_color_neighbors = 0;\n\n    // examine four neighbours (outside counts as color 0)\n    for (int d = 0; d < 4; ++d) {\n        int ni = i + dx[d], nj = j + dy[d];\n        int col;\n        if (ni >= 0 && ni < n && nj >= 0 && nj < n)\n            col = cur[ni][nj];\n        else\n            col = 0;   // outside\n        cnt[col]++;\n        if (col == 0) adj_to_0 = true;\n        else if (!allowed[col]) return false;   // would create forbidden 0\u2013col adjacency\n        if (col == c) same_color_neighbors++;\n    }\n    if (!adj_to_0) return false;\n\n    // Edge count constraints\n    for (int d = 0; d <= m; ++d) {\n        if (cnt[d] == 0 || d == c) continue;\n        if (d == 0) {\n            // need at least one edge between c and 0 after removal\n            if (edgeCount[0][c] - cnt[0] < 1) return false;\n        } else {\n            int a = min(c, d), b = max(c, d);\n            if (required[a][b] && edgeCount[a][b] - cnt[d] < 1) return false;\n        }\n    }\n\n    // Connectivity of color c after removal\n    if (same_color_neighbors == 0) return false;   // should not happen\n    if (same_color_neighbors == 1) return true;    // leaf \u2013 safe\n\n    // BFS on color c, excluding (i,j)\n    int start_i = -1, start_j = -1;\n    for (int d = 0; d < 4; ++d) {\n        int ni = i + dx[d], nj = j + dy[d];\n        if (ni >= 0 && ni < n && nj >= 0 && nj < n && cur[ni][nj] == c) {\n            start_i = ni; start_j = nj; break;\n        }\n    }\n    if (start_i == -1) return false;   // no neighbour of same colour \u2013 impossible\n\n    bool visited[MAXN][MAXN] = {false};\n    queue<pair<int,int>> q;\n    visited[start_i][start_j] = true;\n    q.push({start_i, start_j});\n    int count = 0;\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        count++;\n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (nx >= 0 && nx < n && ny >= 0 && ny < n && !visited[nx][ny] &&\n                cur[nx][ny] == c && !(nx == i && ny == j)) {\n                visited[nx][ny] = true;\n                q.push({nx, ny});\n            }\n        }\n    }\n    return (count == colorCount[c] - 1);\n}\n\n// Actually recolor (i,j) from its colour c to 0\nvoid removeCell(int i, int j) {\n    int c = cur[i][j];\n    // Update edge counts for all incident edges\n    for (int d = 0; d < 4; ++d) {\n        int ni = i + dx[d], nj = j + dy[d];\n        int col;\n        if (ni >= 0 && ni < n && nj >= 0 && nj < n)\n            col = cur[ni][nj];\n        else\n            col = 0;   // outside\n        if (col == c) continue;   // no edge between same colours\n        // Remove edge c\u2013col\n        if (col == 0) {\n            edgeCount[0][c]--;\n        } else {\n            int a = min(c, col), b = max(c, col);\n            edgeCount[a][b]--;\n        }\n        // After recoloring, add edge 0\u2013col (if col != 0)\n        if (col != 0) {\n            edgeCount[0][col]++;\n        }\n    }\n    // Perform the recolor\n    cur[i][j] = 0;\n    colorCount[c]--;\n    colorCount[0]++;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n >> m;\n    for (int i = 0; i < n; ++i)\n        for (int j = 0; j < n; ++j) {\n            cin >> cur[i][j];\n            colorCount[cur[i][j]]++;\n        }\n\n    // Determine which colours are allowed to touch 0 (i.e. appear on the boundary)\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (i == 0 || i == n-1 || j == 0 || j == n-1)\n                allowed[cur[i][j]] = true;\n        }\n    }\n\n    // Build required adjacency matrix\n    // First, adjacency to outside (0)\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (i == 0 || i == n-1 || j == 0 || j == n-1) {\n                int c = cur[i][j];\n                required[0][c] = true;   // 0 < c, so store as [0][c]\n            }\n        }\n    }\n    // Then, adjacencies between colours >0\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c = cur[i][j];\n            if (i+1 < n) {\n                int d = cur[i+1][j];\n                if (c != d) {\n                    int a = min(c,d), b = max(c,d);\n                    required[a][b] = true;\n                }\n            }\n            if (j+1 < n) {\n                int d = cur[i][j+1];\n                if (c != d) {\n                    int a = min(c,d), b = max(c,d);\n                    required[a][b] = true;\n                }\n            }\n        }\n    }\n\n    // Compute initial edge counts\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c = cur[i][j];\n            // down\n            if (i+1 < n) {\n                int d = cur[i+1][j];\n                if (c != d) {\n                    int a = min(c,d), b = max(c,d);\n                    edgeCount[a][b]++;\n                }\n            }\n            // right\n            if (j+1 < n) {\n                int d = cur[i][j+1];\n                if (c != d) {\n                    int a = min(c,d), b = max(c,d);\n                    edgeCount[a][b]++;\n                }\n            }\n            // outside sides\n            if (i == 0) edgeCount[0][c]++;\n            if (i == n-1) edgeCount[0][c]++;\n            if (j == 0) edgeCount[0][c]++;\n            if (j == n-1) edgeCount[0][c]++;\n        }\n    }\n\n    // Erosion: repeatedly turn removable cells into 0\n    bool changed;\n    do {\n        changed = false;\n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                if (cur[i][j] == 0) continue;\n                if (isRemovable(i, j)) {\n                    removeCell(i, j);\n                    changed = true;\n                }\n            }\n        }\n    } while (changed);\n\n    // Output the final map\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (j) cout << ' ';\n            cout << cur[i][j];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, D, Q;\nvector<vector<int>> cmp;   // -2 unknown, -1: <, 0: =, 1: >\nint queries_used = 0;\n\n// Compare items i and j, using a query if necessary.\nint compare(int i, int j) {\n    if (i == j) return 0;\n    if (cmp[i][j] != -2) return cmp[i][j];\n    // Perform a query\n    cout << \"1 1 \" << i << \" \" << j << endl;\n    cout.flush();\n    string res;\n    cin >> res;\n    ++queries_used;\n    int ans;\n    if (res == \"<\") ans = -1;\n    else if (res == \">\") ans = 1;\n    else ans = 0;   // \"=\"\n    cmp[i][j] = ans;\n    cmp[j][i] = -ans;\n    return ans;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cout.tie(nullptr);\n\n    cin >> N >> D >> Q;\n    cmp.assign(N, vector<int>(N, -2));\n\n    // Random order of items (fixed seed for reproducibility)\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    mt19937 rng(123456);\n    shuffle(order.begin(), order.end(), rng);\n\n    // ---------- 1. Insertion sort with binary search ----------\n    vector<int> sorted;\n    sorted.reserve(N);\n\n    for (int idx : order) {\n        if (queries_used >= Q) break;\n        int m = sorted.size();\n        // Worst-case number of comparisons for this insertion\n        int need = (m == 0) ? 0 : (32 - __builtin_clz(m)); // = ceil(log2(m+1))\n        if (queries_used + need > Q) break;   // cannot afford even in worst case\n\n        // Binary search for insertion position\n        int lo = 0, hi = m;\n        while (lo < hi) {\n            int mid = (lo + hi) / 2;\n            int res = compare(idx, sorted[mid]);\n            if (res < 0) hi = mid;      // idx lighter\n            else lo = mid + 1;          // idx heavier or equal\n        }\n        sorted.insert(sorted.begin() + lo, idx);\n    }\n\n    // ---------- 2. Add remaining items (unsorted) ----------\n    vector<bool> used(N, false);\n    for (int x : sorted) used[x] = true;\n    vector<int> unsorted;\n    for (int i = 0; i < N; ++i)\n        if (!used[i]) unsorted.push_back(i);\n    sorted.insert(sorted.end(), unsorted.begin(), unsorted.end());\n\n    // ---------- 3. Refine order with bubble passes (using remaining queries) ----------\n    bool swapped = true;\n    while (swapped && queries_used < Q) {\n        swapped = false;\n        for (size_t i = 0; i + 1 < sorted.size() && queries_used < Q; ++i) {\n            int res = compare(sorted[i], sorted[i+1]);\n            if (res > 0) {   // left heavier than right \u2192 out of order\n                swap(sorted[i], sorted[i+1]);\n                swapped = true;\n            }\n        }\n    }\n\n    // ---------- 4. Assign groups (round\u2011robin on descending order) ----------\n    vector<int> ans(N);\n    for (int pos = 0; pos < N; ++pos) {\n        int item = sorted[N - 1 - pos];   // heaviest first\n        ans[item] = pos % D;\n    }\n\n    // ---------- 5. Dummy queries to reach exactly Q ----------\n    while (queries_used < Q) {\n        cout << \"1 1 0 1\" << endl;\n        cout.flush();\n        string dummy;\n        cin >> dummy;\n        ++queries_used;\n    }\n\n    // ---------- 6. Output final division ----------\n    for (int i = 0; i < N; ++i) {\n        cout << ans[i];\n        if (i < N - 1) cout << \" \";\n    }\n    cout << endl;\n    cout.flush();\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int n, m;\n    cin >> n >> m;\n    int k = n / m;\n    vector<vector<int>> stacks(m);\n    for (int i = 0; i < m; ++i) {\n        stacks[i].resize(k);\n        for (int j = 0; j < k; ++j) {\n            cin >> stacks[i][j];\n        }\n    }\n\n    vector<pair<int, int>> ops;\n\n    for (int v = 1; v <= n; ++v) {\n        // locate box v\n        int cur = -1, pos = -1;\n        for (int i = 0; i < m; ++i) {\n            for (int j = 0; j < (int)stacks[i].size(); ++j) {\n                if (stacks[i][j] == v) {\n                    cur = i;\n                    pos = j;\n                    break;\n                }\n            }\n            if (cur != -1) break;\n        }\n\n        // v is on top -> extract directly\n        if (pos == (int)stacks[cur].size() - 1) {\n            ops.emplace_back(v, 0);\n            stacks[cur].pop_back();\n        } else {\n            // move the block above v\n            int w = stacks[cur][pos + 1];   // box directly above v\n            // choose destination stack\n            int dest = -1;\n            // first prefer an empty stack\n            for (int i = 0; i < m; ++i) {\n                if (i != cur && stacks[i].empty()) {\n                    dest = i;\n                    break;\n                }\n            }\n            if (dest == -1) {\n                int max_top = -1;\n                for (int i = 0; i < m; ++i) {\n                    if (i == cur) continue;\n                    if (!stacks[i].empty()) {\n                        int top_val = stacks[i].back();\n                        if (top_val > max_top) {\n                            max_top = top_val;\n                            dest = i;\n                        }\n                    }\n                }\n            }\n\n            // perform the move\n            ops.emplace_back(w, dest + 1);\n            // extract the block from cur\n            vector<int> moved(stacks[cur].begin() + pos + 1, stacks[cur].end());\n            stacks[cur].erase(stacks[cur].begin() + pos + 1, stacks[cur].end());\n            // append to destination\n            stacks[dest].insert(stacks[dest].end(), moved.begin(), moved.end());\n\n            // now v is on top -> extract it\n            ops.emplace_back(v, 0);\n            stacks[cur].pop_back();\n        }\n    }\n\n    // output the operation sequence\n    for (auto& p : ops) {\n        cout << p.first << \" \" << p.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAX_MOVES = 100000;\n\n// directions: up, down, left, right\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\nconst char move_char[] = {'U', 'D', 'L', 'R'};\nconst char opposite_char[] = {'D', 'U', 'R', 'L'};\n\nint N;\nvector<string> h, v;\nvector<vector<int>> d;\n\n// adjacency list: for each cell (i,j) list of (ni,nj,move_char)\nvector<vector<vector<tuple<int,int,char>>>> adj;\n\n// for DFS\nvector<vector<bool>> visited;\nvector<int> next_neighbor_idx; // index of next neighbor to try for each cell (flattened)\n\n// for BFS\nvector<vector<int>> dist;\nvector<vector<pair<int,int>>> parent;\nvector<vector<char>> move_from_parent;\n\nchar get_opposite(char c) {\n    for (int k = 0; k < 4; ++k)\n        if (move_char[k] == c) return opposite_char[k];\n    return '?';\n}\n\nvoid build_graph() {\n    adj.assign(N, vector<vector<tuple<int,int,char>>>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            // down\n            if (i+1 < N && h[i][j] == '0')\n                adj[i][j].emplace_back(i+1, j, 'D');\n            // up\n            if (i-1 >= 0 && h[i-1][j] == '0')\n                adj[i][j].emplace_back(i-1, j, 'U');\n            // right\n            if (j+1 < N && v[i][j] == '0')\n                adj[i][j].emplace_back(i, j+1, 'R');\n            // left\n            if (j-1 >= 0 && v[i][j-1] == '0')\n                adj[i][j].emplace_back(i, j-1, 'L');\n        }\n    }\n}\n\nstring generate_dfs_route() {\n    visited.assign(N, vector<bool>(N, false));\n    next_neighbor_idx.assign(N*N, 0);\n    string route;\n    stack<pair<int,int>> st;\n    stack<char> move_stack;\n    st.emplace(0, 0);\n    visited[0][0] = true;\n    while (!st.empty()) {\n        auto [i,j] = st.top();\n        int idx = i*N + j;\n        auto& neighbors = adj[i][j];\n        if (next_neighbor_idx[idx] < (int)neighbors.size()) {\n            auto [ni, nj, move] = neighbors[next_neighbor_idx[idx]++];\n            if (!visited[ni][nj]) {\n                visited[ni][nj] = true;\n                route += move;\n                move_stack.push(move);\n                st.emplace(ni, nj);\n            }\n        } else {\n            st.pop();\n            if (!move_stack.empty()) {\n                char move_back = get_opposite(move_stack.top());\n                move_stack.pop();\n                route += move_back;\n            }\n        }\n    }\n    return route;\n}\n\nvoid bfs_from_start() {\n    dist.assign(N, vector<int>(N, -1));\n    parent.assign(N, vector<pair<int,int>>(N, {-1,-1}));\n    move_from_parent.assign(N, vector<char>(N, ' '));\n    queue<pair<int,int>> q;\n    q.emplace(0, 0);\n    dist[0][0] = 0;\n    while (!q.empty()) {\n        auto [i,j] = q.front(); q.pop();\n        for (auto [ni, nj, move] : adj[i][j]) {\n            if (dist[ni][nj] == -1) {\n                dist[ni][nj] = dist[i][j] + 1;\n                parent[ni][nj] = {i,j};\n                move_from_parent[ni][nj] = move;\n                q.emplace(ni, nj);\n            }\n        }\n    }\n}\n\nstring get_path_to(int ti, int tj) {\n    string path;\n    int i = ti, j = tj;\n    while (i != 0 || j != 0) {\n        char m = move_from_parent[i][j];\n        path += m;\n        auto [pi, pj] = parent[i][j];\n        i = pi; j = pj;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nstring reverse_opposite(const string& path) {\n    string rev;\n    for (int k = (int)path.size()-1; k >= 0; --k)\n        rev += get_opposite(path[k]);\n    return rev;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    h.resize(N-1);\n    for (int i = 0; i < N-1; ++i) cin >> h[i];\n    v.resize(N);\n    for (int i = 0; i < N; ++i) cin >> v[i];\n    d.assign(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> d[i][j];\n\n    build_graph();\n\n    string base_route = generate_dfs_route();\n    int L_base = base_route.size();\n    int remaining = MAX_MOVES - L_base;\n\n    bfs_from_start();\n\n    // prepare list of cells (excluding start) with ratio d / dist\n    vector<tuple<double, int, int>> cells;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (i == 0 && j == 0) continue;\n            if (dist[i][j] > 0) {\n                double ratio = (double)d[i][j] / dist[i][j];\n                cells.emplace_back(ratio, i, j);\n            }\n        }\n    }\n    sort(cells.begin(), cells.end(), greater<>());\n\n    string extra_route;\n    while (remaining > 0) {\n        bool added = false;\n        for (auto [ratio, i, j] : cells) {\n            int w = 2 * dist[i][j];\n            if (w <= remaining) {\n                string path = get_path_to(i, j);\n                string rev = reverse_opposite(path);\n                extra_route += path + rev;\n                remaining -= w;\n                added = true;\n                break;\n            }\n        }\n        if (!added) break;\n    }\n\n    cout << base_route << extra_route << endl;\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int INF = 1e9;\n\nstruct Solver {\n    int N, M, start_idx;\n    vector<int> xs, ys;                // coordinates of each cell (index = i*N + j)\n    vector<vector<int>> cells;         // cells[letter] -> list of cell indices\n    vector<string> patterns;           // the M strings (length 5)\n    vector<vector<char>> ov;           // ov[i][j] = max overlap from pattern i to j (0..4)\n\n    Solver(int N, int M, int start_idx, const vector<string>& grid, const vector<string>& patterns)\n        : N(N), M(M), start_idx(start_idx), patterns(patterns) {\n        int total = N * N;\n        xs.resize(total);\n        ys.resize(total);\n        cells.resize(26);\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                int idx = i * N + j;\n                xs[idx] = i;\n                ys[idx] = j;\n                int ch = grid[i][j] - 'A';\n                cells[ch].push_back(idx);\n            }\n        }\n\n        // compute overlap matrix\n        ov.assign(M, vector<char>(M, 0));\n        for (int i = 0; i < M; ++i) {\n            for (int j = 0; j < M; ++j) {\n                if (i == j) continue;\n                const string &a = patterns[i], &b = patterns[j];\n                for (int k = 4; k >= 1; --k) {\n                    if (a.compare(5 - k, k, b, 0, k) == 0) {\n                        ov[i][j] = k;\n                        break;\n                    }\n                }\n            }\n        }\n    }\n\n    // greedy construction of a pattern order (tries every pattern as start)\n    vector<int> greedy_order() {\n        int best_total = -1;\n        vector<int> best_order;\n        for (int start = 0; start < M; ++start) {\n            vector<bool> used(M, false);\n            vector<int> order;\n            order.push_back(start);\n            used[start] = true;\n            for (int step = 1; step < M; ++step) {\n                int last = order.back();\n                int best_ov = -1, best_next = -1;\n                for (int j = 0; j < M; ++j) {\n                    if (!used[j]) {\n                        int o = ov[last][j];\n                        if (o > best_ov) {\n                            best_ov = o;\n                            best_next = j;\n                        }\n                    }\n                }\n                order.push_back(best_next);\n                used[best_next] = true;\n            }\n            int total = 0;\n            for (size_t i = 0; i < order.size() - 1; ++i)\n                total += ov[order[i]][order[i + 1]];\n            if (total > best_total) {\n                best_total = total;\n                best_order = order;\n            }\n        }\n        return best_order;\n    }\n\n    // simple hill\u2011climbing by random reversals (maximises total overlap)\n    void improve_order(vector<int>& order) {\n        auto total_ov = [&](const vector<int>& ord) {\n            int sum = 0;\n            for (size_t i = 0; i < ord.size() - 1; ++i)\n                sum += ov[ord[i]][ord[i + 1]];\n            return sum;\n        };\n        int cur = total_ov(order);\n        for (int iter = 0; iter < 5000; ++iter) {\n            int i = rand() % M;\n            int j = rand() % M;\n            if (i == j) continue;\n            if (i > j) swap(i, j);\n            reverse(order.begin() + i, order.begin() + j + 1);\n            int nw = total_ov(order);\n            if (nw > cur)\n                cur = nw;\n            else\n                reverse(order.begin() + i, order.begin() + j + 1);\n        }\n    }\n\n    // given an order, builds the superstring, runs DP, returns total cost and the path\n    pair<int, vector<int>> solve_order(const vector<int>& order) {\n        // build superstring S\n        string S;\n        S.reserve(5 * M);\n        S += patterns[order[0]];\n        for (size_t i = 1; i < order.size(); ++i) {\n            int prev = order[i - 1];\n            int cur = order[i];\n            int k = ov[prev][cur];\n            S += patterns[cur].substr(k);\n        }\n        int L = S.size();\n        int total_cells = N * N;\n\n        vector<int> dp_prev(total_cells, INF);\n        vector<int> dp_curr(total_cells, INF);\n        vector<short> prev_cell(L * total_cells, -1);   // flat storage for back pointers\n\n        // first character\n        int first_ch = S[0] - 'A';\n        for (int v : cells[first_ch]) {\n            int d = abs(xs[start_idx] - xs[v]) + abs(ys[start_idx] - ys[v]);\n            dp_prev[v] = d + 1;\n            prev_cell[0 * total_cells + v] = -1;       // sentinel\n        }\n\n        // remaining characters\n        for (int pos = 1; pos < L; ++pos) {\n            int cur_ch = S[pos] - 'A';\n            int prev_ch = S[pos - 1] - 'A';\n            const auto& prev_cells = cells[prev_ch];\n            const auto& cur_cells = cells[cur_ch];\n\n            fill(dp_curr.begin(), dp_curr.end(), INF);\n            for (int v : cur_cells) {\n                int best = INF;\n                short best_u = -1;\n                for (int u : prev_cells) {\n                    if (dp_prev[u] == INF) continue;\n                    int d = abs(xs[u] - xs[v]) + abs(ys[u] - ys[v]);\n                    int cand = dp_prev[u] + d;\n                    if (cand < best) {\n                        best = cand;\n                        best_u = u;\n                    }\n                }\n                dp_curr[v] = best + 1;\n                prev_cell[pos * total_cells + v] = best_u;\n            }\n            swap(dp_prev, dp_curr);\n        }\n\n        // choose best ending cell\n        int last_ch = S[L - 1] - 'A';\n        int best_cost = INF, best_end = -1;\n        for (int v : cells[last_ch]) {\n            if (dp_prev[v] < best_cost) {\n                best_cost = dp_prev[v];\n                best_end = v;\n            }\n        }\n\n        // reconstruct the sequence of cells\n        vector<int> path(L);\n        int cur_cell = best_end;\n        for (int pos = L - 1; pos >= 0; --pos) {\n            path[pos] = cur_cell;\n            cur_cell = prev_cell[pos * total_cells + cur_cell];\n        }\n\n        return {best_cost, path};\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    srand(123456);   // fixed seed for reproducibility\n\n    int N, M;\n    cin >> N >> M;\n    int si, sj;\n    cin >> si >> sj;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n    vector<string> patterns(M);\n    for (int k = 0; k < M; ++k) cin >> patterns[k];\n\n    Solver solver(N, M, si * N + sj, grid, patterns);\n\n    // obtain a good ordering of patterns\n    vector<int> order = solver.greedy_order();\n    solver.improve_order(order);\n\n    // try also the reversed order, pick the better one\n    auto [cost1, path1] = solver.solve_order(order);\n    vector<int> rev_order = order;\n    reverse(rev_order.begin(), rev_order.end());\n    auto [cost2, path2] = solver.solve_order(rev_order);\n\n    const vector<int>& final_path = (cost1 <= cost2) ? path1 : path2;\n\n    // output\n    for (int idx : final_path) {\n        int i = idx / N;\n        int j = idx % N;\n        cout << i << ' ' << j << '\\n';\n    }\n\n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <cmath>\n#include <numeric>\n#include <cstdint>\n#include <tuple>\n\nusing namespace std;\n\nstruct Placement {\n    vector<short> cells;          // indices of covered cells (0..N*N-1)\n    vector<uint8_t> contrib;      // contribution to each measurement\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cout.tie(nullptr);\n\n    int N, M;\n    double eps;\n    cin >> N >> M >> eps;\n    double alpha = 1.0 - 2.0 * eps;\n    double beta = eps;\n\n    // read shapes\n    vector<vector<pair<int, int>>> shape_cells(M);\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        shape_cells[k].resize(d);\n        for (int t = 0; t < d; ++t) {\n            cin >> shape_cells[k][t].first >> shape_cells[k][t].second;\n        }\n    }\n\n    // number of divine queries: enough for recovery but leave room for fallback drilling\n    int L = min(150, N * N - 10);\n    // random generator for subsets\n    mt19937 rng(123456);\n    uniform_real_distribution<double> prob(0.0, 1.0);\n\n    // generate random subsets and record which measurements contain each cell\n    vector<vector<int>> subsets(L);\n    vector<vector<int>> meas_including(N * N);\n    for (int l = 0; l < L; ++l) {\n        vector<int>& sub = subsets[l];\n        for (int idx = 0; idx < N * N; ++idx) {\n            if (prob(rng) < 0.5) {\n                sub.push_back(idx);\n                meas_including[idx].push_back(l);\n            }\n        }\n    }\n\n    // precompute all possible placements and their contributions\n    vector<vector<Placement>> placements(M);\n    for (int k = 0; k < M; ++k) {\n        const auto& cells = shape_cells[k];\n        int max_i = 0, max_j = 0;\n        for (auto& p : cells) {\n            max_i = max(max_i, p.first);\n            max_j = max(max_j, p.second);\n        }\n        int h = max_i + 1, w = max_j + 1;\n        for (int dx = 0; dx <= N - h; ++dx) {\n            for (int dy = 0; dy <= N - w; ++dy) {\n                Placement pl;\n                // compute cell indices\n                for (auto& p : cells) {\n                    int i = dx + p.first;\n                    int j = dy + p.second;\n                    pl.cells.push_back(i * N + j);\n                }\n                // compute contribution vector\n                pl.contrib.assign(L, 0);\n                for (int idx : pl.cells) {\n                    for (int l : meas_including[idx]) {\n                        pl.contrib[l]++;\n                    }\n                }\n                placements[k].push_back(move(pl));\n            }\n        }\n    }\n\n    // perform divine queries\n    vector<double> z_vals(L);\n    for (int l = 0; l < L; ++l) {\n        int k = subsets[l].size();\n        cout << \"q \" << k;\n        for (int idx : subsets[l]) {\n            int i = idx / N, j = idx % N;\n            cout << ' ' << i << ' ' << j;\n        }\n        cout << endl;\n        int y;\n        cin >> y;\n        z_vals[l] = (y - beta * k) / alpha;\n    }\n\n    // ----- Greedy OMP to obtain an initial assignment -----\n    vector<int> assignment(M, -1);\n    vector<double> residual = z_vals;\n    for (int iter = 0; iter < M; ++iter) {\n        double best_score = -1e100;\n        int best_shape = -1, best_place = -1;\n        for (int k = 0; k < M; ++k) {\n            if (assignment[k] != -1) continue;\n            const auto& plist = placements[k];\n            for (size_t p_idx = 0; p_idx < plist.size(); ++p_idx) {\n                const auto& p = plist[p_idx];\n                double dot = 0.0, norm2 = 0.0;\n                for (int l = 0; l < L; ++l) {\n                    double c = p.contrib[l];\n                    dot += residual[l] * c;\n                    norm2 += c * c;\n                }\n                if (norm2 == 0) continue;\n                double score = dot / sqrt(norm2);\n                if (score > best_score) {\n                    best_score = score;\n                    best_shape = k;\n                    best_place = p_idx;\n                }\n            }\n        }\n        // assign the best found\n        assignment[best_shape] = best_place;\n        const auto& p = placements[best_shape][best_place];\n        for (int l = 0; l < L; ++l) {\n            residual[l] -= p.contrib[l];\n        }\n    }\n\n    // ----- Simulated Annealing to refine the assignment -----\n    // current sums and error\n    vector<double> cur_sum(L, 0.0);\n    for (int k = 0; k < M; ++k) {\n        const auto& p = placements[k][assignment[k]];\n        for (int l = 0; l < L; ++l) cur_sum[l] += p.contrib[l];\n    }\n    double cur_err = 0.0;\n    for (int l = 0; l < L; ++l) {\n        double diff = z_vals[l] - cur_sum[l];\n        cur_err += diff * diff;\n    }\n\n    vector<int> best_assignment = assignment;\n    double best_err = cur_err;\n\n    const int SA_ITER = 50000;\n    const double INITIAL_TEMP = 1000.0;\n    const double COOLING = 0.9995;\n    double temp = INITIAL_TEMP;\n\n    mt19937 rng_sa(987654);\n    uniform_int_distribution<int> shape_dist(0, M - 1);\n    vector<uniform_int_distribution<int>> place_dist;\n    for (int k = 0; k < M; ++k) {\n        place_dist.emplace_back(0, placements[k].size() - 1);\n    }\n\n    for (int it = 0; it < SA_ITER; ++it) {\n        int k = shape_dist(rng_sa);\n        int old_idx = assignment[k];\n        int new_idx = place_dist[k](rng_sa);\n        if (new_idx == old_idx) continue;\n\n        const auto& p_old = placements[k][old_idx];\n        const auto& p_new = placements[k][new_idx];\n\n        double delta_err = 0.0;\n        for (int l = 0; l < L; ++l) {\n            double delta = (double)p_new.contrib[l] - (double)p_old.contrib[l];\n            double e_l = z_vals[l] - cur_sum[l];\n            delta_err += -2.0 * e_l * delta + delta * delta;\n        }\n\n        if (delta_err < 0 || uniform_real_distribution<double>(0, 1)(rng_sa) < exp(-delta_err / temp)) {\n            cur_err += delta_err;\n            for (int l = 0; l < L; ++l) {\n                cur_sum[l] += (p_new.contrib[l] - p_old.contrib[l]);\n            }\n            assignment[k] = new_idx;\n            if (cur_err < best_err) {\n                best_err = cur_err;\n                best_assignment = assignment;\n            }\n        }\n        temp *= COOLING;\n    }\n\n    // use the best assignment found\n    assignment = best_assignment;\n    // recompute current sums and error for this assignment\n    fill(cur_sum.begin(), cur_sum.end(), 0.0);\n    for (int k = 0; k < M; ++k) {\n        const auto& p = placements[k][assignment[k]];\n        for (int l = 0; l < L; ++l) cur_sum[l] += p.contrib[l];\n    }\n    cur_err = 0.0;\n    for (int l = 0; l < L; ++l) {\n        double diff = z_vals[l] - cur_sum[l];\n        cur_err += diff * diff;\n    }\n\n    // ----- Local hill climbing -----\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng_sa);\n        for (int k : order) {\n            int old_idx = assignment[k];\n            const auto& p_old = placements[k][old_idx];\n            for (size_t new_idx = 0; new_idx < placements[k].size(); ++new_idx) {\n                if (new_idx == old_idx) continue;\n                const auto& p_new = placements[k][new_idx];\n                double delta_err = 0.0;\n                for (int l = 0; l < L; ++l) {\n                    double delta = (double)p_new.contrib[l] - (double)p_old.contrib[l];\n                    double e_l = z_vals[l] - cur_sum[l];\n                    delta_err += -2.0 * e_l * delta + delta * delta;\n                }\n                if (delta_err < -1e-9) {\n                    cur_err += delta_err;\n                    for (int l = 0; l < L; ++l) {\n                        cur_sum[l] += delta;\n                    }\n                    assignment[k] = new_idx;\n                    improved = true;\n                    break; // go to next shape\n                }\n            }\n        }\n    }\n\n    // ----- Reconstruct the island from the assignment -----\n    vector<vector<int>> grid(N, vector<int>(N, 0));\n    for (int k = 0; k < M; ++k) {\n        const auto& p = placements[k][assignment[k]];\n        for (int idx : p.cells) {\n            int i = idx / N, j = idx % N;\n            grid[i][j]++;\n        }\n    }\n\n    // collect cells with positive oil reserves\n    vector<pair<int, int>> positive;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] > 0) {\n                positive.emplace_back(i, j);\n            }\n        }\n    }\n\n    // ----- First guess -----\n    cout << \"a \" << positive.size();\n    for (auto& p : positive) {\n        cout << ' ' << p.first << ' ' << p.second;\n    }\n    cout << endl;\n\n    int resp;\n    cin >> resp;\n    if (resp == 1) {\n        return 0;\n    }\n\n    // ----- Fallback: drill every cell -----\n    vector<bool> has_oil(N * N, false);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << \"q 1 \" << i << ' ' << j << endl;\n            int val;\n            cin >> val;\n            if (val > 0) {\n                has_oil[i * N + j] = true;\n            }\n        }\n    }\n\n    positive.clear();\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (has_oil[i * N + j]) {\n                positive.emplace_back(i, j);\n            }\n        }\n    }\n\n    cout << \"a \" << positive.size();\n    for (auto& p : positive) {\n        cout << ' ' << p.first << ' ' << p.second;\n    }\n    cout << endl;\n\n    cin >> resp; // should be 1\n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cstdint>\n#include <climits>\n\nusing namespace std;\n\nusing ll = long long;\nconst ll INF = 1e18;\n\nint main() {\n    int W, D, N;\n    cin >> W >> D >> N;\n    \n    vector<vector<int>> a(D, vector<int>(N));\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            cin >> a[d][k];\n        }\n        // sort descending for this day\n        sort(a[d].begin(), a[d].end(), greater<int>());\n    }\n    \n    // cost_rank[i][w] : total shortage cost for rank i (0\u2011based) if assigned width w\n    vector<vector<ll>> cost_rank(N, vector<ll>(W + 1, 0));\n    for (int i = 0; i < N; ++i) {\n        for (int w = 1; w <= W; ++w) {\n            ll area = (ll)w * W;\n            ll cost = 0;\n            for (int d = 0; d < D; ++d) {\n                if (a[d][i] > area) {\n                    cost += 100LL * (a[d][i] - area);\n                }\n            }\n            cost_rank[i][w] = cost;\n        }\n    }\n    \n    // DP over ranks\n    // dp[i][s][w] = minimum total cost for first i+1 ranks, total width s, last width = w\n    vector<vector<vector<ll>>> dp(N, vector<vector<ll>>(W + 1, vector<ll>(W + 1, INF)));\n    \n    // rank 0\n    for (int w = 1; w <= W; ++w) {\n        dp[0][w][w] = cost_rank[0][w];\n    }\n    \n    // ranks 1 .. N-1\n    for (int i = 1; i < N; ++i) {\n        // precompute best[t][w] = min_{w' >= w} dp[i-1][t][w']\n        vector<vector<ll>> best(W + 1, vector<ll>(W + 1, INF));\n        for (int t = 0; t <= W; ++t) {\n            ll min_val = INF;\n            for (int w = W; w >= 1; --w) {\n                if (w <= t) {\n                    min_val = min(min_val, dp[i - 1][t][w]);\n                }\n                best[t][w] = min_val;\n            }\n        }\n        \n        // fill dp[i]\n        for (int s = i + 1; s <= W; ++s) {          // at least i+1 total width\n            for (int w = 1; w <= min(s, W); ++w) {\n                int t = s - w;\n                if (t < i) continue;                // previous ranks need at least i width\n                if (best[t][w] == INF) continue;\n                dp[i][s][w] = best[t][w] + cost_rank[i][w];\n            }\n        }\n    }\n    \n    // find optimal total cost and reconstruct widths\n    ll min_cost = INF;\n    int best_s = -1, best_w = -1;\n    for (int s = N; s <= W; ++s) {\n        for (int w = 1; w <= W; ++w) {\n            if (dp[N - 1][s][w] < min_cost) {\n                min_cost = dp[N - 1][s][w];\n                best_s = s;\n                best_w = w;\n            }\n        }\n    }\n    \n    vector<int> widths(N);\n    widths[N - 1] = best_w;\n    int cur_s = best_s, cur_w = best_w;\n    for (int i = N - 1; i >= 1; --i) {\n        int t = cur_s - cur_w;\n        ll target = dp[i][cur_s][cur_w] - cost_rank[i][cur_w];\n        // find w_prev that achieved the minimum\n        for (int w_prev = cur_w; w_prev <= t; ++w_prev) {\n            if (dp[i - 1][t][w_prev] == target) {\n                widths[i - 1] = w_prev;\n                cur_w = w_prev;\n                cur_s = t;\n                break;\n            }\n        }\n    }\n    // widths[0..N-1] are already in non\u2011increasing order\n    \n    // build fixed vertical strips\n    vector<pair<int, int>> strip_lr(N);  // (left, right) column coordinates\n    int left = 0;\n    for (int i = 0; i < N; ++i) {\n        int right = left + widths[i];\n        strip_lr[i] = {left, right};\n        left = right;\n    }\n    // optional: if left < W, the remaining space stays empty\n    \n    // output for each day\n    for (int d = 0; d < D; ++d) {\n        // create list of (area, original_index) and sort descending by area\n        vector<pair<int, int>> order(N);\n        for (int k = 0; k < N; ++k) {\n            order[k] = {a[d][k], k};\n        }\n        sort(order.begin(), order.end(), greater<pair<int, int>>());\n        \n        // assign strips to reservations\n        vector<int> assign(N);\n        for (int i = 0; i < N; ++i) {\n            int orig_idx = order[i].second;\n            assign[orig_idx] = i;   // strip i gets this reservation\n        }\n        \n        // output rectangles in original order of reservations (k = 0..N-1)\n        for (int k = 0; k < N; ++k) {\n            int strip_idx = assign[k];\n            auto [l, r] = strip_lr[strip_idx];\n            // rectangle: top row = 0, bottom row = W, left column = l, right column = r\n            cout << \"0 \" << l << \" \" << W << \" \" << r << \"\\n\";\n        }\n    }\n    \n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <array>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <cstdint>\n\nusing namespace std;\n\nconst int MOD = 998244353;\nconst int N = 9, M = 20, K = 81;   // given fixed values\n\nstruct Operation {\n    int stamp, p, q;\n    vector<pair<int, int>> cells;   // (cell_index, value)\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // ----- input -----\n    int n, m, k;   // though they are fixed, we read them\n    cin >> n >> m >> k;\n\n    vector<int64_t> cur(81);   // flattened 9x9 board, current values\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cin >> cur[i * 9 + j];\n        }\n    }\n\n    vector<array<array<int, 3>, 3>> stamps(m);\n    for (int s = 0; s < m; ++s) {\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                cin >> stamps[s][i][j];\n            }\n        }\n    }\n\n    // ----- precompute all possible operations -----\n    vector<Operation> ops;\n    for (int s = 0; s < m; ++s) {\n        for (int p = 0; p <= n - 3; ++p) {\n            for (int q = 0; q <= n - 3; ++q) {\n                Operation op;\n                op.stamp = s;\n                op.p = p;\n                op.q = q;\n                for (int i = 0; i < 3; ++i) {\n                    for (int j = 0; j < 3; ++j) {\n                        int cell = (p + i) * 9 + (q + j);\n                        int val = stamps[s][i][j];\n                        op.cells.emplace_back(cell, val);\n                    }\n                }\n                ops.push_back(move(op));\n            }\n        }\n    }\n    const int num_ops = ops.size();   // 20*7*7 = 980\n\n    // ----- initial score -----\n    int64_t score = 0;\n    for (int i = 0; i < 81; ++i) score += cur[i] % MOD;\n\n    // ----- helper lambdas -----\n    auto delta_add = [&](int id) -> int64_t {\n        int64_t d = 0;\n        for (auto [idx, val] : ops[id].cells) {\n            int64_t old_rem = cur[idx] % MOD;\n            int64_t new_val = cur[idx] + val;\n            int64_t new_rem = new_val % MOD;\n            d += new_rem - old_rem;\n        }\n        return d;\n    };\n\n    auto apply_add = [&](int id) {\n        for (auto [idx, val] : ops[id].cells) {\n            cur[idx] += val;\n        }\n    };\n\n    auto delta_remove = [&](int id) -> int64_t {\n        int64_t d = 0;\n        for (auto [idx, val] : ops[id].cells) {\n            int64_t old_rem = cur[idx] % MOD;\n            int64_t new_val = cur[idx] - val;\n            int64_t new_rem = new_val % MOD;\n            d += new_rem - old_rem;\n        }\n        return d;\n    };\n\n    auto apply_remove = [&](int id) {\n        for (auto [idx, val] : ops[id].cells) {\n            cur[idx] -= val;\n        }\n    };\n\n    // ----- greedy initial solution -----\n    vector<int> cur_ops;\n    while (cur_ops.size() < K) {\n        int best_id = -1;\n        int64_t best_delta = 0;\n        for (int id = 0; id < num_ops; ++id) {\n            int64_t d = delta_add(id);\n            if (d > best_delta) {\n                best_delta = d;\n                best_id = id;\n            }\n        }\n        if (best_delta <= 0) break;\n        apply_add(best_id);\n        cur_ops.push_back(best_id);\n        score += best_delta;\n    }\n\n    // ----- simulated annealing -----\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> uni_real(0.0, 1.0);\n\n    const int max_iter = 1'000'000;\n    const double T0 = 1e8;\n    double T = T0;\n\n    static int64_t contrib[81];          // for replace moves\n    static vector<int> touched;          // cells affected in a replace\n\n    for (int iter = 0; iter < max_iter; ++iter) {\n        double r = uni_real(rng);\n        if (r < 0.333 && cur_ops.size() < K) {\n            // ---- add a new operation ----\n            int new_id = rng() % num_ops;\n            int64_t delta = delta_add(new_id);\n            if (delta > 0 || (delta <= 0 && exp(delta / T) > uni_real(rng))) {\n                apply_add(new_id);\n                cur_ops.push_back(new_id);\n                score += delta;\n            }\n        } else if (r < 0.666 && !cur_ops.empty()) {\n            // ---- remove an operation ----\n            int idx = rng() % cur_ops.size();\n            int old_id = cur_ops[idx];\n            int64_t delta = delta_remove(old_id);\n            if (delta > 0 || (delta <= 0 && exp(delta / T) > uni_real(rng))) {\n                apply_remove(old_id);\n                // erase by swapping with last\n                cur_ops[idx] = cur_ops.back();\n                cur_ops.pop_back();\n                score += delta;\n            }\n        } else if (!cur_ops.empty()) {\n            // ---- replace an operation ----\n            int idx = rng() % cur_ops.size();\n            int old_id = cur_ops[idx];\n            int new_id = rng() % num_ops;\n            if (new_id == old_id) continue;\n\n            // compute net change using contrib array\n            touched.clear();\n            for (auto [i, v] : ops[old_id].cells) {\n                if (contrib[i] == 0) touched.push_back(i);\n                contrib[i] -= v;\n            }\n            for (auto [i, v] : ops[new_id].cells) {\n                if (contrib[i] == 0) touched.push_back(i);\n                contrib[i] += v;\n            }\n\n            int64_t delta = 0;\n            for (int i : touched) {\n                int64_t net = contrib[i];\n                int64_t old_rem = cur[i] % MOD;\n                int64_t new_val = cur[i] + net;\n                int64_t new_rem = new_val % MOD;\n                delta += new_rem - old_rem;\n            }\n\n            if (delta > 0 || (delta <= 0 && exp(delta / T) > uni_real(rng))) {\n                // accept\n                for (int i : touched) {\n                    cur[i] += contrib[i];\n                }\n                cur_ops[idx] = new_id;\n                score += delta;\n            }\n\n            // reset contrib for next use\n            for (int i : touched) {\n                contrib[i] = 0;\n            }\n        }\n\n        // cool down\n        T = T0 * (1.0 - (double)iter / max_iter);\n    }\n\n    // ----- output -----\n    cout << cur_ops.size() << '\\n';\n    for (int id : cur_ops) {\n        cout << ops[id].stamp << ' ' << ops[id].p << ' ' << ops[id].q << '\\n';\n    }\n\n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <deque>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <climits>\n#include <cstdlib>\n#include <utility>\n\nusing namespace std;\n\nint main() {\n    const int N = 5;\n    int A[N][N];\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> A[i][j];\n\n    // queues of remaining containers for each receiving gate\n    deque<int> gate_rem[N];\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            gate_rem[i].push_back(A[i][j]);\n\n    int grid[N][N];\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            grid[i][j] = -1;          // -1 means empty\n\n    int hold = -1;                    // -1: not holding, otherwise container number\n    int posx = 0, posy = 0;           // position of the large crane\n\n    bool dispatched[25] = {false};\n    int next_exp[5];                  // next expected container for each row\n    for (int i = 0; i < N; ++i)\n        next_exp[i] = N * i;\n\n    pair<int, int> loc[25];           // location of container on the grid, (-1,-1) if not present\n    for (int i = 0; i < 25; ++i)\n        loc[i] = {-1, -1};\n\n    vector<string> ans(5);            // actions for the five cranes\n    int dispatched_cnt = 0;\n\n    const int INF = 1000000;\n\n    // helper lambdas\n    auto manhattan = [](int x1, int y1, int x2, int y2) {\n        return abs(x1 - x2) + abs(y1 - y2);\n    };\n\n    auto move_towards = [](int x, int y, int tx, int ty) -> char {\n        if (x < tx) return 'D';\n        if (x > tx) return 'U';\n        if (y < ty) return 'R';\n        if (y > ty) return 'L';\n        return '.';\n    };\n\n    auto find_buffer = [&](int x, int y, bool allow_active_gates) -> pair<int, int> {\n        int best_dist = INF;\n        pair<int, int> best = {-1, -1};\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N - 1; ++j) {   // columns 0..3 (col4 is dispatch)\n                if (grid[i][j] != -1) continue;\n                if (j == 0 && !allow_active_gates && !gate_rem[i].empty())\n                    continue;\n                int d = manhattan(x, y, i, j);\n                if (d < best_dist) {\n                    best_dist = d;\n                    best = {i, j};\n                }\n            }\n        }\n        return best;\n    };\n\n    auto estimated_store_distance = [&](int x, int y) -> int {\n        auto buf = find_buffer(x, y, false);\n        if (buf.first == -1) return INF;\n        return manhattan(x, y, buf.first, buf.second);\n    };\n\n    struct Candidate {\n        int cost;\n        int type;       // 0 = retrieve stored needed, 1 = pick up from gate\n        int b;          // container number\n        int px, py;     // pickup location\n        bool needed;    // for type 1: is it the next expected?\n    };\n\n    int turn = 0;\n    while (dispatched_cnt < N * N) {\n        ++turn;\n        if (turn > 10000) break;   // safety limit\n\n        // ---------- Step 1: place containers at receiving gates ----------\n        for (int i = 0; i < N; ++i) {\n            if (grid[i][0] == -1) {\n                // placement is blocked only if the large crane is at (i,0) and holding\n                if (!(posx == i && posy == 0 && hold != -1)) {\n                    if (!gate_rem[i].empty()) {\n                        int b = gate_rem[i].front();\n                        gate_rem[i].pop_front();\n                        grid[i][0] = b;\n                        loc[b] = {i, 0};\n                    }\n                }\n            }\n        }\n\n        // ---------- Step 2: decide action for the large crane ----------\n        char action;\n\n        if (hold != -1) {   // holding a container\n            int b = hold;\n            int r = b / N;\n            if (b == next_exp[r]) {   // should deliver\n                if (posx == r && posy == N - 1)\n                    action = 'Q';\n                else\n                    action = move_towards(posx, posy, r, N - 1);\n            } else {   // should store\n                // can we release here?\n                bool can_release_here = false;\n                if (posy != N - 1 && grid[posx][posy] == -1) {\n                    if (posy != 0 || gate_rem[posx].empty())\n                        can_release_here = true;\n                }\n                if (can_release_here) {\n                    action = 'Q';\n                } else {\n                    auto target = find_buffer(posx, posy, false);\n                    if (target.first == -1)   // no buffer -> fallback to deliver (causes inversion)\n                        target = {r, N - 1};\n                    action = move_towards(posx, posy, target.first, target.second);\n                }\n            }\n        } else {   // not holding\n            vector<Candidate> cand;\n\n            // retrieve stored needed containers\n            for (int r = 0; r < N; ++r) {\n                int b = next_exp[r];\n                if (b >= 0 && b < N * N && loc[b].first != -1) {\n                    int px = loc[b].first, py = loc[b].second;\n                    int d1 = manhattan(posx, posy, px, py);\n                    int d2 = manhattan(px, py, r, N - 1);\n                    int cost = d1 + d2 + 2;\n                    cand.push_back({cost, 0, b, px, py, true});\n                }\n            }\n\n            // pick up from gates\n            for (int i = 0; i < N; ++i) {\n                if (gate_rem[i].empty()) continue;\n                int head = gate_rem[i][0];\n                // only consider if the gate cell is empty or already contains the head\n                if (grid[i][0] != -1 && grid[i][0] != head) continue;\n                int px = i, py = 0;\n                int r = head / N;\n                bool needed = (head == next_exp[r]);\n                int d1 = manhattan(posx, posy, px, py);\n                int d2;\n                if (needed) {\n                    d2 = manhattan(px, py, r, N - 1);\n                } else {\n                    d2 = estimated_store_distance(px, py);\n                    if (d2 >= INF) d2 = 1000;   // large fallback\n                }\n                int cost = d1 + d2 + 2;\n                cand.push_back({cost, 1, head, px, py, needed});\n            }\n\n            if (cand.empty()) {\n                action = '.';\n            } else {\n                auto best = *min_element(cand.begin(), cand.end(),\n                    [](const Candidate& a, const Candidate& b) { return a.cost < b.cost; });\n                if (posx == best.px && posy == best.py)\n                    action = 'P';\n                else\n                    action = move_towards(posx, posy, best.px, best.py);\n            }\n        }\n\n        // execute the chosen action for crane 0\n        switch (action) {\n            case 'P':\n                hold = grid[posx][posy];\n                grid[posx][posy] = -1;\n                loc[hold] = {-1, -1};\n                break;\n            case 'Q':\n                grid[posx][posy] = hold;\n                loc[hold] = {posx, posy};\n                hold = -1;\n                break;\n            case 'U':\n                if (posx > 0) posx--;\n                break;\n            case 'D':\n                if (posx < N - 1) posx++;\n                break;\n            case 'L':\n                if (posy > 0) posy--;\n                break;\n            case 'R':\n                if (posy < N - 1) posy++;\n                break;\n            case '.':\n                break;\n            case 'B':\n                break;   // never used for crane 0\n        }\n\n        ans[0] += action;\n\n        // actions for the four small cranes (1..4)\n        for (int i = 1; i < N; ++i) {\n            if (turn == 1)\n                ans[i] += 'B';\n            else\n                ans[i] += '.';\n        }\n\n        // ---------- Step 3: dispatch containers at dispatch gates ----------\n        for (int i = 0; i < N; ++i) {\n            if (grid[i][N - 1] != -1) {\n                int b = grid[i][N - 1];\n                grid[i][N - 1] = -1;\n                dispatched[b] = true;\n                loc[b] = {-1, -1};\n                dispatched_cnt++;\n                // update next expected for this row\n                for (int c = N * i; c < N * (i + 1); ++c) {\n                    if (!dispatched[c]) {\n                        next_exp[i] = c;\n                        break;\n                    }\n                }\n            }\n        }\n\n        if (dispatched_cnt == N * N) break;\n    }\n\n    // output\n    for (int i = 0; i < N; ++i)\n        cout << ans[i] << endl;\n\n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <cassert>\n\nusing namespace std;\n\nstruct Square {\n    int x, y, h;\n};\n\n// compute Manhattan distance\ninline int manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\n// evaluate a permutation: returns (cost_without_base, feasible)\npair<long long, bool> evaluate(const vector<int>& perm, const vector<Square>& squares) {\n    long long total_steps = 0;\n    long long load_dist = 0;\n    int load = 0;\n    int cur_x = 0, cur_y = 0;\n    bool feasible = true;\n\n    for (int idx : perm) {\n        const Square& sq = squares[idx];\n        int d = manhattan(cur_x, cur_y, sq.x, sq.y);\n        total_steps += d;\n        load_dist += (long long)load * d;\n\n        // perform load/unload at the square\n        load += sq.h;\n        if (load < 0) {\n            feasible = false;\n            break;\n        }\n\n        cur_x = sq.x;\n        cur_y = sq.y;\n    }\n\n    // after visiting all squares, load must be zero (guaranteed by input)\n    if (load != 0) feasible = false;\n\n    long long cost_without_base = 100 * total_steps + load_dist;\n    return {cost_without_base, feasible};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<vector<int>> h(N, vector<int>(N));\n    long long base = 0;\n    vector<Square> squares;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> h[i][j];\n            if (h[i][j] != 0) {\n                squares.push_back({i, j, h[i][j]});\n                base += abs(h[i][j]);\n            }\n        }\n    }\n\n    int M = squares.size();\n    if (M == 0) {\n        // all heights are zero, nothing to do (should not happen by generation)\n        return 0;\n    }\n\n    // separate indices of positives and negatives for initial construction\n    vector<int> pos_idx, neg_idx;\n    for (int i = 0; i < M; ++i) {\n        if (squares[i].h > 0) pos_idx.push_back(i);\n        else neg_idx.push_back(i);\n    }\n\n    // build initial permutation: all positives then all negatives, each ordered by nearest neighbor\n    vector<int> init_perm;\n    vector<bool> visited(M, false);\n\n    // order positives using nearest neighbor from (0,0)\n    int cur_x = 0, cur_y = 0;\n    for (size_t k = 0; k < pos_idx.size(); ++k) {\n        int best = -1;\n        int best_dist = 1e9;\n        for (int i : pos_idx) {\n            if (!visited[i]) {\n                int d = manhattan(cur_x, cur_y, squares[i].x, squares[i].y);\n                if (d < best_dist) {\n                    best_dist = d;\n                    best = i;\n                }\n            }\n        }\n        assert(best != -1);\n        visited[best] = true;\n        init_perm.push_back(best);\n        cur_x = squares[best].x;\n        cur_y = squares[best].y;\n    }\n\n    // order negatives using nearest neighbor from the last positive\n    for (size_t k = 0; k < neg_idx.size(); ++k) {\n        int best = -1;\n        int best_dist = 1e9;\n        for (int i : neg_idx) {\n            if (!visited[i]) {\n                int d = manhattan(cur_x, cur_y, squares[i].x, squares[i].y);\n                if (d < best_dist) {\n                    best_dist = d;\n                    best = i;\n                }\n            }\n        }\n        assert(best != -1);\n        visited[best] = true;\n        init_perm.push_back(best);\n        cur_x = squares[best].x;\n        cur_y = squares[best].y;\n    }\n\n    // simulated annealing\n    const int MAX_ITER = 200000;\n    double start_temp = 10000.0;\n    double end_temp = 1e-2;\n    double cooling = exp(log(end_temp / start_temp) / MAX_ITER);\n\n    random_device rd;\n    mt19937 rng(rd());\n    uniform_real_distribution<double> uni(0.0, 1.0);\n    uniform_int_distribution<int> rand_idx(0, M-1);\n\n    vector<int> best_perm = init_perm;\n    auto [best_cost, feasible_init] = evaluate(best_perm, squares);\n    assert(feasible_init);\n    vector<int> cur_perm = best_perm;\n    long long cur_cost = best_cost;\n\n    for (int iter = 0; iter < MAX_ITER; ++iter) {\n        double T = start_temp * pow(cooling, iter);\n        vector<int> new_perm = cur_perm;\n\n        // generate a move\n        if (uni(rng) < 0.5) {\n            // swap two random positions\n            int i = rand_idx(rng);\n            int j = rand_idx(rng);\n            if (i != j) swap(new_perm[i], new_perm[j]);\n        } else {\n            // reverse a random segment\n            int i = rand_idx(rng);\n            int j = rand_idx(rng);\n            if (i > j) swap(i, j);\n            reverse(new_perm.begin() + i, new_perm.begin() + j + 1);\n        }\n\n        auto [new_cost, feasible] = evaluate(new_perm, squares);\n        if (!feasible) continue;\n\n        if (new_cost < cur_cost || uni(rng) < exp((cur_cost - new_cost) / T)) {\n            cur_perm = new_perm;\n            cur_cost = new_cost;\n            if (cur_cost < best_cost) {\n                best_perm = cur_perm;\n                best_cost = cur_cost;\n            }\n        }\n    }\n\n    // output the operation sequence for the best permutation\n    cur_x = 0; cur_y = 0; int load = 0;\n    for (int idx : best_perm) {\n        const Square& sq = squares[idx];\n        // move to the square\n        while (cur_y < sq.y) { cout << \"R\\n\"; ++cur_y; }\n        while (cur_y > sq.y) { cout << \"L\\n\"; --cur_y; }\n        while (cur_x < sq.x) { cout << \"D\\n\"; ++cur_x; }\n        while (cur_x > sq.x) { cout << \"U\\n\"; --cur_x; }\n        // load or unload\n        if (sq.h > 0) {\n            cout << \"+\" << sq.h << \"\\n\";\n            load += sq.h;\n        } else {\n            cout << \"-\" << -sq.h << \"\\n\";\n            load += sq.h;  // h is negative\n        }\n    }\n\n    return 0;\n}","ahc035":"#include <cstdio>\n#include <vector>\n#include <array>\n#include <algorithm>\n#include <numeric>\n\nusing namespace std;\n\nconst int N = 6;\nconst int M = 15;\nconst int T = 10;\nconst int SEED_COUNT = 2 * N * (N - 1); // 60\n\nusing Seed = array<int, M>;\n\n// Select 36 seeds: Pareto optimal ones first, then highest sums\nvector<int> select_seeds(const vector<Seed>& seeds, const vector<int>& sums) {\n    vector<bool> dominated(SEED_COUNT, false);\n    for (int i = 0; i < SEED_COUNT; ++i) {\n        for (int j = 0; j < SEED_COUNT; ++j) {\n            if (i == j) continue;\n            bool all_geq = true;\n            bool any_greater = false;\n            for (int l = 0; l < M; ++l) {\n                if (seeds[j][l] < seeds[i][l]) {\n                    all_geq = false;\n                    break;\n                }\n                if (seeds[j][l] > seeds[i][l]) any_greater = true;\n            }\n            if (all_geq && any_greater) {\n                dominated[i] = true;\n                break;\n            }\n        }\n    }\n\n    vector<int> pareto;\n    for (int i = 0; i < SEED_COUNT; ++i) {\n        if (!dominated[i]) pareto.push_back(i);\n    }\n\n    vector<int> selected;\n    if (pareto.size() >= 36) {\n        sort(pareto.begin(), pareto.end(),\n             [&](int a, int b) { return sums[a] > sums[b]; });\n        selected.assign(pareto.begin(), pareto.begin() + 36);\n    } else {\n        selected = pareto;\n        vector<bool> in_pareto(SEED_COUNT, false);\n        for (int p : pareto) in_pareto[p] = true;\n        vector<int> remaining;\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            if (!in_pareto[i]) remaining.push_back(i);\n        }\n        sort(remaining.begin(), remaining.end(),\n             [&](int a, int b) { return sums[a] > sums[b]; });\n        int need = 36 - selected.size();\n        selected.insert(selected.end(), remaining.begin(), remaining.begin() + need);\n    }\n    return selected;\n}\n\nint main() {\n    // Precompute cell order by degree (higher degree first)\n    vector<pair<int, int>> cells; // (degree, cell_index)\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int degree = 4;\n            if (i == 0 || i == N - 1) --degree;\n            if (j == 0 || j == N - 1) --degree;\n            cells.push_back({degree, i * N + j});\n        }\n    }\n    sort(cells.begin(), cells.end(),\n         [](const auto& a, const auto& b) { return a.first > b.first; });\n    vector<int> cell_order;\n    for (auto& p : cells) cell_order.push_back(p.second);\n\n    vector<Seed> seeds(SEED_COUNT);\n    vector<int> sums(SEED_COUNT);\n\n    // Read initial seeds\n    for (int i = 0; i < SEED_COUNT; ++i) {\n        for (int j = 0; j < M; ++j) {\n            scanf(\"%d\", &seeds[i][j]);\n        }\n        sums[i] = accumulate(seeds[i].begin(), seeds[i].end(), 0);\n    }\n\n    for (int t = 0; t < T; ++t) {\n        // Select seeds for planting\n        vector<int> selected = select_seeds(seeds, sums);\n        // Sort selected by sum descending\n        sort(selected.begin(), selected.end(),\n             [&](int a, int b) { return sums[a] > sums[b]; });\n\n        // Assign seeds to grid cells\n        vector<vector<int>> grid(N, vector<int>(N));\n        for (int k = 0; k < 36; ++k) {\n            int cell_idx = cell_order[k];\n            int i = cell_idx / N;\n            int j = cell_idx % N;\n            grid[i][j] = selected[k];\n        }\n\n        // Output the grid\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                printf(\"%d\", grid[i][j]);\n                if (j < N - 1) printf(\" \");\n                else printf(\"\\n\");\n            }\n        }\n        fflush(stdout);\n\n        // Read new seeds\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            for (int j = 0; j < M; ++j) {\n                scanf(\"%d\", &seeds[i][j]);\n            }\n            sums[i] = accumulate(seeds[i].begin(), seeds[i].end(), 0);\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <string>\n#include <cmath>\n#include <cassert>\n#include <climits>\n\nusing namespace std;\n\nstruct Point {\n    int x, y;\n    Point(int x = 0, int y = 0) : x(x), y(y) {}\n    bool operator==(const Point& other) const {\n        return x == other.x && y == other.y;\n    }\n};\n\nint manhattan(const Point& a, const Point& b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\nint N, M, V_arm; // V_arm = number of vertices in the arm (given V)\nvector<string> s_grid, t_grid;\nvector<Point> pickups;   // initial positions that need to be moved\nvector<Point> dropoffs;  // target positions that need to be filled\n\n// current state of the robotic arm\nPoint root;                     // current root position\nvector<int> cur_dir;            // current directions of edges (size = V_arm-1)\nvector<string> output_turns;    // sequence of operation strings\n\n// direction vectors: 0:right, 1:down, 2:left, 3:up\nconst int dx_dir[4] = {0, 1, 0, -1};\nconst int dy_dir[4] = {1, 0, -1, 0};\n\n// Helper: for a given cell, find the root position and offset (dx,dy) with Manhattan distance D\n// that minimizes distance from current root.\npair<Point, Point> find_best_root_offset(const Point& cell, const Point& cur_root, int D) {\n    int best_dist = INT_MAX;\n    Point best_root, best_offset;\n    for (int dx = -D; dx <= D; ++dx) {\n        int abs_dx = abs(dx);\n        int abs_dy = D - abs_dx;\n        for (int dy_sign : {1, -1}) {\n            int dy = dy_sign * abs_dy;\n            Point cand_root(cell.x - dx, cell.y - dy);\n            if (cand_root.x >= 0 && cand_root.x < N &&\n                cand_root.y >= 0 && cand_root.y < N) {\n                int dist = manhattan(cur_root, cand_root);\n                if (dist < best_dist) {\n                    best_dist = dist;\n                    best_root = cand_root;\n                    best_offset = Point(dx, dy);\n                }\n            }\n        }\n    }\n    return {best_root, best_offset};\n}\n\n// Move the root step by step to target_root, outputting moves.\nvoid move_to(const Point& target_root) {\n    while (root.x != target_root.x || root.y != target_root.y) {\n        char move_char = '.';\n        if (root.x < target_root.x) {\n            move_char = 'D';\n            root.x++;\n        } else if (root.x > target_root.x) {\n            move_char = 'U';\n            root.x--;\n        } else if (root.y < target_root.y) {\n            move_char = 'R';\n            root.y++;\n        } else if (root.y > target_root.y) {\n            move_char = 'L';\n            root.y--;\n        }\n        string turn(2 * V_arm, '.');\n        turn[0] = move_char;\n        output_turns.push_back(turn);\n    }\n}\n\n// Change the offset to (tx,ty) and perform action act ('P' for grab/release, '.' otherwise).\n// The function may output one or two turns.\nvoid change_offset_and_act(int tx, int ty, char act) {\n    int D = V_arm - 1; // number of edges\n    int H = abs(ty);   // number of horizontal edges needed\n    int V_edges = D - H; // = abs(tx)\n\n    int hor_sign = (ty > 0) ? 0 : 2; // 0:right, 2:left\n    int ver_sign = (tx > 0) ? 1 : 3; // 1:down, 3:up\n\n    // Compute target directions for each edge with min-cost assignment\n    vector<int> target_dir(D, 0);\n    vector<int> cost_hor(D), cost_ver(D);\n    for (int i = 0; i < D; ++i) {\n        int d = cur_dir[i];\n        cost_hor[i] = min(abs(d - hor_sign), 4 - abs(d - hor_sign));\n        cost_ver[i] = min(abs(d - ver_sign), 4 - abs(d - ver_sign));\n    }\n\n    vector<pair<int, int>> diff; // (cost_hor - cost_ver, index)\n    for (int i = 0; i < D; ++i) {\n        diff.emplace_back(cost_hor[i] - cost_ver[i], i);\n    }\n    sort(diff.begin(), diff.end());\n\n    vector<bool> is_hor(D, false);\n    for (int i = 0; i < H; ++i) {\n        is_hor[diff[i].second] = true;\n    }\n    for (int i = 0; i < D; ++i) {\n        if (is_hor[i])\n            target_dir[i] = hor_sign;\n        else\n            target_dir[i] = ver_sign;\n    }\n\n    // Compute required rotations (number of clockwise 90\u00b0 steps)\n    vector<int> need(D);\n    for (int i = 0; i < D; ++i) {\n        need[i] = (target_dir[i] - cur_dir[i] + 4) % 4;\n    }\n\n    bool has_180 = false;\n    for (int i = 0; i < D; ++i) {\n        if (need[i] == 2) {\n            has_180 = true;\n            break;\n        }\n    }\n\n    auto make_rotation_string = [&](bool final_turn) -> string {\n        string rot(D, '.');\n        for (int i = 0; i < D; ++i) {\n            if (need[i] == 0) rot[i] = '.';\n            else if (need[i] == 1) rot[i] = 'R';\n            else if (need[i] == 2) {\n                rot[i] = 'R'; // one rotation now, another later if needed\n            }\n            else if (need[i] == 3) rot[i] = 'L';\n        }\n        return rot;\n    };\n\n    if (!has_180) {\n        // One turn is enough\n        string rot_str = make_rotation_string(true);\n        // Update cur_dir\n        for (int i = 0; i < D; ++i) {\n            if (need[i] == 1) cur_dir[i] = (cur_dir[i] + 1) % 4;\n            else if (need[i] == 3) cur_dir[i] = (cur_dir[i] + 3) % 4;\n        }\n        // Build turn string\n        string turn(2 * V_arm, '.');\n        turn[0] = '.'; // no move\n        for (int i = 0; i < D; ++i) turn[1 + i] = rot_str[i];\n        if (act == 'P') turn[2 * V_arm - 1] = 'P'; // fingertip action at vertex V_arm-1\n        output_turns.push_back(turn);\n    } else {\n        // Need two turns\n        // First turn: rotate once where needed\n        string rot_str1 = make_rotation_string(false);\n        // Update cur_dir after first rotation\n        for (int i = 0; i < D; ++i) {\n            if (need[i] == 1 || need[i] == 2) cur_dir[i] = (cur_dir[i] + 1) % 4;\n            else if (need[i] == 3) cur_dir[i] = (cur_dir[i] + 3) % 4;\n        }\n        // Build first turn\n        string turn1(2 * V_arm, '.');\n        turn1[0] = '.';\n        for (int i = 0; i < D; ++i) turn1[1 + i] = rot_str1[i];\n        output_turns.push_back(turn1);\n\n        // Second turn: rotate the remaining 180\u00b0 edges\n        vector<int> need2(D, 0);\n        for (int i = 0; i < D; ++i) {\n            if (need[i] == 2) need2[i] = 1;\n        }\n        string rot_str2(D, '.');\n        for (int i = 0; i < D; ++i) {\n            if (need2[i] == 1) rot_str2[i] = 'R';\n        }\n        // Update cur_dir\n        for (int i = 0; i < D; ++i) {\n            if (need2[i] == 1) cur_dir[i] = (cur_dir[i] + 1) % 4;\n        }\n        string turn2(2 * V_arm, '.');\n        turn2[0] = '.';\n        for (int i = 0; i < D; ++i) turn2[1 + i] = rot_str2[i];\n        if (act == 'P') turn2[2 * V_arm - 1] = 'P';\n        output_turns.push_back(turn2);\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Read input\n    cin >> N >> M >> V_arm;\n    s_grid.resize(N);\n    t_grid.resize(N);\n    for (int i = 0; i < N; ++i) cin >> s_grid[i];\n    for (int i = 0; i < N; ++i) cin >> t_grid[i];\n\n    // Determine pickups and dropoffs\n    vector<vector<bool>> is_target(N, vector<bool>(N, false));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (t_grid[i][j] == '1') is_target[i][j] = true;\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (s_grid[i][j] == '1') {\n                if (is_target[i][j]) {\n                    // Already at a target, mark both as done\n                    is_target[i][j] = false;\n                } else {\n                    pickups.emplace_back(i, j);\n                }\n            }\n        }\n    }\n\n    // The remaining targets are dropoffs\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (is_target[i][j]) {\n                dropoffs.emplace_back(i, j);\n            }\n        }\n    }\n\n    // Design the arm: a chain of V_arm vertices, edges of length 1\n    cout << V_arm << '\\n';\n    for (int i = 1; i < V_arm; ++i) {\n        cout << i-1 << \" 1\\n\";\n    }\n\n    // Initial root position (0,0)\n    root = Point(0, 0);\n    cout << root.x << ' ' << root.y << '\\n';\n\n    // Initialize edge directions (all right)\n    cur_dir.assign(V_arm - 1, 0);\n\n    int D = V_arm - 1; // total length of the arm\n\n    // Process each takoyaki\n    while (!pickups.empty()) {\n        // Find the closest pickup\n        int best_pickup_idx = -1;\n        int best_pickup_dist = INT_MAX;\n        Point best_pickup_root, best_pickup_offset;\n        for (int idx = 0; idx < (int)pickups.size(); ++idx) {\n            auto [cand_root, cand_offset] = find_best_root_offset(pickups[idx], root, D);\n            int dist = manhattan(root, cand_root);\n            if (dist < best_pickup_dist) {\n                best_pickup_dist = dist;\n                best_pickup_idx = idx;\n                best_pickup_root = cand_root;\n                best_pickup_offset = cand_offset;\n            }\n        }\n\n        // Move to the pickup root position\n        move_to(best_pickup_root);\n        // Change offset and grab\n        change_offset_and_act(best_pickup_offset.x, best_pickup_offset.y, 'P');\n        // Remove the pickup from the list\n        pickups.erase(pickups.begin() + best_pickup_idx);\n\n        // Find the closest dropoff\n        int best_dropoff_idx = -1;\n        int best_dropoff_dist = INT_MAX;\n        Point best_dropoff_root, best_dropoff_offset;\n        for (int idx = 0; idx < (int)dropoffs.size(); ++idx) {\n            auto [cand_root, cand_offset] = find_best_root_offset(dropoffs[idx], root, D);\n            int dist = manhattan(root, cand_root);\n            if (dist < best_dropoff_dist) {\n                best_dropoff_dist = dist;\n                best_dropoff_idx = idx;\n                best_dropoff_root = cand_root;\n                best_dropoff_offset = cand_offset;\n            }\n        }\n\n        // Move to the dropoff root position\n        move_to(best_dropoff_root);\n        // Change offset and release\n        change_offset_and_act(best_dropoff_offset.x, best_dropoff_offset.y, 'P');\n        // Remove the dropoff from the list\n        dropoffs.erase(dropoffs.begin() + best_dropoff_idx);\n    }\n\n    // Output all turns\n    for (const string& turn : output_turns) {\n        cout << turn << '\\n';\n    }\n\n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <cstring>\n\nusing namespace std;\n\nstruct Point {\n    int x, y, w;\n};\n\nstruct Node {\n    int sum;\n    int max_prefix, max_prefix_end;\n    int max_suffix, max_suffix_start;\n    int max_sub, max_sub_start, max_sub_end;\n};\n\nNode merge(const Node& l, const Node& r) {\n    Node res;\n    res.sum = l.sum + r.sum;\n\n    // max_prefix\n    if (l.max_prefix >= l.sum + r.max_prefix) {\n        res.max_prefix = l.max_prefix;\n        res.max_prefix_end = l.max_prefix_end;\n    } else {\n        res.max_prefix = l.sum + r.max_prefix;\n        res.max_prefix_end = r.max_prefix_end;\n    }\n\n    // max_suffix\n    if (r.max_suffix >= r.sum + l.max_suffix) {\n        res.max_suffix = r.max_suffix;\n        res.max_suffix_start = r.max_suffix_start;\n    } else {\n        res.max_suffix = r.sum + l.max_suffix;\n        res.max_suffix_start = l.max_suffix_start;\n    }\n\n    // max_sub\n    res.max_sub = l.max_sub;\n    res.max_sub_start = l.max_sub_start;\n    res.max_sub_end = l.max_sub_end;\n    if (r.max_sub > res.max_sub) {\n        res.max_sub = r.max_sub;\n        res.max_sub_start = r.max_sub_start;\n        res.max_sub_end = r.max_sub_end;\n    }\n    int cross = l.max_suffix + r.max_prefix;\n    if (cross > res.max_sub) {\n        res.max_sub = cross;\n        res.max_sub_start = l.max_suffix_start;\n        res.max_sub_end = r.max_prefix_end;\n    }\n    return res;\n}\n\nclass SegTree {\n    int n;\n    vector<int> leaf_vals;\n    vector<Node> tree;\n\n    void build(int node, int l, int r) {\n        if (l == r) {\n            int v = leaf_vals[l];\n            tree[node].sum = v;\n            tree[node].max_prefix = v;\n            tree[node].max_prefix_end = l;\n            tree[node].max_suffix = v;\n            tree[node].max_suffix_start = l;\n            tree[node].max_sub = v;\n            tree[node].max_sub_start = l;\n            tree[node].max_sub_end = l;\n        } else {\n            int mid = (l + r) / 2;\n            build(node * 2, l, mid);\n            build(node * 2 + 1, mid + 1, r);\n            tree[node] = merge(tree[node * 2], tree[node * 2 + 1]);\n        }\n    }\n\n    void update_tree(int node, int l, int r, int idx) {\n        if (l == r) {\n            int v = leaf_vals[l];\n            tree[node].sum = v;\n            tree[node].max_prefix = v;\n            tree[node].max_suffix = v;\n            tree[node].max_sub = v;\n        } else {\n            int mid = (l + r) / 2;\n            if (idx <= mid)\n                update_tree(node * 2, l, mid, idx);\n            else\n                update_tree(node * 2 + 1, mid + 1, r, idx);\n            tree[node] = merge(tree[node * 2], tree[node * 2 + 1]);\n        }\n    }\n\npublic:\n    SegTree(int size) : n(size), leaf_vals(size, 0), tree(4 * size) {\n        build(1, 0, n - 1);\n    }\n\n    void reset() {\n        fill(leaf_vals.begin(), leaf_vals.end(), 0);\n        build(1, 0, n - 1);\n    }\n\n    void update(int idx, int delta) {\n        leaf_vals[idx] += delta;\n        update_tree(1, 0, n - 1, idx);\n    }\n\n    Node query() {\n        return tree[1];\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<Point> points(2 * N);\n    for (int i = 0; i < 2 * N; ++i) {\n        cin >> points[i].x >> points[i].y;\n        points[i].w = (i < N) ? 1 : -1;\n    }\n\n    // coordinate compression\n    vector<int> xs, ys;\n    for (auto& p : points) {\n        xs.push_back(p.x);\n        ys.push_back(p.y);\n    }\n    sort(xs.begin(), xs.end());\n    xs.erase(unique(xs.begin(), xs.end()), xs.end());\n    sort(ys.begin(), ys.end());\n    ys.erase(unique(ys.begin(), ys.end()), ys.end());\n\n    int X = xs.size();\n    int Y = ys.size();\n\n    // group points by compressed x\n    vector<vector<pair<int, int>>> points_by_x(X);\n    for (auto& p : points) {\n        int xi = lower_bound(xs.begin(), xs.end(), p.x) - xs.begin();\n        int yi = lower_bound(ys.begin(), ys.end(), p.y) - ys.begin();\n        points_by_x[xi].emplace_back(yi, p.w);\n    }\n\n    // 2D prefix sum for fast rectangle queries\n    vector<vector<int>> pref(X + 1, vector<int>(Y + 1, 0));\n    for (int i = 0; i < X; ++i) {\n        for (auto& [yi, w] : points_by_x[i]) {\n            pref[i + 1][yi + 1] += w;\n        }\n    }\n    for (int i = 1; i <= X; ++i) {\n        for (int j = 1; j <= Y; ++j) {\n            pref[i][j] += pref[i - 1][j] + pref[i][j - 1] - pref[i - 1][j - 1];\n        }\n    }\n\n    auto rect_sum = [&](int l, int r, int b, int t) -> int {\n        return pref[r + 1][t + 1] - pref[l][t + 1] - pref[r + 1][b] + pref[l][b];\n    };\n\n    // initial candidate: the whole bounding box (score = 1)\n    int best_sum = 0;\n    int best_L = 0, best_R = X - 1, best_B = 0, best_T = Y - 1;\n\n    // segment tree search for the best rectangle\n    SegTree seg(Y);\n    for (int L = 0; L < X; ++L) {\n        seg.reset();\n        for (int R = L; R < X; ++R) {\n            for (auto& [yi, w] : points_by_x[R]) {\n                seg.update(yi, w);\n            }\n            if (R == L) continue;   // need positive width\n            Node res = seg.query();\n            if (res.max_sub > best_sum && res.max_sub_end - res.max_sub_start >= 1) {\n                best_sum = res.max_sub;\n                best_L = L;\n                best_R = R;\n                best_B = res.max_sub_start;\n                best_T = res.max_sub_end;\n            }\n        }\n    }\n\n    // local optimization by moving boundaries\n    int cur_sum = best_sum;\n    int L = best_L, R = best_R, B = best_B, T = best_T;\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        int best_improve = 0;\n        char best_type = 0;\n        int best_new_idx = -1;\n\n        // try moving left edge\n        for (int newL = 0; newL < X; ++newL) {\n            if (newL >= R) continue;\n            int new_sum = rect_sum(newL, R, B, T);\n            if (new_sum > cur_sum) {\n                int improve = new_sum - cur_sum;\n                if (improve > best_improve) {\n                    best_improve = improve;\n                    best_type = 'L';\n                    best_new_idx = newL;\n                }\n            }\n        }\n\n        // try moving right edge\n        for (int newR = 0; newR < X; ++newR) {\n            if (newR <= L) continue;\n            int new_sum = rect_sum(L, newR, B, T);\n            if (new_sum > cur_sum) {\n                int improve = new_sum - cur_sum;\n                if (improve > best_improve) {\n                    best_improve = improve;\n                    best_type = 'R';\n                    best_new_idx = newR;\n                }\n            }\n        }\n\n        // try moving bottom edge\n        for (int newB = 0; newB < Y; ++newB) {\n            if (newB >= T) continue;\n            int new_sum = rect_sum(L, R, newB, T);\n            if (new_sum > cur_sum) {\n                int improve = new_sum - cur_sum;\n                if (improve > best_improve) {\n                    best_improve = improve;\n                    best_type = 'B';\n                    best_new_idx = newB;\n                }\n            }\n        }\n\n        // try moving top edge\n        for (int newT = 0; newT < Y; ++newT) {\n            if (newT <= B) continue;\n            int new_sum = rect_sum(L, R, B, newT);\n            if (new_sum > cur_sum) {\n                int improve = new_sum - cur_sum;\n                if (improve > best_improve) {\n                    best_improve = improve;\n                    best_type = 'T';\n                    best_new_idx = newT;\n                }\n            }\n        }\n\n        if (best_improve > 0) {\n            improved = true;\n            if (best_type == 'L') L = best_new_idx;\n            else if (best_type == 'R') R = best_new_idx;\n            else if (best_type == 'B') B = best_new_idx;\n            else if (best_type == 'T') T = best_new_idx;\n            cur_sum = rect_sum(L, R, B, T);\n        }\n    }\n\n    // output the rectangle as a 4\u2011vertex polygon\n    cout << 4 << '\\n';\n    cout << xs[L] << ' ' << ys[B] << '\\n';\n    cout << xs[R] << ' ' << ys[B] << '\\n';\n    cout << xs[R] << ' ' << ys[T] << '\\n';\n    cout << xs[L] << ' ' << ys[T] << '\\n';\n\n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <tuple>\n\nusing namespace std;\n\nconst double p_place = 0.9; // probability to attempt placing a rectangle\n\nstruct Rectangle {\n    int x, y, w, h;\n    int right() const { return x + w; }\n    int bottom() const { return y + h; }\n};\n\n// Compute y0 for U placement given left edge x0 and width\nint compute_y0(int x0, int width, const vector<int>& placed_indices, const Rectangle rect_of_index[]) {\n    int y0 = 0;\n    for (int idx : placed_indices) {\n        const Rectangle& R = rect_of_index[idx];\n        if (x0 < R.right() && x0 + width > R.x) {\n            y0 = max(y0, R.bottom());\n        }\n    }\n    return y0;\n}\n\n// Compute x0 for L placement given top edge y0 and height\nint compute_x0(int y0, int height, const vector<int>& placed_indices, const Rectangle rect_of_index[]) {\n    int x0 = 0;\n    for (int idx : placed_indices) {\n        const Rectangle& R = rect_of_index[idx];\n        if (y0 < R.bottom() && y0 + height > R.y) {\n            x0 = max(x0, R.right());\n        }\n    }\n    return x0;\n}\n\nvoid solve_turn(int turn, const vector<int>& w, const vector<int>& h, int N, mt19937& rng) {\n    vector<int> placed_indices;          // indices of placed rectangles\n    Rectangle rect_of_index[N];          // stores rectangle data when placed\n    bool is_placed[N] = {false};\n    int W = 0, H = 0;                    // current bounding box\n\n    vector<tuple<int, int, char, int>> ops; // (p, r, d, b)\n\n    uniform_real_distribution<double> dist_real(0.0, 1.0);\n    uniform_int_distribution<int> dist_binary(0, 1);\n\n    for (int i = 0; i < N; ++i) {\n        // Decide whether to attempt placement\n        if (dist_real(rng) >= p_place) continue;\n\n        // Choose random rotation and direction\n        int r = dist_binary(rng);\n        char d = (dist_binary(rng) == 0) ? 'U' : 'L';\n        int width = (r == 0) ? w[i] : h[i];\n        int height = (r == 0) ? h[i] : w[i];\n\n        // Find best reference b for the chosen d, r\n        int best_b = -1;\n        int best_newW = W, best_newH = H;\n        int best_score = -1;\n\n        // List of possible b: -1 and all placed indices\n        vector<int> b_candidates = {-1};\n        for (int idx : placed_indices) b_candidates.push_back(idx);\n\n        for (int b : b_candidates) {\n            int x0, y0;\n            if (d == 'U') {\n                x0 = (b == -1) ? 0 : rect_of_index[b].right();\n                y0 = compute_y0(x0, width, placed_indices, rect_of_index);\n            } else { // 'L'\n                y0 = (b == -1) ? 0 : rect_of_index[b].bottom();\n                x0 = compute_x0(y0, height, placed_indices, rect_of_index);\n            }\n            int newW = max(W, x0 + width);\n            int newH = max(H, y0 + height);\n            int score = newW + newH;\n            if (best_b == -1 || score < best_score) {\n                best_b = b;\n                best_score = score;\n                best_newW = newW;\n                best_newH = newH;\n            }\n        }\n\n        // Check if placing is beneficial (using measured dimensions)\n        if (best_score <= W + H + w[i] + h[i]) {\n            // Perform placement\n            int x0, y0;\n            if (d == 'U') {\n                x0 = (best_b == -1) ? 0 : rect_of_index[best_b].right();\n                y0 = compute_y0(x0, width, placed_indices, rect_of_index);\n            } else {\n                y0 = (best_b == -1) ? 0 : rect_of_index[best_b].bottom();\n                x0 = compute_x0(y0, height, placed_indices, rect_of_index);\n            }\n            // Update state\n            rect_of_index[i] = {x0, y0, width, height};\n            is_placed[i] = true;\n            placed_indices.push_back(i);\n            W = best_newW;\n            H = best_newH;\n            ops.emplace_back(i, r, d, best_b);\n        }\n    }\n\n    // Output operations\n    cout << ops.size() << '\\n';\n    for (auto [p, r, d, b] : ops) {\n        cout << p << ' ' << r << ' ' << d << ' ' << b << '\\n';\n    }\n    cout.flush();\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T, sigma;\n    cin >> N >> T >> sigma;\n    vector<int> w(N), h(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> w[i] >> h[i];\n    }\n\n    // Random number generator\n    random_device rd;\n    mt19937 rng(rd());\n\n    for (int t = 0; t < T; ++t) {\n        solve_turn(t, w, h, N, rng);\n        // Read measured box dimensions (not used in this simple strategy)\n        int Wp, Hp;\n        cin >> Wp >> Hp;\n    }\n\n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <random>\n#include <cmath>\n#include <numeric>\n#include <chrono>\nusing namespace std;\n\nint N, H;\nvector<vector<int>> adj;\nvector<int> A;\n\n// Check if changing vertex v to newd is feasible (without modifying state)\nbool can_change(int v, int newd, const vector<int>& depth) {\n    // check v itself if newd > 0\n    if (newd > 0) {\n        bool has = false;\n        for (int u : adj[v]) {\n            if (depth[u] == newd - 1) {\n                has = true;\n                break;\n            }\n        }\n        if (!has) return false;\n    }\n    // check all neighbours\n    for (int u : adj[v]) {\n        if (depth[u] == 0) continue; // root has no constraint\n        bool has = false;\n        for (int w : adj[u]) {\n            int d_w = (w == v) ? newd : depth[w];\n            if (d_w == depth[u] - 1) {\n                has = true;\n                break;\n            }\n        }\n        if (!has) return false;\n    }\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    cin >> N >> M >> H;\n    A.resize(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n    adj.resize(N);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n    // read coordinates (unused)\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // ---------- 1. Compute H-neighborhoods ----------\n    vector<vector<int>> cover(N);\n    for (int v = 0; v < N; ++v) {\n        vector<int> dist(N, -1);\n        queue<int> q;\n        dist[v] = 0;\n        q.push(v);\n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            if (dist[u] > H) continue;\n            cover[v].push_back(u);\n            if (dist[u] == H) continue;\n            for (int w : adj[u]) {\n                if (dist[w] == -1) {\n                    dist[w] = dist[u] + 1;\n                    q.push(w);\n                }\n            }\n        }\n    }\n\n    // ---------- 2. Greedy set cover to choose roots ----------\n    vector<bool> covered(N, false);\n    vector<int> roots;\n    int remaining = N;\n    while (remaining > 0) {\n        int best_v = -1, best_cnt = -1;\n        for (int v = 0; v < N; ++v) {\n            int cnt = 0;\n            for (int u : cover[v]) if (!covered[u]) cnt++;\n            if (cnt > best_cnt || (cnt == best_cnt && (best_v == -1 || A[v] < A[best_v]))) {\n                best_cnt = cnt;\n                best_v = v;\n            }\n        }\n        roots.push_back(best_v);\n        for (int u : cover[best_v]) if (!covered[u]) {\n            covered[u] = true;\n            --remaining;\n        }\n    }\n\n    // ---------- 3. Multi-source BFS to get initial depths ----------\n    vector<int> depth(N, -1);\n    queue<int> q;\n    for (int r : roots) {\n        depth[r] = 0;\n        q.push(r);\n    }\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (int v : adj[u]) {\n            if (depth[v] == -1) {\n                depth[v] = depth[u] + 1;\n                q.push(v);\n            }\n        }\n    }\n    long long cur_obj = 0;\n    for (int v = 0; v < N; ++v) cur_obj += depth[v] * A[v];\n\n    // ---------- 4. Simulated Annealing ----------\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> rand_v(0, N-1);\n    uniform_int_distribution<int> rand_d(0, H);\n    uniform_real_distribution<double> rand_float(0.0, 1.0);\n\n    const int ITER = 500000;\n    double temp = 1000.0;\n    const double cooling = 0.99999;\n\n    for (int iter = 0; iter < ITER; ++iter) {\n        int v = rand_v(rng);\n        int oldd = depth[v];\n        int newd = rand_d(rng);\n        if (newd == oldd) continue;\n        int delta = (newd - oldd) * A[v];\n\n        // feasibility check\n        if (!can_change(v, newd, depth)) continue;\n\n        // SA acceptance\n        if (delta >= 0 || rand_float(rng) < exp(delta / temp)) {\n            depth[v] = newd;\n            cur_obj += delta;\n        }\n        temp *= cooling;\n    }\n\n    // ---------- 5. Greedy increase passes ----------\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n        for (int v : order) {\n            if (depth[v] == H) continue;\n            int newd = depth[v] + 1;\n            if (can_change(v, newd, depth)) {\n                depth[v] = newd;\n                cur_obj += A[v];\n                improved = true;\n            }\n        }\n    }\n\n    // ---------- 6. Build parent pointers ----------\n    vector<int> parent(N, -1);\n    for (int v = 0; v < N; ++v) {\n        if (depth[v] == 0) continue;\n        for (int u : adj[v]) {\n            if (depth[u] == depth[v] - 1) {\n                parent[v] = u;\n                break;\n            }\n        }\n    }\n\n    // ---------- 7. Output ----------\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << parent[i];\n    }\n    cout << endl;\n\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 20;\nconst int INF = 1e9;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    int n;\n    cin >> n; // n is always 20\n    vector<string> board(n);\n    for (int i = 0; i < n; ++i) {\n        cin >> board[i];\n    }\n    \n    // Precompute free prefixes/suffixes for columns and rows\n    vector<int> up_free(n, -1), down_free(n, n);\n    for (int j = 0; j < n; ++j) {\n        // up_free[j]: largest i such that rows 0..i have no 'o'\n        for (int i = 0; i < n; ++i) {\n            if (board[i][j] == 'o') {\n                up_free[j] = i - 1;\n                break;\n            }\n        }\n        if (up_free[j] == -1) up_free[j] = n - 1; // no 'o'\n        // down_free[j]: smallest i such that rows i..n-1 have no 'o'\n        for (int i = n - 1; i >= 0; --i) {\n            if (board[i][j] == 'o') {\n                down_free[j] = i + 1;\n                break;\n            }\n        }\n        if (down_free[j] == n) down_free[j] = 0; // no 'o'\n    }\n    \n    vector<int> left_free(n, -1), right_free(n, n);\n    for (int i = 0; i < n; ++i) {\n        // left_free[i]: largest j such that columns 0..j have no 'o'\n        for (int j = 0; j < n; ++j) {\n            if (board[i][j] == 'o') {\n                left_free[i] = j - 1;\n                break;\n            }\n        }\n        if (left_free[i] == -1) left_free[i] = n - 1;\n        // right_free[i]: smallest j such that columns j..n-1 have no 'o'\n        for (int j = n - 1; j >= 0; --j) {\n            if (board[i][j] == 'o') {\n                right_free[i] = j + 1;\n                break;\n            }\n        }\n        if (right_free[i] == n) right_free[i] = 0;\n    }\n    \n    // Compute cost and decisions for column strategy\n    int total_cost_col = 0;\n    vector<int> col_option(n, -1); // 0: up only, 1: down only, 2: both\n    vector<int> col_k1(n, 0), col_k2(n, 0);\n    \n    for (int j = 0; j < n; ++j) {\n        vector<int> oni_rows;\n        for (int i = 0; i < n; ++i) {\n            if (board[i][j] == 'x') oni_rows.push_back(i);\n        }\n        if (oni_rows.empty()) continue;\n        \n        int min_r = oni_rows.front();\n        int max_r = oni_rows.back();\n        \n        int max_prefix_row = -1;\n        for (int i : oni_rows) if (i <= up_free[j]) max_prefix_row = max(max_prefix_row, i);\n        int min_suffix_row = n;\n        for (int i : oni_rows) if (i >= down_free[j]) min_suffix_row = min(min_suffix_row, i);\n        \n        bool all_in_prefix = (max_r <= up_free[j]);\n        bool all_in_suffix = (min_r >= down_free[j]);\n        \n        int cost_up_only = all_in_prefix ? 2 * (max_r + 1) : INF;\n        int cost_down_only = all_in_suffix ? 2 * (n - min_r) : INF;\n        int cost_up_part = (max_prefix_row >= 0) ? 2 * (max_prefix_row + 1) : 0;\n        int cost_down_part = (min_suffix_row < n) ? 2 * (n - min_suffix_row) : 0;\n        int cost_both = cost_up_part + cost_down_part;\n        \n        // Choose the minimal cost option\n        if (cost_up_only <= cost_down_only && cost_up_only <= cost_both) {\n            col_option[j] = 0;\n            col_k1[j] = max_r + 1;\n            total_cost_col += cost_up_only;\n        } else if (cost_down_only <= cost_up_only && cost_down_only <= cost_both) {\n            col_option[j] = 1;\n            col_k1[j] = n - min_r;\n            total_cost_col += cost_down_only;\n        } else {\n            col_option[j] = 2;\n            col_k1[j] = max_prefix_row + 1;\n            col_k2[j] = n - min_suffix_row;\n            total_cost_col += cost_both;\n        }\n    }\n    \n    // Compute cost and decisions for row strategy\n    int total_cost_row = 0;\n    vector<int> row_option(n, -1); // 0: left only, 1: right only, 2: both\n    vector<int> row_k1(n, 0), row_k2(n, 0);\n    \n    for (int i = 0; i < n; ++i) {\n        vector<int> oni_cols;\n        for (int j = 0; j < n; ++j) {\n            if (board[i][j] == 'x') oni_cols.push_back(j);\n        }\n        if (oni_cols.empty()) continue;\n        \n        int min_c = oni_cols.front();\n        int max_c = oni_cols.back();\n        \n        int max_left_col = -1;\n        for (int j : oni_cols) if (j <= left_free[i]) max_left_col = max(max_left_col, j);\n        int min_right_col = n;\n        for (int j : oni_cols) if (j >= right_free[i]) min_right_col = min(min_right_col, j);\n        \n        bool all_in_left = (max_c <= left_free[i]);\n        bool all_in_right = (min_c >= right_free[i]);\n        \n        int cost_left_only = all_in_left ? 2 * (max_c + 1) : INF;\n        int cost_right_only = all_in_right ? 2 * (n - min_c) : INF;\n        int cost_left_part = (max_left_col >= 0) ? 2 * (max_left_col + 1) : 0;\n        int cost_right_part = (min_right_col < n) ? 2 * (n - min_right_col) : 0;\n        int cost_both = cost_left_part + cost_right_part;\n        \n        if (cost_left_only <= cost_right_only && cost_left_only <= cost_both) {\n            row_option[i] = 0;\n            row_k1[i] = max_c + 1;\n            total_cost_row += cost_left_only;\n        } else if (cost_right_only <= cost_left_only && cost_right_only <= cost_both) {\n            row_option[i] = 1;\n            row_k1[i] = n - min_c;\n            total_cost_row += cost_right_only;\n        } else {\n            row_option[i] = 2;\n            row_k1[i] = max_left_col + 1;\n            row_k2[i] = n - min_right_col;\n            total_cost_row += cost_both;\n        }\n    }\n    \n    // Choose the cheaper strategy\n    if (total_cost_col <= total_cost_row) {\n        // Column strategy\n        for (int j = 0; j < n; ++j) {\n            if (col_option[j] == -1) continue;\n            if (col_option[j] == 0) { // up only\n                int k = col_k1[j];\n                for (int t = 0; t < k; ++t) cout << \"U \" << j << \"\\n\";\n                for (int t = 0; t < k; ++t) cout << \"D \" << j << \"\\n\";\n            } else if (col_option[j] == 1) { // down only\n                int k = col_k1[j];\n                for (int t = 0; t < k; ++t) cout << \"D \" << j << \"\\n\";\n                for (int t = 0; t < k; ++t) cout << \"U \" << j << \"\\n\";\n            } else { // both\n                int k_up = col_k1[j];\n                for (int t = 0; t < k_up; ++t) cout << \"U \" << j << \"\\n\";\n                for (int t = 0; t < k_up; ++t) cout << \"D \" << j << \"\\n\";\n                int k_down = col_k2[j];\n                for (int t = 0; t < k_down; ++t) cout << \"D \" << j << \"\\n\";\n                for (int t = 0; t < k_down; ++t) cout << \"U \" << j << \"\\n\";\n            }\n        }\n    } else {\n        // Row strategy\n        for (int i = 0; i < n; ++i) {\n            if (row_option[i] == -1) continue;\n            if (row_option[i] == 0) { // left only\n                int k = row_k1[i];\n                for (int t = 0; t < k; ++t) cout << \"L \" << i << \"\\n\";\n                for (int t = 0; t < k; ++t) cout << \"R \" << i << \"\\n\";\n            } else if (row_option[i] == 1) { // right only\n                int k = row_k1[i];\n                for (int t = 0; t < k; ++t) cout << \"R \" << i << \"\\n\";\n                for (int t = 0; t < k; ++t) cout << \"L \" << i << \"\\n\";\n            } else { // both\n                int k_left = row_k1[i];\n                for (int t = 0; t < k_left; ++t) cout << \"L \" << i << \"\\n\";\n                for (int t = 0; t < k_left; ++t) cout << \"R \" << i << \"\\n\";\n                int k_right = row_k2[i];\n                for (int t = 0; t < k_right; ++t) cout << \"R \" << i << \"\\n\";\n                for (int t = 0; t < k_right; ++t) cout << \"L \" << i << \"\\n\";\n            }\n        }\n    }\n    \n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, L;\n    cin >> N >> L;\n    vector<int> T(N);\n    for (int i = 0; i < N; ++i) cin >> T[i];\n\n    // Random generator\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    // Initialize a and b\n    vector<int> a(N), b(N);\n    for (int i = 0; i < N; ++i) {\n        a[i] = i;\n        b[i] = (i + 1) % N;\n    }\n\n    // Build transition table: nxt[i][0] = b_i, nxt[i][1] = a_i\n    array<array<int, 2>, 100> nxt;\n    for (int i = 0; i < N; ++i) {\n        nxt[i][0] = b[i];\n        nxt[i][1] = a[i];\n    }\n\n    // Simulation function\n    auto simulate = [&]() {\n        int cnt[100];\n        memset(cnt, 0, sizeof(cnt));\n        cnt[0] = 1;\n        int cur = 0;\n        int steps = L - 1;\n        while (steps--) {\n            int parity = cnt[cur] & 1;\n            int next_emp = nxt[cur][parity];\n            ++cnt[next_emp];\n            cur = next_emp;\n        }\n        int error = 0;\n        for (int i = 0; i < N; ++i) {\n            error += abs(cnt[i] - T[i]);\n        }\n        return error;\n    };\n\n    int cur_error = simulate();\n    int best_error = cur_error;\n    vector<int> best_a = a, best_b = b;\n\n    double temp = 1000.0;\n    const double cooling = 0.998;\n    auto start_time = chrono::steady_clock::now();\n    const double time_limit = 1.9; // seconds\n    uniform_real_distribution<double> dist(0.0, 1.0);\n\n    int iter = 0;\n    while (true) {\n        if ((iter & 63) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > time_limit) break;\n        }\n        ++iter;\n\n        // Choose random edge\n        int i = rng() % N;\n        int type = rng() % 2; // 0 -> a_i, 1 -> b_i\n        int old_val = (type == 0) ? a[i] : b[i];\n        int new_val = rng() % N;\n        if (new_val == old_val) continue;\n\n        // Apply change\n        if (type == 0) {\n            a[i] = new_val;\n            nxt[i][1] = new_val;\n        } else {\n            b[i] = new_val;\n            nxt[i][0] = new_val;\n        }\n\n        int new_error = simulate();\n        int delta = new_error - cur_error;\n\n        bool accept = false;\n        if (delta < 0) {\n            accept = true;\n        } else {\n            double prob = exp(-delta / temp);\n            if (dist(rng) < prob) accept = true;\n        }\n\n        if (accept) {\n            cur_error = new_error;\n            if (cur_error < best_error) {\n                best_error = cur_error;\n                best_a = a;\n                best_b = b;\n                if (best_error == 0) break; // optimal found\n            }\n        } else {\n            // Revert\n            if (type == 0) {\n                a[i] = old_val;\n                nxt[i][1] = old_val;\n            } else {\n                b[i] = old_val;\n                nxt[i][0] = old_val;\n            }\n        }\n\n        // Cool down\n        temp *= cooling;\n    }\n\n    // Output best assignment\n    for (int i = 0; i < N; ++i) {\n        cout << best_a[i] << \" \" << best_b[i] << \"\\n\";\n    }\n\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int N, M, Q, L, W;\n    cin >> N >> M >> Q >> L >> W;\n\n    vector<int> G(M);\n    for (int i = 0; i < M; ++i) cin >> G[i];\n\n    vector<int> lx(N), rx(N), ly(N), ry(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n    }\n\n    // sort cities by the sum of their coordinate intervals (proxy for the centre)\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int i, int j) {\n        int sx_i = lx[i] + rx[i], sy_i = ly[i] + ry[i];\n        int sx_j = lx[j] + rx[j], sy_j = ly[j] + ry[j];\n        if (sx_i != sx_j) return sx_i < sx_j;\n        return sy_i < sy_j;\n    });\n\n    // partition into groups according to the given sizes\n    vector<vector<int>> groups(M);\n    int pos = 0;\n    for (int k = 0; k < M; ++k) {\n        for (int i = 0; i < G[k]; ++i) {\n            groups[k].push_back(order[pos++]);\n        }\n    }\n\n    vector<vector<pair<int, int>>> edges(M);   // edges for each group\n\n    for (int k = 0; k < M; ++k) {\n        int g = groups[k].size();\n        if (g == 1) continue;\n\n        if (g <= L) {\n            // whole group fits in one query\n            cout << \"? \" << g;\n            for (int city : groups[k]) cout << \" \" << city;\n            cout << endl;\n            cout.flush();\n            for (int i = 0; i < g - 1; ++i) {\n                int a, b;\n                cin >> a >> b;\n                edges[k].emplace_back(a, b);\n            }\n        } else {\n            int step = L - 1;\n            int windows = (g - 1 + step - 1) / step;   // ceil((g-1)/step)\n            for (int w = 0; w < windows; ++w) {\n                int start = w * step;\n                int end = min(start + L, g);\n                int sz = end - start;\n                cout << \"? \" << sz;\n                for (int i = start; i < end; ++i) cout << \" \" << groups[k][i];\n                cout << endl;\n                cout.flush();\n                for (int i = 0; i < sz - 1; ++i) {\n                    int a, b;\n                    cin >> a >> b;\n                    edges[k].emplace_back(a, b);\n                }\n            }\n        }\n    }\n\n    // output answer\n    cout << \"!\" << endl;\n    for (int k = 0; k < M; ++k) {\n        // cities of the group\n        for (int i = 0; i < (int)groups[k].size(); ++i) {\n            if (i) cout << \" \";\n            cout << groups[k][i];\n        }\n        cout << endl;\n        // roads (edges)\n        for (auto [a, b] : edges[k]) {\n            cout << a << \" \" << b << endl;\n        }\n    }\n\n    return 0;\n}\n","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n    vector<pair<int, int>> pts(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> pts[i].first >> pts[i].second;\n    }\n\n    vector<string> actions;\n\n    for (int i = 0; i < M - 1; ++i) {\n        int r1 = pts[i].first, c1 = pts[i].second;\n        int r2 = pts[i + 1].first, c2 = pts[i + 1].second;\n\n        // ----- compute costs of the five possible plans -----\n        int direct = abs(r1 - r2) + abs(c1 - c2);\n\n        int costU = (r1 > 0 ? 1 : 0) + abs(c1 - c2) + r2;\n        int costD = (r1 < N - 1 ? 1 : 0) + abs(c1 - c2) + (N - 1 - r2);\n        int costL = (c1 > 0 ? 1 : 0) + abs(r1 - r2) + c2;\n        int costR = (c1 < N - 1 ? 1 : 0) + abs(r1 - r2) + (N - 1 - c2);\n\n        // ----- choose the cheapest plan -----\n        int best = direct;\n        int option = 0;   // 0:direct, 1:up, 2:down, 3:left, 4:right\n        if (costU < best) { best = costU; option = 1; }\n        if (costD < best) { best = costD; option = 2; }\n        if (costL < best) { best = costL; option = 3; }\n        if (costR < best) { best = costR; option = 4; }\n\n        // ----- generate the actions for the chosen plan -----\n        switch (option) {\n            case 0: // direct moves\n                // vertical\n                if (r2 > r1) {\n                    for (int k = 0; k < r2 - r1; ++k) actions.push_back(\"M D\");\n                } else if (r2 < r1) {\n                    for (int k = 0; k < r1 - r2; ++k) actions.push_back(\"M U\");\n                }\n                // horizontal\n                if (c2 > c1) {\n                    for (int k = 0; k < c2 - c1; ++k) actions.push_back(\"M R\");\n                } else if (c2 < c1) {\n                    for (int k = 0; k < c1 - c2; ++k) actions.push_back(\"M L\");\n                }\n                break;\n\n            case 1: // Up\n                if (r1 > 0) actions.push_back(\"S U\");\n                // move horizontally on the top row\n                if (c2 > c1) {\n                    for (int k = 0; k < c2 - c1; ++k) actions.push_back(\"M R\");\n                } else if (c2 < c1) {\n                    for (int k = 0; k < c1 - c2; ++k) actions.push_back(\"M L\");\n                }\n                // move down to the target row\n                if (r2 > 0) {\n                    for (int k = 0; k < r2; ++k) actions.push_back(\"M D\");\n                }\n                break;\n\n            case 2: // Down\n                if (r1 < N - 1) actions.push_back(\"S D\");\n                // move horizontally on the bottom row\n                if (c2 > c1) {\n                    for (int k = 0; k < c2 - c1; ++k) actions.push_back(\"M R\");\n                } else if (c2 < c1) {\n                    for (int k = 0; k < c1 - c2; ++k) actions.push_back(\"M L\");\n                }\n                // move up to the target row\n                if (r2 < N - 1) {\n                    int steps = N - 1 - r2;\n                    for (int k = 0; k < steps; ++k) actions.push_back(\"M U\");\n                }\n                break;\n\n            case 3: // Left\n                if (c1 > 0) actions.push_back(\"S L\");\n                // move vertically on the left column\n                if (r2 > r1) {\n                    for (int k = 0; k < r2 - r1; ++k) actions.push_back(\"M D\");\n                } else if (r2 < r1) {\n                    for (int k = 0; k < r1 - r2; ++k) actions.push_back(\"M U\");\n                }\n                // move right to the target column\n                if (c2 > 0) {\n                    for (int k = 0; k < c2; ++k) actions.push_back(\"M R\");\n                }\n                break;\n\n            case 4: // Right\n                if (c1 < N - 1) actions.push_back(\"S R\");\n                // move vertically on the right column\n                if (r2 > r1) {\n                    for (int k = 0; k < r2 - r1; ++k) actions.push_back(\"M D\");\n                } else if (r2 < r1) {\n                    for (int k = 0; k < r1 - r2; ++k) actions.push_back(\"M U\");\n                }\n                // move left to the target column\n                if (c2 < N - 1) {\n                    int steps = N - 1 - c2;\n                    for (int k = 0; k < steps; ++k) actions.push_back(\"M L\");\n                }\n                break;\n        }\n    }\n\n    // ----- output all actions -----\n    for (const string& act : actions) {\n        cout << act << '\\n';\n    }\n\n    return 0;\n}\n"},"2":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\n\nstruct Company {\n    int x, y, r;\n};\n\nstruct Node {\n    int x1, y1, x2, y2;\n    vector<int> ids;          // indices of companies in this node\n    int cut_type;             // 0: leaf, 1: vertical, 2: horizontal\n    int cut_pos;              // coordinate of the cut (if not leaf)\n    Node *left, *right;\n    Node() : left(nullptr), right(nullptr) {}\n};\n\nint n;\nvector<Company> comps;\nvector<int> a, b, c, d;      // answer rectangles\n\n// recursively build the partition tree\nNode* build(int x1, int y1, int x2, int y2, vector<int>& ids) {\n    Node* node = new Node();\n    node->x1 = x1; node->y1 = y1; node->x2 = x2; node->y2 = y2;\n    node->ids = ids;\n\n    // leaf: single company\n    if (ids.size() == 1) {\n        node->cut_type = 0;\n        return node;\n    }\n\n    // total desired area in this node\n    ll total_r = 0;\n    for (int i : ids) total_r += comps[i].r;\n\n    // find extreme coordinates of points in this node\n    int min_x = 10000, max_x = 0, min_y = 10000, max_y = 0;\n    for (int i : ids) {\n        min_x = min(min_x, comps[i].x);\n        max_x = max(max_x, comps[i].x);\n        min_y = min(min_y, comps[i].y);\n        max_y = max(max_y, comps[i].y);\n    }\n\n    ll best_cost = LLONG_MAX;\n    int best_type = -1;   // 1 vertical, 2 horizontal\n    int best_pos = -1;\n\n    // ----- vertical cuts -----\n    if (max_x > min_x) {   // at least two different x coordinates\n        for (int X = x1 + 1; X < x2; ++X) {\n            if (X <= min_x || X > max_x) continue;   // ensure both sides non\u2011empty\n            ll left_sum = 0;\n            for (int i : ids)\n                if (comps[i].x < X) left_sum += comps[i].r;\n            ll left_area  = (ll)(X - x1) * (y2 - y1);\n            ll right_sum  = total_r - left_sum;\n            ll right_area = (ll)(x2 - X) * (y2 - y1);\n            ll cost = (left_area - left_sum) * (left_area - left_sum)\n                    + (right_area - right_sum) * (right_area - right_sum);\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_type = 1;\n                best_pos  = X;\n            }\n        }\n    }\n\n    // ----- horizontal cuts -----\n    if (max_y > min_y) {\n        for (int Y = y1 + 1; Y < y2; ++Y) {\n            if (Y <= min_y || Y > max_y) continue;\n            ll bottom_sum = 0;\n            for (int i : ids)\n                if (comps[i].y < Y) bottom_sum += comps[i].r;\n            ll bottom_area = (ll)(x2 - x1) * (Y - y1);\n            ll top_sum     = total_r - bottom_sum;\n            ll top_area    = (ll)(x2 - x1) * (y2 - Y);\n            ll cost = (bottom_area - bottom_sum) * (bottom_area - bottom_sum)\n                    + (top_area - top_sum) * (top_area - top_sum);\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_type = 2;\n                best_pos  = Y;\n            }\n        }\n    }\n\n    // At least one orientation must be valid because points are distinct.\n    assert(best_type != -1);\n\n    // split the point set according to the chosen cut\n    if (best_type == 1) {   // vertical\n        vector<int> left_ids, right_ids;\n        for (int i : ids) {\n            if (comps[i].x < best_pos) left_ids.push_back(i);\n            else right_ids.push_back(i);\n        }\n        node->cut_type = 1;\n        node->cut_pos  = best_pos;\n        node->left  = build(x1, y1, best_pos, y2, left_ids);\n        node->right = build(best_pos, y1, x2, y2, right_ids);\n    } else {                // horizontal\n        vector<int> bottom_ids, top_ids;\n        for (int i : ids) {\n            if (comps[i].y < best_pos) bottom_ids.push_back(i);\n            else top_ids.push_back(i);\n        }\n        node->cut_type = 2;\n        node->cut_pos  = best_pos;\n        node->left  = build(x1, y1, x2, best_pos, bottom_ids);\n        node->right = build(x1, best_pos, x2, y2, top_ids);\n    }\n\n    return node;\n}\n\n// collect leaf rectangles into the answer arrays\nvoid collect(Node* node) {\n    if (node->cut_type == 0) {\n        int i = node->ids[0];\n        a[i] = node->x1;\n        b[i] = node->y1;\n        c[i] = node->x2;\n        d[i] = node->y2;\n        return;\n    }\n    collect(node->left);\n    collect(node->right);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n;\n    comps.resize(n);\n    for (int i = 0; i < n; ++i)\n        cin >> comps[i].x >> comps[i].y >> comps[i].r;\n\n    a.resize(n); b.resize(n); c.resize(n); d.resize(n);\n\n    vector<int> ids(n);\n    iota(ids.begin(), ids.end(), 0);\n    Node* root = build(0, 0, 10000, 10000, ids);\n\n    collect(root);\n\n    for (int i = 0; i < n; ++i)\n        cout << a[i] << ' ' << b[i] << ' ' << c[i] << ' ' << d[i] << '\\n';\n\n    return 0;\n}","ahc002":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <cassert>\n#include <tuple>\n#include <set>\n\nusing namespace std;\n\nconst int N = 50;\nconst int dr[4] = {-1, 1, 0, 0};\nconst int dc[4] = {0, 0, -1, 1};\nconst char dir_char[4] = {'U', 'D', 'L', 'R'};\n\nstruct Neighbor {\n    int r, c;\n    char dir;\n};\n\n// Get valid neighbors from (r,c) given visited tiles.\nvector<Neighbor> get_neighbors(int r, int c, const vector<char>& visited,\n                               const vector<vector<int>>& tile_id) {\n    vector<Neighbor> res;\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) {\n            int tile = tile_id[nr][nc];\n            if (!visited[tile]) {\n                res.push_back({nr, nc, dir_char[d]});\n            }\n        }\n    }\n    return res;\n}\n\n// Count unvisited neighbors for a tile (considering all squares in the tile)\nint count_unvisited_neighbors(const pair<int,int>& square,\n                              const vector<char>& visited,\n                              const vector<vector<int>>& tile_id) {\n    int count = 0;\n    set<int> neighboring_tiles;\n    for (int d = 0; d < 4; ++d) {\n        int nr = square.first + dr[d], nc = square.second + dc[d];\n        if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n            int tile = tile_id[nr][nc];\n            if (!visited[tile] && neighboring_tiles.find(tile) == neighboring_tiles.end()) {\n                count++;\n                neighboring_tiles.insert(tile);\n            }\n        }\n    }\n    return count;\n}\n\n// Greedily extend the path from the last square with lookahead.\nvoid extend_greedy(vector<pair<int,int>>& path, vector<int>& tiles,\n                   vector<char>& visited, int& score,\n                   const vector<vector<int>>& p,\n                   const vector<vector<int>>& tile_id,\n                   mt19937& rng) {\n    while (true) {\n        int r = path.back().first, c = path.back().second;\n        auto candidates = get_neighbors(r, c, visited, tile_id);\n        if (candidates.empty()) break;\n        \n        // Score each candidate by p and number of unvisited neighbors\n        vector<pair<double, int>> candidate_scores;\n        for (size_t i = 0; i < candidates.size(); ++i) {\n            const auto& cand = candidates[i];\n            double score_val = p[cand.r][cand.c];\n            // Add bonus for having more unvisited neighbors (helps avoid dead ends)\n            int neighbor_count = count_unvisited_neighbors({cand.r, cand.c}, visited, tile_id);\n            score_val += 0.1 * neighbor_count;\n            candidate_scores.emplace_back(score_val, i);\n        }\n        \n        // Choose with probability proportional to score (softmax-like)\n        vector<double> weights;\n        for (const auto& cs : candidate_scores) {\n            weights.push_back(exp(cs.first / 10.0));\n        }\n        discrete_distribution<int> dist(weights.begin(), weights.end());\n        int idx = dist(rng);\n        \n        const auto& cand = candidates[idx];\n        path.push_back({cand.r, cand.c});\n        tiles.push_back(tile_id[cand.r][cand.c]);\n        visited[tile_id[cand.r][cand.c]] = 1;\n        score += p[cand.r][cand.c];\n    }\n}\n\n// Try to reverse a segment of the path\nbool try_reverse_segment(vector<pair<int,int>>& path, vector<int>& tiles,\n                         vector<char>& visited, int& score,\n                         const vector<vector<int>>& p,\n                         const vector<vector<int>>& tile_id,\n                         mt19937& rng) {\n    if (path.size() < 4) return false;\n    \n    uniform_int_distribution<int> len_dist(2, min(20, (int)path.size() - 2));\n    int seg_len = len_dist(rng);\n    uniform_int_distribution<int> start_dist(1, path.size() - seg_len - 1);\n    int start_idx = start_dist(rng);\n    \n    // Check if reversing this segment maintains validity\n    vector<pair<int,int>> new_path = path;\n    vector<int> new_tiles = tiles;\n    \n    // Temporarily mark tiles as unvisited for the segment\n    vector<char> temp_visited = visited;\n    for (int i = start_idx; i < start_idx + seg_len; ++i) {\n        temp_visited[tiles[i]] = 0;\n    }\n    \n    // Try to reverse\n    for (int i = 0; i < seg_len; ++i) {\n        int src_idx = start_idx + seg_len - 1 - i;\n        int dst_idx = start_idx + i;\n        new_path[dst_idx] = path[src_idx];\n        new_tiles[dst_idx] = tiles[src_idx];\n        \n        // Check if this tile is already used in the rest of the path\n        if (temp_visited[tiles[src_idx]]) return false;\n        temp_visited[tiles[src_idx]] = 1;\n    }\n    \n    // Check connectivity between segments\n    auto check_connection = [&](int from_idx, int to_idx) {\n        const auto& from = new_path[from_idx];\n        const auto& to = new_path[to_idx];\n        int dr = abs(from.first - to.first);\n        int dc = abs(from.second - to.second);\n        return (dr + dc == 1);\n    };\n    \n    if (!check_connection(start_idx - 1, start_idx)) return false;\n    if (!check_connection(start_idx + seg_len - 1, start_idx + seg_len)) return false;\n    \n    // If valid, apply the reversal\n    path = new_path;\n    tiles = new_tiles;\n    visited = temp_visited;\n    \n    // Recalculate score (could optimize but it's fine)\n    score = 0;\n    for (const auto& sq : path) {\n        score += p[sq.first][sq.second];\n    }\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Read input.\n    int si, sj;\n    cin >> si >> sj;\n    vector<vector<int>> tile_id(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> tile_id[i][j];\n    vector<vector<int>> 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    // Determine number of tiles.\n    int M = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            M = max(M, tile_id[i][j] + 1);\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    // Generate multiple initial paths and keep the best\n    vector<pair<int,int>> best_initial_path;\n    int best_initial_score = -1;\n    \n    for (int trial = 0; trial < 5; ++trial) {\n        vector<pair<int,int>> cur_path;\n        vector<int> cur_tiles;\n        vector<char> cur_visited(M, 0);\n        int cur_score = 0;\n\n        cur_path.emplace_back(si, sj);\n        cur_tiles.push_back(tile_id[si][sj]);\n        cur_visited[tile_id[si][sj]] = 1;\n        cur_score += p[si][sj];\n        \n        if (trial == 0) {\n            extend_greedy(cur_path, cur_tiles, cur_visited, cur_score, p, tile_id, rng);\n        } else {\n            // For other trials, use a more exploratory initial walk\n            uniform_int_distribution<int> walk_dist(50, 200);\n            int walk_length = walk_dist(rng);\n            for (int step = 0; step < walk_length; ++step) {\n                auto candidates = get_neighbors(cur_path.back().first, cur_path.back().second,\n                                               cur_visited, tile_id);\n                if (candidates.empty()) break;\n                \n                uniform_int_distribution<int> cand_dist(0, candidates.size() - 1);\n                int idx = cand_dist(rng);\n                const auto& cand = candidates[idx];\n                cur_path.push_back({cand.r, cand.c});\n                cur_tiles.push_back(tile_id[cand.r][cand.c]);\n                cur_visited[tile_id[cand.r][cand.c]] = 1;\n                cur_score += p[cand.r][cand.c];\n            }\n            // Then extend greedily\n            extend_greedy(cur_path, cur_tiles, cur_visited, cur_score, p, tile_id, rng);\n        }\n        \n        if (cur_score > best_initial_score) {\n            best_initial_score = cur_score;\n            best_initial_path = cur_path;\n        }\n    }\n\n    vector<pair<int,int>> cur_path = best_initial_path;\n    vector<int> cur_tiles;\n    vector<char> cur_visited(M, 0);\n    int cur_score = 0;\n    \n    // Rebuild tiles and visited from path\n    for (const auto& sq : cur_path) {\n        cur_tiles.push_back(tile_id[sq.first][sq.second]);\n        cur_visited[tile_id[sq.first][sq.second]] = 1;\n        cur_score += p[sq.first][sq.second];\n    }\n\n    vector<pair<int,int>> best_path = cur_path;\n    int best_score = cur_score;\n\n    // Simulated annealing parameters\n    const int ITER = 150000;\n    const double T_start = 200.0;\n    const double T_min = 1e-3;\n    double T = T_start;\n    double cooling_rate = pow(T_min / T_start, 1.0 / ITER);\n    \n    uniform_real_distribution<double> real_dist(0.0, 1.0);\n    auto start_time = chrono::steady_clock::now();\n    const chrono::milliseconds time_limit(1900); // 1.9 seconds\n    \n    int restart_count = 0;\n    const int RESTART_THRESHOLD = 50000; // restart if no improvement for this many iterations\n    int iterations_without_improvement = 0;\n\n    for (int iter = 0; iter < ITER; ++iter) {\n        // Time check\n        if (iter % 1000 == 0) {\n            auto now = chrono::steady_clock::now();\n            if (chrono::duration_cast<chrono::milliseconds>(now - start_time) > time_limit)\n                break;\n        }\n        \n        // Temperature restart if stuck\n        if (iterations_without_improvement > RESTART_THRESHOLD && restart_count < 3) {\n            // Revert to best solution found so far and reheat\n            cur_path = best_path;\n            cur_tiles.clear();\n            cur_visited.assign(M, 0);\n            cur_score = 0;\n            for (const auto& sq : cur_path) {\n                cur_tiles.push_back(tile_id[sq.first][sq.second]);\n                cur_visited[tile_id[sq.first][sq.second]] = 1;\n                cur_score += p[sq.first][sq.second];\n            }\n            T = T_start * pow(0.5, restart_count);\n            restart_count++;\n            iterations_without_improvement = 0;\n            continue;\n        }\n\n        // Copy current state\n        vector<pair<int,int>> new_path = cur_path;\n        vector<int> new_tiles = cur_tiles;\n        vector<char> new_visited = cur_visited;\n        int new_score = cur_score;\n\n        double op = real_dist(rng);\n        if (op < 0.3) {\n            // Extend: add one move at the end\n            if (!new_path.empty()) {\n                int r = new_path.back().first, c = new_path.back().second;\n                auto candidates = get_neighbors(r, c, new_visited, tile_id);\n                if (!candidates.empty()) {\n                    uniform_int_distribution<int> dist(0, candidates.size() - 1);\n                    int idx = dist(rng);\n                    auto& cand = candidates[idx];\n                    new_path.push_back({cand.r, cand.c});\n                    new_tiles.push_back(tile_id[cand.r][cand.c]);\n                    new_visited[tile_id[cand.r][cand.c]] = 1;\n                    new_score += p[cand.r][cand.c];\n                }\n            }\n        } else if (op < 0.5) {\n            // Shrink: remove last move\n            if (new_path.size() > 1) {\n                auto last = new_path.back();\n                int tile = new_tiles.back();\n                new_path.pop_back();\n                new_tiles.pop_back();\n                new_visited[tile] = 0;\n                new_score -= p[last.first][last.second];\n            }\n        } else if (op < 0.8) {\n            // Modify: truncate at random index, change next move, then extend\n            if (new_path.size() <= 1) {\n                // Fallback to extend\n                if (!new_path.empty()) {\n                    int r = new_path.back().first, c = new_path.back().second;\n                    auto candidates = get_neighbors(r, c, new_visited, tile_id);\n                    if (!candidates.empty()) {\n                        uniform_int_distribution<int> dist(0, candidates.size() - 1);\n                        int idx = dist(rng);\n                        auto& cand = candidates[idx];\n                        new_path.push_back({cand.r, cand.c});\n                        new_tiles.push_back(tile_id[cand.r][cand.c]);\n                        new_visited[tile_id[cand.r][cand.c]] = 1;\n                        new_score += p[cand.r][cand.c];\n                    }\n                }\n            } else {\n                int L = new_path.size();\n                uniform_int_distribution<int> idx_dist(1, L - 1);\n                int k = idx_dist(rng);\n                \n                // Remove squares from index k onward\n                for (int i = k; i < L; ++i) {\n                    int tile = new_tiles[i];\n                    new_visited[tile] = 0;\n                    new_score -= p[new_path[i].first][new_path[i].second];\n                }\n                new_path.resize(k);\n                new_tiles.resize(k);\n                \n                // Choose a new move from the square at index k-1\n                int r_prev = new_path.back().first, c_prev = new_path.back().second;\n                auto candidates = get_neighbors(r_prev, c_prev, new_visited, tile_id);\n                if (!candidates.empty()) {\n                    uniform_int_distribution<int> dist(0, candidates.size() - 1);\n                    int idx = dist(rng);\n                    auto& cand = candidates[idx];\n                    new_path.push_back({cand.r, cand.c});\n                    new_tiles.push_back(tile_id[cand.r][cand.c]);\n                    new_visited[tile_id[cand.r][cand.c]] = 1;\n                    new_score += p[cand.r][cand.c];\n                    \n                    // Extend greedily with lookahead\n                    extend_greedy(new_path, new_tiles, new_visited, new_score, p, tile_id, rng);\n                }\n            }\n        } else {\n            // Try to reverse a segment\n            if (try_reverse_segment(new_path, new_tiles, new_visited, new_score, p, tile_id, rng)) {\n                // Success - path was improved by reversal\n            } else {\n                // If reversal fails, do a simple extend\n                if (!new_path.empty()) {\n                    int r = new_path.back().first, c = new_path.back().second;\n                    auto candidates = get_neighbors(r, c, new_visited, tile_id);\n                    if (!candidates.empty()) {\n                        uniform_int_distribution<int> dist(0, candidates.size() - 1);\n                        int idx = dist(rng);\n                        auto& cand = candidates[idx];\n                        new_path.push_back({cand.r, cand.c});\n                        new_tiles.push_back(tile_id[cand.r][cand.c]);\n                        new_visited[tile_id[cand.r][cand.c]] = 1;\n                        new_score += p[cand.r][cand.c];\n                    }\n                }\n            }\n        }\n\n        // Metropolis criterion\n        int delta = new_score - cur_score;\n        bool accept = false;\n        if (delta > 0) {\n            accept = true;\n        } else {\n            double prob = exp(delta / T);\n            if (real_dist(rng) < prob) accept = true;\n        }\n\n        if (accept) {\n            cur_path = std::move(new_path);\n            cur_tiles = std::move(new_tiles);\n            cur_visited = std::move(new_visited);\n            cur_score = new_score;\n            if (cur_score > best_score) {\n                best_score = cur_score;\n                best_path = cur_path;\n                iterations_without_improvement = 0;\n            } else {\n                iterations_without_improvement++;\n            }\n        } else {\n            iterations_without_improvement++;\n        }\n\n        // Cooling\n        T *= cooling_rate;\n    }\n\n    // Convert best_path to move string\n    string moves;\n    for (size_t i = 1; i < best_path.size(); ++i) {\n        int dr = best_path[i].first - best_path[i-1].first;\n        int dc = best_path[i].second - best_path[i-1].second;\n        if (dr == -1 && dc == 0) moves += 'U';\n        else if (dr == 1 && dc == 0) moves += 'D';\n        else if (dr == 0 && dc == -1) moves += 'L';\n        else if (dr == 0 && dc == 1) moves += 'R';\n        else assert(false);\n    }\n\n    cout << moves << endl;\n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <string>\n\nusing namespace std;\n\nconst int N = 30;\n\ndouble h_est[N][N-1]; // horizontal edges: between (i,j) and (i,j+1)\ndouble v_est[N-1][N]; // vertical edges: between (i,j) and (i+1,j)\n\nstruct Node {\n    int i, j;\n    bool operator==(const Node& other) const { return i == other.i && j == other.j; }\n    bool operator!=(const Node& other) const { return !(*this == other); }\n};\n\nusing PQElement = pair<double, Node>;\n\nstruct Compare {\n    bool operator()(const PQElement& a, const PQElement& b) const {\n        return a.first > b.first;\n    }\n};\n\ndouble getEdgeEstimate(int i, int j, int ni, int nj) {\n    if (i == ni) {\n        if (nj == j+1) return h_est[i][j];\n        else if (nj == j-1) return h_est[i][j-1];\n    } else if (j == nj) {\n        if (ni == i+1) return v_est[i][j];\n        else if (ni == i-1) return v_est[i-1][j];\n    }\n    return 0.0; // should not happen\n}\n\nvoid updateEdge(int i, int j, int ni, int nj, double factor) {\n    if (i == ni) {\n        if (nj == j+1) {\n            h_est[i][j] *= factor;\n            if (h_est[i][j] < 500.0) h_est[i][j] = 500.0;\n            if (h_est[i][j] > 15000.0) h_est[i][j] = 15000.0;\n        } else if (nj == j-1) {\n            h_est[i][j-1] *= factor;\n            if (h_est[i][j-1] < 500.0) h_est[i][j-1] = 500.0;\n            if (h_est[i][j-1] > 15000.0) h_est[i][j-1] = 15000.0;\n        }\n    } else if (j == nj) {\n        if (ni == i+1) {\n            v_est[i][j] *= factor;\n            if (v_est[i][j] < 500.0) v_est[i][j] = 500.0;\n            if (v_est[i][j] > 15000.0) v_est[i][j] = 15000.0;\n        } else if (ni == i-1) {\n            v_est[i-1][j] *= factor;\n            if (v_est[i-1][j] < 500.0) v_est[i-1][j] = 500.0;\n            if (v_est[i-1][j] > 15000.0) v_est[i-1][j] = 15000.0;\n        }\n    }\n}\n\nvoid updateEstimates(const vector<Node>& path, int obs, int k) {\n    int path_length = path.size() - 1;\n    if (path_length == 0) return;\n    double pred = 0.0;\n    for (int idx = 0; idx < path_length; idx++) {\n        auto& from = path[idx];\n        auto& to = path[idx+1];\n        pred += getEdgeEstimate(from.i, from.j, to.i, to.j);\n    }\n    double factor = obs / pred;\n    double alpha = 0.1 * (1.0 - k/1000.0);\n    double damp_factor = 1.0 + alpha * (factor - 1.0);\n    double edge_factor = pow(damp_factor, 1.0 / path_length);\n    for (int idx = 0; idx < path_length; idx++) {\n        auto& from = path[idx];\n        auto& to = path[idx+1];\n        updateEdge(from.i, from.j, to.i, to.j, edge_factor);\n    }\n}\n\npair<string, vector<Node>> computePath(int si, int sj, int ti, int tj) {\n    vector<vector<double>> dist(N, vector<double>(N, 1e18));\n    vector<vector<Node>> prev(N, vector<Node>(N, {-1,-1}));\n    dist[si][sj] = 0.0;\n    priority_queue<PQElement, vector<PQElement>, Compare> pq;\n    pq.push({0.0, {si, sj}});\n    while (!pq.empty()) {\n        auto [d, node] = pq.top(); pq.pop();\n        if (d > dist[node.i][node.j]) continue;\n        if (node.i == ti && node.j == tj) break;\n        // right\n        if (node.j+1 < N) {\n            double w = h_est[node.i][node.j];\n            if (dist[node.i][node.j] + w < dist[node.i][node.j+1]) {\n                dist[node.i][node.j+1] = dist[node.i][node.j] + w;\n                prev[node.i][node.j+1] = {node.i, node.j};\n                pq.push({dist[node.i][node.j+1], {node.i, node.j+1}});\n            }\n        }\n        // left\n        if (node.j-1 >= 0) {\n            double w = h_est[node.i][node.j-1];\n            if (dist[node.i][node.j] + w < dist[node.i][node.j-1]) {\n                dist[node.i][node.j-1] = dist[node.i][node.j] + w;\n                prev[node.i][node.j-1] = {node.i, node.j};\n                pq.push({dist[node.i][node.j-1], {node.i, node.j-1}});\n            }\n        }\n        // down\n        if (node.i+1 < N) {\n            double w = v_est[node.i][node.j];\n            if (dist[node.i][node.j] + w < dist[node.i+1][node.j]) {\n                dist[node.i+1][node.j] = dist[node.i][node.j] + w;\n                prev[node.i+1][node.j] = {node.i, node.j};\n                pq.push({dist[node.i+1][node.j], {node.i+1, node.j}});\n            }\n        }\n        // up\n        if (node.i-1 >= 0) {\n            double w = v_est[node.i-1][node.j];\n            if (dist[node.i][node.j] + w < dist[node.i-1][node.j]) {\n                dist[node.i-1][node.j] = dist[node.i][node.j] + w;\n                prev[node.i-1][node.j] = {node.i, node.j};\n                pq.push({dist[node.i-1][node.j], {node.i-1, node.j}});\n            }\n        }\n    }\n    // reconstruct path\n    vector<Node> path_nodes;\n    Node cur = {ti, tj};\n    while (cur.i != si || cur.j != sj) {\n        path_nodes.push_back(cur);\n        cur = prev[cur.i][cur.j];\n    }\n    path_nodes.push_back({si, sj});\n    reverse(path_nodes.begin(), path_nodes.end());\n    // convert to string\n    string path_str;\n    for (size_t idx = 0; idx < path_nodes.size()-1; idx++) {\n        auto& from = path_nodes[idx];\n        auto& to = path_nodes[idx+1];\n        if (to.i == from.i && to.j == from.j+1) path_str += 'R';\n        else if (to.i == from.i && to.j == from.j-1) path_str += 'L';\n        else if (to.i == from.i+1 && to.j == from.j) path_str += 'D';\n        else if (to.i == from.i-1 && to.j == from.j) path_str += 'U';\n    }\n    return {path_str, path_nodes};\n}\n\nint main() {\n    // initialize estimates\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N-1; ++j)\n            h_est[i][j] = 5000.0;\n    for (int i = 0; i < N-1; ++i)\n        for (int j = 0; j < N; ++j)\n            v_est[i][j] = 5000.0;\n\n    for (int k = 0; k < 1000; ++k) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n        auto [path_str, path_nodes] = computePath(si, sj, ti, tj);\n        cout << path_str << endl;\n        cout.flush();\n        int obs;\n        cin >> obs;\n        updateEstimates(path_nodes, obs, k);\n    }\n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <cmath>\n#include <numeric>\n#include <array>\n#include <cassert>\n\nusing namespace std;\n\nconst int N = 20; // fixed\nconst int ALPHABET = 8; // A..H\n\nstruct Placement {\n    int str_idx;\n    int row, col; // starting position\n    int dir;      // 0: horizontal, 1: vertical\n    int len;\n};\n\nvector<string> strings;\nvector<Placement> placements;\nvector<vector<int>> placements_by_str;\nvector<vector<pair<int, char>>> cell_lists; // for each cell, list of (placement_id, required_char)\n\n// random generator\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// ------------------------------------------------------------\n// Generate all placements and group by string\nvoid generate_placements() {\n    int M = strings.size();\n    placements_by_str.resize(M);\n    placements.clear();\n    placements.reserve(M * 800);\n    int id = 0;\n    for (int s = 0; s < M; ++s) {\n        int len = strings[s].size();\n        for (int dir = 0; dir < 2; ++dir) {\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    placements.push_back({s, r, c, dir, len});\n                    placements_by_str[s].push_back(id);\n                    ++id;\n                }\n            }\n        }\n    }\n}\n\n// Build cell lists (reverse index)\nvoid build_cell_lists() {\n    cell_lists.assign(N * N, {});\n    for (int pid = 0; pid < (int)placements.size(); ++pid) {\n        const Placement& p = placements[pid];\n        for (int off = 0; off < p.len; ++off) {\n            int r, c;\n            if (p.dir == 0) { // horizontal\n                r = p.row;\n                c = (p.col + off) % N;\n            } else { // vertical\n                r = (p.row + off) % N;\n                c = p.col;\n            }\n            int cell = r * N + c;\n            char req = strings[p.str_idx][off];\n            cell_lists[cell].emplace_back(pid, req);\n        }\n    }\n}\n\n// Check if a string appears as a subsequence in the matrix\nbool is_subsequence(const vector<vector<char>>& mat, const string& s) {\n    int len = s.size();\n    // horizontal\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            bool ok = true;\n            for (int p = 0; p < len; ++p) {\n                if (mat[i][(j + p) % N] != s[p]) {\n                    ok = false;\n                    break;\n                }\n            }\n            if (ok) return true;\n        }\n    }\n    // vertical\n    for (int j = 0; j < N; ++j) {\n        for (int i = 0; i < N; ++i) {\n            bool ok = true;\n            for (int p = 0; p < len; ++p) {\n                if (mat[(i + p) % N][j] != s[p]) {\n                    ok = false;\n                    break;\n                }\n            }\n            if (ok) return true;\n        }\n    }\n    return false;\n}\n\n// Evaluate a matrix: number of satisfied strings\nint evaluate(const vector<vector<char>>& mat) {\n    int cnt = 0;\n    for (const string& s : strings) {\n        if (is_subsequence(mat, s)) ++cnt;\n    }\n    return cnt;\n}\n\n// ------------------------------------------------------------\n// Greedy construction (randomized)\nvector<vector<char>> greedy(int seed) {\n    mt19937 gen(seed);\n    vector<vector<char>> mat(N, vector<char>(N, '.'));\n    int M = strings.size();\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    shuffle(order.begin(), order.end(), gen);\n\n    for (int idx : order) {\n        const string& s = strings[idx];\n        int len = s.size();\n        vector<int> plist = placements_by_str[idx];\n        shuffle(plist.begin(), plist.end(), gen);\n        bool placed = false;\n        for (int pid : plist) {\n            const Placement& p = placements[pid];\n            // check compatibility\n            bool compatible = true;\n            for (int off = 0; off < len; ++off) {\n                int r, c;\n                if (p.dir == 0) {\n                    r = p.row;\n                    c = (p.col + off) % N;\n                } else {\n                    r = (p.row + off) % N;\n                    c = p.col;\n                }\n                if (mat[r][c] != '.' && mat[r][c] != s[off]) {\n                    compatible = false;\n                    break;\n                }\n            }\n            if (compatible) {\n                // place\n                for (int off = 0; off < len; ++off) {\n                    int r, c;\n                    if (p.dir == 0) {\n                        r = p.row;\n                        c = (p.col + off) % N;\n                    } else {\n                        r = (p.row + off) % N;\n                        c = p.col;\n                    }\n                    if (mat[r][c] == '.') {\n                        mat[r][c] = s[off];\n                    }\n                }\n                placed = true;\n                break;\n            }\n        }\n        // if not placed, we simply skip\n    }\n    // fill remaining '.' with 'A'\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (mat[i][j] == '.')\n                mat[i][j] = 'A';\n    return mat;\n}\n\n// ------------------------------------------------------------\n// Simulated Annealing\nvector<vector<char>> simulated_annealing(vector<vector<char>> mat) {\n    int M = strings.size();\n    int P = placements.size();\n    // Initialize placement_match_count and string_sat_count\n    vector<int> placement_match_count(P, 0);\n    vector<int> string_sat_count(M, 0);\n    int global_c = 0;\n\n    // Compute initial counts\n    for (int pid = 0; pid < P; ++pid) {\n        const Placement& p = placements[pid];\n        int cnt = 0;\n        for (int off = 0; off < p.len; ++off) {\n            int r, c;\n            if (p.dir == 0) {\n                r = p.row;\n                c = (p.col + off) % N;\n            } else {\n                r = (p.row + off) % N;\n                c = p.col;\n            }\n            if (mat[r][c] == strings[p.str_idx][off]) ++cnt;\n        }\n        placement_match_count[pid] = cnt;\n        if (cnt == p.len) {\n            ++string_sat_count[p.str_idx];\n        }\n    }\n    for (int s = 0; s < M; ++s)\n        if (string_sat_count[s] > 0) ++global_c;\n\n    // SA parameters\n    const int ITER = 200000; // adjustable\n    double T = 10.0;\n    double cooling = 0.99995; // such that after ITER, T ~ 10 * 0.99995^200000 \u2248 0.00045\n    uniform_int_distribution<int> cell_dist(0, N*N - 1);\n    uniform_int_distribution<int> char_dist(0, ALPHABET - 1);\n    uniform_real_distribution<double> prob_dist(0.0, 1.0);\n\n    for (int iter = 0; iter < ITER; ++iter) {\n        int cell = cell_dist(rng);\n        char old_char = mat[cell / N][cell % N];\n        char new_char = 'A' + char_dist(rng);\n        if (new_char == old_char) continue;\n\n        // We'll compute changes and apply them if accepted\n        vector<pair<int, int>> changed_placements; // (pid, old_count)\n        vector<pair<int, int>> changed_strings;    // (str_idx, delta)\n        int delta_c = 0;\n\n        for (const auto& [pid, req] : cell_lists[cell]) {\n            int cur_cnt = placement_match_count[pid];\n            int new_cnt = cur_cnt;\n            if (old_char == req) --new_cnt;\n            if (new_char == req) ++new_cnt;\n            if (new_cnt == cur_cnt) continue;\n\n            int len = placements[pid].len;\n            bool was_sat = (cur_cnt == len);\n            bool now_sat = (new_cnt == len);\n\n            changed_placements.emplace_back(pid, cur_cnt);\n            placement_match_count[pid] = new_cnt;\n\n            if (was_sat != now_sat) {\n                int str_idx = placements[pid].str_idx;\n                int delta = now_sat ? 1 : -1;\n                changed_strings.emplace_back(str_idx, delta);\n                string_sat_count[str_idx] += delta;\n                if (delta == 1 && string_sat_count[str_idx] == 1) ++delta_c;\n                if (delta == -1 && string_sat_count[str_idx] == 0) --delta_c;\n            }\n        }\n\n        // Decide acceptance\n        bool accept = false;\n        if (delta_c >= 0) accept = true;\n        else {\n            double prob = exp(delta_c / T);\n            if (prob_dist(rng) < prob) accept = true;\n        }\n\n        if (accept) {\n            mat[cell / N][cell % N] = new_char;\n            global_c += delta_c;\n            if (global_c == M) break; // perfect, we can stop\n        } else {\n            // revert changes\n            for (auto& [pid, old_cnt] : changed_placements) {\n                placement_match_count[pid] = old_cnt;\n            }\n            for (auto& [str_idx, delta] : changed_strings) {\n                string_sat_count[str_idx] -= delta;\n            }\n        }\n\n        T *= cooling;\n    }\n\n    return mat;\n}\n\n// ------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    cin >> N >> M;\n    strings.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> strings[i];\n    }\n\n    generate_placements();\n    build_cell_lists();\n\n    // Run greedy several times to get a good starting matrix\n    vector<vector<char>> best_mat;\n    int best_c = -1;\n    const int GREEDY_TRIES = 10;\n    for (int t = 0; t < GREEDY_TRIES; ++t) {\n        auto mat = greedy(rng());\n        int c = evaluate(mat);\n        if (c > best_c) {\n            best_c = c;\n            best_mat = mat;\n        }\n        if (best_c == M) break;\n    }\n\n    // If greedy already achieved perfect, we can skip SA (but we may still run SA to reduce dots? but we have no dots)\n    if (best_c < M) {\n        best_mat = simulated_annealing(best_mat);\n    }\n\n    // Output\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << best_mat[i][j];\n        }\n        cout << '\\n';\n    }\n    return 0;\n}","ahc005":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <utility>\n\nusing namespace std;\n\nconst int INF = 1e9;\nconst int dr[4] = {-1, 1, 0, 0};\nconst int dc[4] = {0, 0, -1, 1};\nconst char dir_char[4] = {'U', 'D', 'L', 'R'};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, si, sj;\n    cin >> N >> si >> sj;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> grid[i];\n    }\n\n    // assign indices to road squares\n    vector<vector<int>> idx(N, vector<int>(N, -1));\n    vector<int> row, col, w;\n    int V = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != '#') {\n                idx[i][j] = V;\n                row.push_back(i);\n                col.push_back(j);\n                w.push_back(grid[i][j] - '0');\n                ++V;\n            }\n        }\n    }\n\n    // ---------- horizontal segments ----------\n    vector<int> seg_id_h(V, -1);\n    vector<vector<int>> seg_nodes_h;\n    int h_cnt = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != '#' && seg_id_h[idx[i][j]] == -1) {\n                int sid = h_cnt++;\n                seg_nodes_h.push_back({});\n                int jj = j;\n                while (jj < N && grid[i][jj] != '#') {\n                    int id = idx[i][jj];\n                    seg_id_h[id] = sid;\n                    seg_nodes_h[sid].push_back(id);\n                    ++jj;\n                }\n            }\n        }\n    }\n\n    // ---------- vertical segments ----------\n    vector<int> seg_id_v(V, -1);\n    vector<vector<int>> seg_nodes_v;\n    int v_cnt = 0;\n    for (int j = 0; j < N; ++j) {\n        for (int i = 0; i < N; ++i) {\n            if (grid[i][j] != '#' && seg_id_v[idx[i][j]] == -1) {\n                int sid = v_cnt++;\n                seg_nodes_v.push_back({});\n                int ii = i;\n                while (ii < N && grid[ii][j] != '#') {\n                    int id = idx[ii][j];\n                    seg_id_v[id] = sid;\n                    seg_nodes_v[sid].push_back(id);\n                    ++ii;\n                }\n            }\n        }\n    }\n\n    // choose the orientation with fewer segments\n    bool use_horiz = (h_cnt <= v_cnt);\n    int seg_cnt;\n    vector<int> seg_id(V);\n    vector<vector<int>> seg_nodes;\n    if (use_horiz) {\n        seg_cnt = h_cnt;\n        seg_id = seg_id_h;\n        seg_nodes = seg_nodes_h;\n    } else {\n        seg_cnt = v_cnt;\n        seg_id = seg_id_v;\n        seg_nodes = seg_nodes_v;\n    }\n\n    int start_idx = idx[si][sj];\n    int start_seg = seg_id[start_idx];\n    vector<bool> seg_visited(seg_cnt, false);\n    seg_visited[start_seg] = true;\n    int remaining = seg_cnt - 1;\n\n    string moves;\n    int cur = start_idx;\n\n    // Dijkstra from a source, filling dist and pred\n    auto dijkstra = [&](int src, vector<int>& dist, vector<int>& pred) {\n        dist.assign(V, INF);\n        pred.assign(V, -1);\n        dist[src] = 0;\n        using P = pair<int, int>;\n        priority_queue<P, vector<P>, greater<P>> pq;\n        pq.emplace(0, src);\n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop();\n            if (d != dist[u]) continue;\n            int r = row[u], c = col[u];\n            for (int k = 0; k < 4; ++k) {\n                int nr = r + dr[k];\n                int nc = c + dc[k];\n                if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n                int v = idx[nr][nc];\n                if (v == -1) continue;\n                int nd = d + w[v];\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    pred[v] = u;\n                    pq.emplace(nd, v);\n                }\n            }\n        }\n    };\n\n    // main loop: visit all segments\n    while (remaining > 0) {\n        vector<int> dist(V), pred(V);\n        dijkstra(cur, dist, pred);\n\n        // find the closest unvisited segment and its closest square\n        int best_seg = -1, best_node = -1, best_dist = INF;\n        for (int s = 0; s < seg_cnt; ++s) {\n            if (seg_visited[s]) continue;\n            int min_d = INF, node = -1;\n            for (int v : seg_nodes[s]) {\n                if (dist[v] < min_d) {\n                    min_d = dist[v];\n                    node = v;\n                }\n            }\n            if (min_d < best_dist) {\n                best_dist = min_d;\n                best_seg = s;\n                best_node = node;\n            }\n        }\n\n        // reconstruct the path from cur to best_node\n        vector<int> path;\n        for (int v = best_node; v != cur; v = pred[v]) {\n            path.push_back(v);\n        }\n        path.push_back(cur);\n        reverse(path.begin(), path.end());   // now path[0] = cur, path[last] = best_node\n\n        // walk along the path, record moves and mark newly visited segments\n        for (size_t i = 0; i + 1 < path.size(); ++i) {\n            int from = path[i];\n            int to = path[i+1];\n            int dr = row[to] - row[from];\n            int dc = col[to] - col[from];\n            char move;\n            if (dr == -1) move = 'U';\n            else if (dr == 1) move = 'D';\n            else if (dc == -1) move = 'L';\n            else if (dc == 1) move = 'R';\n            else { /* should not happen */ }\n            moves += move;\n            int s = seg_id[to];\n            if (!seg_visited[s]) {\n                seg_visited[s] = true;\n                --remaining;\n            }\n        }\n        cur = best_node;\n    }\n\n    // return to the start square\n    if (cur != start_idx) {\n        vector<int> dist(V), pred(V);\n        dijkstra(cur, dist, pred);\n        vector<int> path;\n        for (int v = start_idx; v != cur; v = pred[v]) {\n            path.push_back(v);\n        }\n        path.push_back(cur);\n        reverse(path.begin(), path.end());\n        for (size_t i = 0; i + 1 < path.size(); ++i) {\n            int from = path[i];\n            int to = path[i+1];\n            int dr = row[to] - row[from];\n            int dc = col[to] - col[from];\n            char move;\n            if (dr == -1) move = 'U';\n            else if (dr == 1) move = 'D';\n            else if (dc == -1) move = 'L';\n            else if (dc == 1) move = 'R';\n            moves += move;\n        }\n    }\n\n    cout << moves << '\\n';\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K, R;\n    cin >> N >> M >> K >> R;\n    \n    vector<vector<int>> d(N, vector<int>(K));\n    vector<double> d_sum_per_skill(K, 0.0);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < K; ++j) {\n            cin >> d[i][j];\n            d_sum_per_skill[j] += d[i][j];\n        }\n    }\n\n    // Compute average required skill per dimension\n    vector<double> avg_d(K);\n    for (int k = 0; k < K; ++k) {\n        avg_d[k] = d_sum_per_skill[k] / N;\n    }\n\n    vector<vector<int>> succ(N);\n    vector<vector<int>> pred(N);\n    vector<int> prereq_count(N, 0);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        succ[u].push_back(v);\n        pred[v].push_back(u);\n        ++prereq_count[v];\n    }\n\n    // Compute longest path (depth) for each task\n    vector<int> depth(N, 0);\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        return a < b;  // Process in natural order due to u<v guarantee\n    });\n    \n    for (int i = N-1; i >= 0; --i) {\n        int task = order[i];\n        if (succ[task].empty()) {\n            depth[task] = 1;\n        } else {\n            int max_depth = 0;\n            for (int next : succ[task]) {\n                max_depth = max(max_depth, depth[next]);\n            }\n            depth[task] = max_depth + 1;\n        }\n    }\n\n    vector<int> task_status(N, -1);\n    vector<int> task_start_day(N, -1);\n    vector<int> prereq_rem = prereq_count;\n    vector<int> member_task(M, -1);\n    vector<int> member_load(M, 0);\n    \n    // Initialize skill estimates based on s_j generation range\n    vector<vector<double>> est_s(M, vector<double>(K));\n    for (int j = 0; j < M; ++j) {\n        for (int k = 0; k < K; ++k) {\n            // s_j generation: norm between 20-60, so per dimension ~20/sqrt(K) to 60/sqrt(K)\n            // For K=15, that's about 5-15. Start with 10 as initial guess\n            est_s[j][k] = 10.0 + avg_d[k] * 0.5;\n        }\n    }\n\n    int day = 0;\n    int total_observations = 0;\n    while (true) {\n        ++day;\n        if (day > 2000) break;\n\n        if (day > 1) {\n            int n;\n            cin >> n;\n            if (n == -1) break;\n            for (int i = 0; i < n; ++i) {\n                int f;\n                cin >> f;\n                --f;\n                int task = member_task[f];\n                if (task != -1) {\n                    task_status[task] = 1;\n                    int t_obs = (day - 1) - task_start_day[task] + 1;\n                    ++total_observations;\n                    \n                    double w_pred = 0.0;\n                    int deficit_count = 0;\n                    for (int k = 0; k < K; ++k) {\n                        if (d[task][k] > est_s[f][k]) {\n                            w_pred += d[task][k] - est_s[f][k];\n                            ++deficit_count;\n                        }\n                    }\n                    \n                    // Learning rate decreases as we get more observations\n                    double lr = 0.7 / (1.0 + total_observations * 0.01);\n                    \n                    if (t_obs > 1) {\n                        double error = t_obs - w_pred;\n                        if (deficit_count > 0 && abs(error) > 1e-9) {\n                            double delta = lr * error / deficit_count;\n                            for (int k = 0; k < K; ++k) {\n                                if (d[task][k] > est_s[f][k]) {\n                                    est_s[f][k] = max(0.0, est_s[f][k] - delta);\n                                }\n                            }\n                        }\n                    } else {\n                        if (w_pred > 0 && deficit_count > 0) {\n                            double delta = lr * w_pred / deficit_count;\n                            for (int k = 0; k < K; ++k) {\n                                if (d[task][k] > est_s[f][k]) {\n                                    est_s[f][k] = min(double(d[task][k]), est_s[f][k] + delta);\n                                }\n                            }\n                        }\n                    }\n                    \n                    for (int s : succ[task]) {\n                        --prereq_rem[s];\n                    }\n                    member_task[f] = -1;\n                    member_load[f] = max(0, member_load[f] - 1);\n                }\n            }\n        }\n\n        vector<int> free_members;\n        for (int j = 0; j < M; ++j) {\n            if (member_task[j] == -1) free_members.push_back(j);\n        }\n\n        vector<int> ready_tasks;\n        for (int i = 0; i < N; ++i) {\n            if (task_status[i] == -1 && prereq_rem[i] == 0) {\n                ready_tasks.push_back(i);\n            }\n        }\n\n        if (free_members.empty() || ready_tasks.empty()) {\n            cout << \"0\\n\";\n            cout.flush();\n            continue;\n        }\n\n        // Sort tasks by criticality (longest path) descending, then by predicted difficulty\n        sort(ready_tasks.begin(), ready_tasks.end(), [&](int a, int b) {\n            if (depth[a] != depth[b]) return depth[a] > depth[b];\n            // If same depth, prefer tasks with higher total requirement\n            double sum_a = 0, sum_b = 0;\n            for (int k = 0; k < K; ++k) {\n                sum_a += d[a][k];\n                sum_b += d[b][k];\n            }\n            return sum_a > sum_b;\n        });\n\n        vector<pair<int, int>> assignments;\n        for (int task : ready_tasks) {\n            if (free_members.empty()) break;\n            \n            // Find best member considering both skill and load\n            int best_member = -1;\n            double best_score = -1e18;\n            \n            for (int j : free_members) {\n                double w = 0.0;\n                for (int k = 0; k < K; ++k) {\n                    if (d[task][k] > est_s[j][k]) {\n                        w += d[task][k] - est_s[j][k];\n                    }\n                }\n                double t_pred = max(1.0, w);\n                \n                // Score considers both predicted time and current load\n                // Lower predicted time is better, lower load is better\n                double score = -t_pred - member_load[j] * 0.5;\n                \n                if (score > best_score) {\n                    best_score = score;\n                    best_member = j;\n                }\n            }\n            \n            if (best_member != -1) {\n                task_status[task] = 0;\n                task_start_day[task] = day;\n                member_task[best_member] = task;\n                member_load[best_member]++;\n                assignments.emplace_back(best_member, task);\n                free_members.erase(find(free_members.begin(), free_members.end(), best_member));\n            }\n        }\n\n        cout << assignments.size();\n        for (auto [member, task] : assignments) {\n            cout << ' ' << member + 1 << ' ' << task + 1;\n        }\n        cout << '\\n';\n        cout.flush();\n    }\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point {\n    int x, y;\n    Point() {}\n    Point(int x, int y) : x(x), y(y) {}\n};\n\nint manhattan(const Point& a, const Point& b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    // Read 1000 orders\n    vector<Point> restaurants(1000), destinations(1000);\n    for (int i = 0; i < 1000; ++i) {\n        cin >> restaurants[i].x >> restaurants[i].y >> destinations[i].x >> destinations[i].y;\n    }\n\n    const Point depot(400, 400);\n\n    // Step 1: Select 50 orders with smallest max distance to depot\n    vector<int> order_cost(1000);\n    for (int i = 0; i < 1000; ++i) {\n        order_cost[i] = max(manhattan(depot, restaurants[i]), manhattan(depot, destinations[i]));\n    }\n    vector<int> indices(1000);\n    iota(indices.begin(), indices.end(), 0);\n    sort(indices.begin(), indices.end(), [&](int i, int j) {\n        return order_cost[i] < order_cost[j];\n    });\n\n    vector<int> selected_orders;\n    for (int i = 0; i < 50; ++i) {\n        selected_orders.push_back(indices[i]);\n    }\n\n    // Create points for selected orders\n    vector<Point> points;\n    vector<pair<int, int>> point_info; // (order_index, type) type: 0=pickup, 1=delivery\n    for (int i = 0; i < 50; ++i) {\n        int order_idx = selected_orders[i];\n        points.push_back(restaurants[order_idx]);\n        point_info.push_back({i, 0});\n        points.push_back(destinations[order_idx]);\n        point_info.push_back({i, 1});\n    }\n\n    // Step 2: Build initial tour using cheapest insertion\n    const int total_points = 100;\n    // Precompute distances between all points and depot\n    vector<vector<int>> dist_mat(total_points, vector<int>(total_points));\n    vector<int> dist_to_depot(total_points);\n    for (int i = 0; i < total_points; ++i) {\n        for (int j = 0; j < total_points; ++j) {\n            dist_mat[i][j] = manhattan(points[i], points[j]);\n        }\n        dist_to_depot[i] = manhattan(points[i], depot);\n    }\n\n    // Start with the first order (pick the one with smallest cost)\n    int first_order = 0; // index in selected_orders\n    vector<int> tour = {first_order * 2, first_order * 2 + 1}; // pickup then delivery\n    vector<bool> used(50, false);\n    used[first_order] = true;\n\n    // Insert remaining orders\n    for (int step = 1; step < 50; ++step) {\n        int best_increase = INT_MAX;\n        int best_order = -1;\n        int best_pickup_pos = -1;\n        int best_delivery_pos = -1;\n\n        // Try each unused order\n        for (int order = 0; order < 50; ++order) {\n            if (used[order]) continue;\n            int pickup_idx = order * 2;\n            int delivery_idx = order * 2 + 1;\n\n            // Try all insertion positions for pickup and delivery\n            // Tour representation: depot -> tour[0] -> tour[1] -> ... -> depot\n            // We'll consider inserting between points in the tour\n            int tour_size = tour.size();\n            // For each possible pickup insertion position (between i and i+1)\n            for (int i = 0; i <= tour_size; ++i) {\n                // For each possible delivery insertion position (between j and j+1) with j >= i\n                for (int j = i; j <= tour_size; ++j) {\n                    int increase = 0;\n                    if (i == j) {\n                        // Insert both in the same gap: ... -> A -> (pickup, delivery) -> B ...\n                        Point A = (i == 0) ? depot : points[tour[i-1]];\n                        Point B = (i == tour_size) ? depot : points[tour[i]];\n                        increase = dist_to_depot[pickup_idx] + \n                                   dist_mat[pickup_idx][delivery_idx] + \n                                   dist_to_depot[delivery_idx] -\n                                   (i == 0 ? 0 : manhattan(A, B));\n                        // Correction: Actually we need to compute properly\n                        // Let's compute the change in distance when inserting pickup and delivery between A and B\n                        // Original: dist(A,B)\n                        // New: dist(A, pickup) + dist(pickup, delivery) + dist(delivery, B)\n                        // So increase = dist(A,pickup) + dist(pickup,delivery) + dist(delivery,B) - dist(A,B)\n                        int dAB = (i == 0 || i == tour_size) ? 0 : manhattan(A, B);\n                        increase = manhattan(A, points[pickup_idx]) + \n                                   dist_mat[pickup_idx][delivery_idx] + \n                                   manhattan(points[delivery_idx], B) - dAB;\n                    } else {\n                        // Insert pickup at position i, delivery at position j (i < j)\n                        // First, insertion of pickup between A and B\n                        Point A1 = (i == 0) ? depot : points[tour[i-1]];\n                        Point B1 = (i == tour_size) ? depot : points[tour[i]];\n                        int dA1B1 = (i == 0 || i == tour_size) ? 0 : manhattan(A1, B1);\n                        int inc_pickup = manhattan(A1, points[pickup_idx]) + \n                                         manhattan(points[pickup_idx], B1) - dA1B1;\n                        \n                        // Then insertion of delivery between C and D (note indices shift after pickup insertion)\n                        // After inserting pickup, the tour size increases by 1, so delivery position j becomes j+1\n                        Point C = (j == 0) ? depot : points[tour[j-1]];\n                        Point D = (j == tour_size) ? depot : points[tour[j]];\n                        int dCD = (j == 0 || j == tour_size) ? 0 : manhattan(C, D);\n                        int inc_delivery = manhattan(C, points[delivery_idx]) + \n                                           manhattan(points[delivery_idx], D) - dCD;\n                        increase = inc_pickup + inc_delivery;\n                    }\n\n                    if (increase < best_increase) {\n                        best_increase = increase;\n                        best_order = order;\n                        best_pickup_pos = i;\n                        best_delivery_pos = j;\n                    }\n                }\n            }\n        }\n\n        // Insert the best order\n        int pickup_idx = best_order * 2;\n        int delivery_idx = best_order * 2 + 1;\n        \n        if (best_pickup_pos == best_delivery_pos) {\n            // Insert both in the same gap\n            tour.insert(tour.begin() + best_pickup_pos, pickup_idx);\n            tour.insert(tour.begin() + best_pickup_pos + 1, delivery_idx);\n        } else {\n            // Insert pickup first, then delivery (adjusting indices)\n            tour.insert(tour.begin() + best_pickup_pos, pickup_idx);\n            // After inserting pickup, the delivery position shifts by 1 if it was after pickup\n            if (best_delivery_pos > best_pickup_pos) {\n                best_delivery_pos++;\n            }\n            tour.insert(tour.begin() + best_delivery_pos, delivery_idx);\n        }\n        used[best_order] = true;\n    }\n\n    // Convert tour to sequence of point indices (tour already contains point indices)\n    vector<int> seq = tour;\n\n    // Step 3: Improve with 2-opt using best move per pass\n    auto is_feasible = [&](const vector<int>& sequence) {\n        vector<int> first_pickup(50, -1);\n        vector<int> first_delivery(50, -1);\n        for (int idx = 0; idx < sequence.size(); ++idx) {\n            int point_idx = sequence[idx];\n            auto [order, type] = point_info[point_idx];\n            if (type == 0 && first_pickup[order] == -1) {\n                first_pickup[order] = idx;\n            }\n            if (type == 1 && first_delivery[order] == -1) {\n                first_delivery[order] = idx;\n            }\n        }\n        for (int i = 0; i < 50; ++i) {\n            if (first_pickup[i] > first_delivery[i]) {\n                return false;\n            }\n        }\n        return true;\n    };\n\n    bool improved = true;\n    int passes = 0;\n    const int max_passes = 200;\n    while (improved && passes < max_passes) {\n        improved = false;\n        passes++;\n        int best_delta = 0;\n        int best_i = -1, best_j = -1;\n        bool best_feasible = false;\n        \n        for (int i = 0; i < total_points - 1; ++i) {\n            for (int j = i + 1; j < total_points; ++j) {\n                int a = seq[i];\n                int b = seq[i + 1];\n                int c = seq[j];\n                int d = (j + 1 < total_points) ? seq[j + 1] : -1;\n\n                int old_len = dist_mat[a][b];\n                if (d == -1) old_len += dist_to_depot[c];\n                else old_len += dist_mat[c][d];\n\n                int new_len = dist_mat[a][c];\n                if (d == -1) new_len += dist_to_depot[b];\n                else new_len += dist_mat[b][d];\n\n                int delta = new_len - old_len;\n                \n                // Only consider improving moves\n                if (delta < 0) {\n                    // Check feasibility of the move\n                    vector<int> new_seq = seq;\n                    reverse(new_seq.begin() + i + 1, new_seq.begin() + j + 1);\n                    if (is_feasible(new_seq)) {\n                        if (delta < best_delta) {\n                            best_delta = delta;\n                            best_i = i;\n                            best_j = j;\n                            best_feasible = true;\n                        }\n                    }\n                }\n            }\n        }\n        \n        if (best_feasible) {\n            // Apply the best move\n            reverse(seq.begin() + best_i + 1, seq.begin() + best_j + 1);\n            improved = true;\n        }\n    }\n\n    // Step 4: Output results\n    cout << 50 << \" \";\n    for (int i = 0; i < 50; ++i) {\n        cout << selected_orders[i] + 1 << \" \";\n    }\n    cout << \"\\n\";\n\n    cout << 102 << \" 400 400 \";\n    for (int idx : seq) {\n        cout << points[idx].x << \" \" << points[idx].y << \" \";\n    }\n    cout << \"400 400\\n\";\n\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Edge {\n    int u, v, d;\n};\n\nstruct DSU {\n    vector<int> parent, sz;\n    DSU(int n) : parent(n), sz(n, 1) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        if (parent[x] != x) parent[x] = find(parent[x]);\n        return parent[x];\n    }\n    bool unite(int x, int y) {\n        x = find(x), y = find(y);\n        if (x == y) return false;\n        if (sz[x] < sz[y]) swap(x, y);\n        parent[y] = x;\n        sz[x] += sz[y];\n        return true;\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(N), y(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> x[i] >> y[i];\n    }\n\n    const int M = 5 * (N - 1);   // 1995\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        int dx = x[u] - x[v];\n        int dy = y[u] - y[v];\n        double dist = sqrt(dx * dx + dy * dy);\n        int d = (int)(dist + 0.5);   // round to nearest integer\n        edges[i] = {u, v, d};\n    }\n\n    // Precompute for each edge whether it is a bridge in the suffix graph (edges i..M-1)\n    vector<bool> is_bridge(M, false);\n    for (int i = 0; i < M; ++i) {\n        // build adjacency for edges i..M-1\n        vector<vector<pair<int, int>>> adj(N);\n        for (int j = i; j < M; ++j) {\n            int u = edges[j].u, v = edges[j].v;\n            adj[u].emplace_back(v, j);\n            adj[v].emplace_back(u, j);\n        }\n\n        vector<int> disc(N, -1), low(N, -1);\n        int timer = 0;\n        vector<bool> bridge_this(M, false);\n\n        function<void(int, int)> dfs = [&](int v, int parent_edge) {\n            disc[v] = low[v] = timer++;\n            for (auto [to, id] : adj[v]) {\n                if (id == parent_edge) continue;\n                if (disc[to] == -1) {\n                    dfs(to, id);\n                    low[v] = min(low[v], low[to]);\n                    if (low[to] > disc[v]) {\n                        bridge_this[id] = true;\n                    }\n                } else {\n                    low[v] = min(low[v], disc[to]);\n                }\n            }\n        };\n\n        for (int v = 0; v < N; ++v) {\n            if (disc[v] == -1) {\n                dfs(v, -1);\n            }\n        }\n        is_bridge[i] = bridge_this[i];\n    }\n\n    DSU dsu(N);\n    for (int i = 0; i < M; ++i) {\n        int l;\n        cin >> l;\n        int u = edges[i].u, v = edges[i].v;\n        bool accept = false;\n        if (dsu.find(u) == dsu.find(v)) {\n            accept = false;   // would create a cycle\n        } else {\n            if (is_bridge[i]) {\n                accept = true;   // forced to keep connectivity\n            } else {\n                // accept if weight is at most twice the lower bound (mean)\n                if (l <= 2 * edges[i].d) {\n                    accept = true;\n                } else {\n                    accept = false;\n                }\n            }\n        }\n        cout << (accept ? 1 : 0) << endl;\n        if (accept) {\n            dsu.unite(u, v);\n        }\n    }\n    return 0;\n}","ahc008":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <string>\n#include <algorithm>\n#include <utility>\n\nusing namespace std;\n\nconst int MAXN = 30;\nconst int dirs[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N;\n    vector<pair<int, int>> pets(N);\n    vector<int> pet_types(N);\n    for (int i = 0; i < N; ++i) {\n        int x, y, t;\n        cin >> x >> y >> t;\n        pets[i] = {x - 1, y - 1};\n        pet_types[i] = t;\n    }\n    cin >> M;\n    vector<pair<int, int>> humans(M);\n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        humans[i] = {x - 1, y - 1};\n    }\n\n    // grid state\n    bool wall[MAXN][MAXN] = {false};\n    bool to_build[MAXN][MAXN] = {false};\n    int owner[MAXN][MAXN];\n\n    // compute Voronoi owner based on initial human positions\n    for (int x = 0; x < MAXN; ++x) {\n        for (int y = 0; y < MAXN; ++y) {\n            int best_dist = 1000000, best_idx = -1;\n            for (int i = 0; i < M; ++i) {\n                int d = abs(x - humans[i].first) + abs(y - humans[i].second);\n                if (d < best_dist) {\n                    best_dist = d;\n                    best_idx = i;\n                }\n            }\n            owner[x][y] = best_idx;\n        }\n    }\n\n    // mark cells that should become walls (boundary between regions)\n    for (int x = 0; x < MAXN; ++x) {\n        for (int y = 0; y < MAXN; ++y) {\n            // skip human cells\n            bool is_human = false;\n            for (int i = 0; i < M; ++i) {\n                if (humans[i].first == x && humans[i].second == y) {\n                    is_human = true;\n                    break;\n                }\n            }\n            if (is_human) continue;\n\n            // check if any neighbor has different owner\n            bool boundary = false;\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 >= MAXN || ny < 0 || ny >= MAXN) continue;\n                if (owner[nx][ny] != owner[x][y]) {\n                    boundary = true;\n                    break;\n                }\n            }\n            if (boundary) {\n                to_build[x][y] = true;\n            }\n        }\n    }\n\n    // main loop for 300 turns\n    for (int turn = 0; turn < 300; ++turn) {\n        string actions(M, '.');\n\n        // decide actions for each human\n        for (int i = 0; i < M; ++i) {\n            int sx = humans[i].first, sy = humans[i].second;\n\n            // BFS on passable cells (owner == i, not wall, not to_build)\n            vector<vector<int>> dist(MAXN, vector<int>(MAXN, -1));\n            vector<vector<pair<int, int>>> parent(MAXN, vector<pair<int, int>>(MAXN, {-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 + dirs[d][0], ny = y + dirs[d][1];\n                    if (nx < 0 || nx >= MAXN || ny < 0 || ny >= MAXN) continue;\n                    if (owner[nx][ny] != i) continue;\n                    if (wall[nx][ny] || to_build[nx][ny]) continue;\n                    if (dist[nx][ny] != -1) continue;\n                    dist[nx][ny] = dist[x][y] + 1;\n                    parent[nx][ny] = {x, y};\n                    q.push({nx, ny});\n                }\n            }\n\n            // find the farthest reachable wall cell (to avoid trapping the human)\n            int best_wall_x = -1, best_wall_y = -1;\n            int best_adj_x = -1, best_adj_y = -1;\n            int best_dist = -1;\n\n            for (int x = 0; x < MAXN; ++x) {\n                for (int y = 0; y < MAXN; ++y) {\n                    if (!to_build[x][y] || wall[x][y]) continue;\n                    if (owner[x][y] != i) continue;  // only walls owned by this human\n                    // check each neighbor that is passable\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 >= MAXN || ny < 0 || ny >= MAXN) continue;\n                        if (owner[nx][ny] != i) continue;\n                        if (wall[nx][ny] || to_build[nx][ny]) continue;\n                        if (dist[nx][ny] == -1) continue;  // unreachable\n                        if (dist[nx][ny] > best_dist) {\n                            best_dist = dist[nx][ny];\n                            best_wall_x = x;\n                            best_wall_y = y;\n                            best_adj_x = nx;\n                            best_adj_y = ny;\n                        }\n                    }\n                }\n            }\n\n            if (best_wall_x == -1) {\n                // no reachable wall cell \u2192 stay\n                actions[i] = '.';\n                continue;\n            }\n\n            // if already adjacent to the target wall cell, try to build\n            if (abs(sx - best_wall_x) + abs(sy - best_wall_y) == 1) {\n                bool safe = true;\n                // check that no pet is on the wall cell itself\n                for (const auto& p : pets) {\n                    if (p.first == best_wall_x && p.second == best_wall_y) {\n                        safe = false;\n                        break;\n                    }\n                }\n                // check that no pet is adjacent to the wall cell\n                if (safe) {\n                    for (int d = 0; d < 4; ++d) {\n                        int nx = best_wall_x + dirs[d][0], ny = best_wall_y + dirs[d][1];\n                        if (nx < 0 || nx >= MAXN || ny < 0 || ny >= MAXN) continue;\n                        for (const auto& p : pets) {\n                            if (p.first == nx && p.second == ny) {\n                                safe = false;\n                                break;\n                            }\n                        }\n                        if (!safe) break;\n                    }\n                }\n                if (safe) {\n                    // output build action\n                    if (best_wall_x == sx - 1 && best_wall_y == sy) actions[i] = 'u';\n                    else if (best_wall_x == sx + 1 && best_wall_y == sy) actions[i] = 'd';\n                    else if (best_wall_x == sx && best_wall_y == sy - 1) actions[i] = 'l';\n                    else if (best_wall_x == sx && best_wall_y == sy + 1) actions[i] = 'r';\n                    else actions[i] = '.';  // should not happen\n                } else {\n                    actions[i] = '.';  // not safe, wait\n                }\n            } else {\n                // move one step towards the adjacent cell of the target wall\n                pair<int, int> next = {best_adj_x, best_adj_y};\n                while (parent[next.first][next.second] != make_pair(sx, sy)) {\n                    next = parent[next.first][next.second];\n                }\n                // determine move character\n                if (next.first == sx - 1 && next.second == sy) actions[i] = 'U';\n                else if (next.first == sx + 1 && next.second == sy) actions[i] = 'D';\n                else if (next.first == sx && next.second == sy - 1) actions[i] = 'L';\n                else if (next.first == sx && next.second == sy + 1) actions[i] = 'R';\n                else actions[i] = '.';  // should not happen\n            }\n        }\n\n        // output actions for this turn\n        cout << actions << endl;\n        cout.flush();\n\n        // apply human actions to update internal state\n        for (int i = 0; i < M; ++i) {\n            char act = actions[i];\n            int x = humans[i].first, y = humans[i].second;\n            if (act == 'u' || act == 'd' || act == 'l' || act == 'r') {\n                // build wall\n                int wx = x, wy = y;\n                if (act == 'u') wx = x - 1;\n                else if (act == 'd') wx = x + 1;\n                else if (act == 'l') wy = y - 1;\n                else if (act == 'r') wy = y + 1;\n                wall[wx][wy] = true;\n                to_build[wx][wy] = false;\n            } else if (act == 'U' || act == 'D' || act == 'L' || act == 'R') {\n                // move\n                if (act == 'U') humans[i].first = x - 1;\n                else if (act == 'D') humans[i].first = x + 1;\n                else if (act == 'L') humans[i].second = y - 1;\n                else if (act == 'R') humans[i].second = y + 1;\n            }\n            // '.' does nothing\n        }\n\n        // read pet movements for this turn\n        vector<string> pet_moves(N);\n        for (int i = 0; i < N; ++i) {\n            cin >> pet_moves[i];\n        }\n\n        // update pet positions\n        for (int i = 0; i < N; ++i) {\n            int x = pets[i].first, y = pets[i].second;\n            for (char c : pet_moves[i]) {\n                if (c == 'U') --x;\n                else if (c == 'D') ++x;\n                else if (c == 'L') --y;\n                else if (c == 'R') ++y;\n                // '.' does nothing\n            }\n            pets[i] = {x, y};\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cstring>\n#include <algorithm>\n#include <cmath>\nusing namespace std;\n\nconst int N = 20;\nconst int L = 200;\nconst int STATES = N * N;\nconst int BEAM_WIDTH = 10;\n\nint neighbor[STATES][4];\ndouble stay_prob[STATES][4];\ndouble move_prob[STATES][4];\ndouble V[STATES][L + 1];\n\nstruct Candidate {\n    vector<double> bel;\n    double accum;\n    string seq;\n    double estimate;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj, ti, tj;\n    double p;\n    cin >> si >> sj >> ti >> tj >> p;\n\n    vector<string> h(N);\n    for (int i = 0; i < N; ++i) cin >> h[i];\n    vector<string> v(N - 1);\n    for (int i = 0; i < N - 1; ++i) cin >> v[i];\n\n    // Build neighbour table and transition probabilities\n    memset(neighbor, -1, sizeof(neighbor));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int id = i * N + j;\n            // up\n            if (i > 0 && v[i - 1][j] == '0')\n                neighbor[id][0] = (i - 1) * N + j;\n            // down\n            if (i < N - 1 && v[i][j] == '0')\n                neighbor[id][1] = (i + 1) * N + j;\n            // left\n            if (j > 0 && h[i][j - 1] == '0')\n                neighbor[id][2] = i * N + (j - 1);\n            // right\n            if (j < N - 1 && h[i][j] == '0')\n                neighbor[id][3] = i * N + (j + 1);\n        }\n    }\n\n    // Precompute stay_prob and move_prob for each state and action\n    for (int s = 0; s < STATES; ++s) {\n        for (int a = 0; a < 4; ++a) {\n            if (neighbor[s][a] == -1) {\n                stay_prob[s][a] = 1.0;\n                move_prob[s][a] = 0.0;\n            } else {\n                stay_prob[s][a] = p;\n                move_prob[s][a] = 1.0 - p;\n            }\n        }\n    }\n\n    int start_id = si * N + sj;\n    int goal_id = ti * N + tj;\n\n    // DP for optimal closed\u2011loop value V[state][rem]\n    for (int s = 0; s < STATES; ++s)\n        for (int r = 0; r <= L; ++r)\n            V[s][r] = 0.0;\n\n    for (int rem = 1; rem <= L; ++rem) {\n        double reward_reach = 200.0 + rem;   // 401 - (200 - rem + 1)\n        for (int s = 0; s < STATES; ++s) {\n            if (s == goal_id) {\n                V[s][rem] = 0.0;\n                continue;\n            }\n            double best = 0.0;\n            for (int a = 0; a < 4; ++a) {\n                int nb = neighbor[s][a];\n                double sp = stay_prob[s][a];\n                double mp = move_prob[s][a];\n                double expected = sp * V[s][rem - 1];\n                if (mp > 0.0) {\n                    if (nb == goal_id) {\n                        expected += mp * reward_reach;\n                    } else {\n                        expected += mp * V[nb][rem - 1];\n                    }\n                }\n                if (expected > best) best = expected;\n            }\n            V[s][rem] = best;\n        }\n    }\n\n    // Beam search for the memorized string\n    vector<Candidate> beam;\n    vector<double> start_bel(STATES, 0.0);\n    start_bel[start_id] = 1.0;\n    beam.push_back({start_bel, 0.0, \"\", 0.0});\n\n    const char dir_chars[] = \"UDLR\";\n\n    for (int step = 1; step <= L; ++step) {\n        int rem = L - step;   // steps remaining after this one\n        vector<Candidate> next_beam;\n        next_beam.reserve(beam.size() * 4);\n\n        for (const auto& cand : beam) {\n            for (int a = 0; a < 4; ++a) {\n                vector<double> new_bel(STATES, 0.0);\n                double immediate_reward = 0.0;\n\n                for (int s = 0; s < STATES; ++s) {\n                    double prob = cand.bel[s];\n                    if (prob == 0.0) continue;\n                    int nb = neighbor[s][a];\n                    double sp = stay_prob[s][a];\n                    double mp = move_prob[s][a];\n                    new_bel[s] += prob * sp;\n                    if (mp > 0.0) {\n                        if (nb == goal_id) {\n                            immediate_reward += prob * mp * (401 - step);\n                        } else {\n                            new_bel[nb] += prob * mp;\n                        }\n                    }\n                }\n\n                double new_accum = cand.accum + immediate_reward;\n                double heuristic = 0.0;\n                for (int s = 0; s < STATES; ++s)\n                    heuristic += new_bel[s] * V[s][rem];\n                double estimate = new_accum + heuristic;\n\n                Candidate new_cand;\n                new_cand.bel = move(new_bel);\n                new_cand.accum = new_accum;\n                new_cand.seq = cand.seq + dir_chars[a];\n                new_cand.estimate = estimate;\n                next_beam.push_back(move(new_cand));\n            }\n        }\n\n        // Keep only the top BEAM_WIDTH candidates by estimate\n        sort(next_beam.begin(), next_beam.end(),\n             [](const Candidate& x, const Candidate& y) {\n                 return x.estimate > y.estimate;\n             });\n        if (next_beam.size() > BEAM_WIDTH)\n            next_beam.resize(BEAM_WIDTH);\n        beam = move(next_beam);\n    }\n\n    // Select the candidate with the highest actual accumulated score\n    Candidate best = *max_element(beam.begin(), beam.end(),\n                                  [](const Candidate& x, const Candidate& y) {\n                                      return x.accum < y.accum;\n                                  });\n    cout << best.seq << endl;\n\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30;\nconst int D = 4; // 0: left, 1: up, 2: right, 3: down\nconst int di[D] = {0, -1, 0, 1};\nconst int dj[D] = {-1, 0, 1, 0};\n\n// to[t][d] = exit direction when entering from d, or -1 if impossible\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\nint type[N][N];\nint rot[N][N];\nint best_rot[N][N];\nint best_score = 0;\n\ninline int get_exit(int t, int r, int d) {\n    int d_in = ((d - r) + 4) & 3;\n    int e = to[t][d_in];\n    if (e == -1) return -1;\n    return (e + r) & 3;\n}\n\nint compute_score(const int rot[N][N]) {\n    int status[N][N][D] = {0}; // 0: unvisited, 1: visiting, 2: processed\n    vector<int> cycles;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            for (int d = 0; d < D; ++d) {\n                if (status[i][j][d]) continue;\n                int t = type[i][j];\n                int r = rot[i][j];\n                if (get_exit(t, r, d) == -1) {\n                    status[i][j][d] = 2;\n                    continue;\n                }\n\n                vector<array<int, 3>> path;\n                int ci = i, cj = j, cd = d;\n                while (true) {\n                    if (status[ci][cj][cd] == 2) {\n                        for (auto& s : path) status[s[0]][s[1]][s[2]] = 2;\n                        break;\n                    }\n                    if (status[ci][cj][cd] == 1) {\n                        // cycle found\n                        int idx = -1;\n                        for (int k = 0; k < (int)path.size(); ++k) {\n                            if (path[k][0] == ci && path[k][1] == cj && path[k][2] == cd) {\n                                idx = k;\n                                break;\n                            }\n                        }\n                        int len = path.size() - idx;\n                        cycles.push_back(len);\n                        for (auto& s : path) status[s[0]][s[1]][s[2]] = 2;\n                        break;\n                    }\n                    status[ci][cj][cd] = 1;\n                    path.push_back({ci, cj, cd});\n\n                    // compute next state\n                    int t2 = type[ci][cj];\n                    int r2 = rot[ci][cj];\n                    int d2 = get_exit(t2, r2, cd);\n                    if (d2 == -1) {\n                        for (auto& s : path) status[s[0]][s[1]][s[2]] = 2;\n                        break;\n                    }\n                    int ni = ci + di[d2];\n                    int nj = cj + dj[d2];\n                    if (ni < 0 || ni >= N || nj < 0 || nj >= N) {\n                        for (auto& s : path) status[s[0]][s[1]][s[2]] = 2;\n                        break;\n                    }\n                    int nd = (d2 + 2) & 3;\n                    if (get_exit(type[ni][nj], rot[ni][nj], nd) == -1) {\n                        for (auto& s : path) status[s[0]][s[1]][s[2]] = 2;\n                        break;\n                    }\n                    ci = ni; cj = nj; cd = nd;\n                }\n            }\n        }\n    }\n\n    sort(cycles.rbegin(), cycles.rend());\n    if (cycles.size() < 2) return 0;\n    return cycles[0] * cycles[1];\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // read input\n    for (int i = 0; i < N; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; ++j) {\n            type[i][j] = s[j] - '0';\n        }\n    }\n\n    // random number generator\n    random_device rd;\n    mt19937 rng(rd());\n    uniform_real_distribution<double> uni(0.0, 1.0);\n    uniform_int_distribution<int> rand_tile(0, N-1);\n    uniform_int_distribution<int> rand_rot(0, 3);\n\n    // initialize rotations randomly\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            rot[i][j] = rand_rot(rng);\n\n    int current_score = compute_score(rot);\n    best_score = current_score;\n    memcpy(best_rot, rot, sizeof(rot));\n\n    // simulated annealing parameters\n    const int max_iter = 20000;\n    const double T0 = 1000.0;\n    double T = T0;\n\n    for (int iter = 0; iter < max_iter; ++iter) {\n        // pick a random tile\n        int i = rand_tile(rng);\n        int j = rand_tile(rng);\n        int old_r = rot[i][j];\n        int new_r = (old_r + 1 + rand_rot(rng)) % 4; // different rotation\n        rot[i][j] = new_r;\n\n        int new_score = compute_score(rot);\n        double delta = new_score - current_score;\n        if (delta > 0 || uni(rng) < exp(delta / T)) {\n            current_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            rot[i][j] = old_r; // revert\n        }\n\n        // cool down\n        T = T0 * (1.0 - iter / (double)max_iter);\n    }\n\n    // output best rotations as a string of 900 characters\n    string ans;\n    ans.reserve(N * N);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            ans += char('0' + best_rot[i][j]);\n    cout << ans << endl;\n\n    return 0;\n}","ahc011":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <cstring>\n#include <stack>\n\nusing namespace std;\n\nint N, T;\nint board[10][10];\nint empty_r, empty_c;\nint total_tiles; // N*N-1\n\n// precomputed bits for patterns 0..15\nbool has_up[16], has_down[16], has_left[16], has_right[16];\n\nvoid precompute_bits() {\n    for (int p = 0; p < 16; ++p) {\n        has_left[p]  = p & 1;\n        has_up[p]    = p & 2;\n        has_right[p] = p & 4;\n        has_down[p]  = p & 8;\n    }\n}\n\n// convert hex char to integer\nint hex_to_int(char c) {\n    if ('0' <= c && c <= '9') return c - '0';\n    return 10 + c - 'a';\n}\n\n// compute size of largest tree in the current board\nint compute_tree_size(int b[10][10]) {\n    bool vis[10][10] = {false};\n    int max_size = 0;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (b[i][j] == 0 || vis[i][j]) continue;\n\n            // DFS stack (encoded as i*N + j)\n            int stack[100];\n            int top = 0;\n            stack[top++] = i * N + j;\n            vis[i][j] = true;\n\n            int vertices = 0, edges = 0;\n            while (top) {\n                int pos = stack[--top];\n                int x = pos / N, y = pos % N;\n                ++vertices;\n                int p = b[x][y];\n\n                // up\n                if (has_up[p] && x > 0 && b[x-1][y] && has_down[b[x-1][y]]) {\n                    if (!vis[x-1][y]) {\n                        ++edges;\n                        vis[x-1][y] = true;\n                        stack[top++] = (x-1)*N + y;\n                    }\n                }\n                // down\n                if (has_down[p] && x+1 < N && b[x+1][y] && has_up[b[x+1][y]]) {\n                    if (!vis[x+1][y]) {\n                        ++edges;\n                        vis[x+1][y] = true;\n                        stack[top++] = (x+1)*N + y;\n                    }\n                }\n                // left\n                if (has_left[p] && y > 0 && b[x][y-1] && has_right[b[x][y-1]]) {\n                    if (!vis[x][y-1]) {\n                        ++edges;\n                        vis[x][y-1] = true;\n                        stack[top++] = x*N + (y-1);\n                    }\n                }\n                // right\n                if (has_right[p] && y+1 < N && b[x][y+1] && has_left[b[x][y+1]]) {\n                    if (!vis[x][y+1]) {\n                        ++edges;\n                        vis[x][y+1] = true;\n                        stack[top++] = x*N + (y+1);\n                    }\n                }\n            }\n\n            if (edges == vertices - 1) {\n                max_size = max(max_size, vertices);\n            }\n        }\n    }\n    return max_size;\n}\n\n// simulated annealing solver\nstring solve() {\n    precompute_bits();\n    total_tiles = N * N - 1;\n\n    // find initial empty position\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (board[i][j] == 0) {\n                empty_r = i;\n                empty_c = j;\n            }\n\n    // current state\n    int cur_board[10][10];\n    memcpy(cur_board, board, sizeof(board));\n    int cur_er = empty_r, cur_ec = empty_c;\n    int cur_S = compute_tree_size(cur_board);\n    string cur_moves = \"\";\n    int steps = 0;\n\n    // best state\n    int best_S = cur_S;\n    string best_moves = \"\";\n    int best_score;\n    if (cur_S == total_tiles)\n        best_score = (int)round(500000.0 * (2.0 - 0.0 / T));\n    else\n        best_score = (int)round(500000.0 * cur_S / total_tiles);\n\n    // SA parameters\n    double temp = 5.0;\n    const double cooling = 0.99995;\n    const double min_temp = 1e-3;\n\n    // random generators\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> dir_dist(0, 3);\n    uniform_real_distribution<double> prob_dist(0.0, 1.0);\n\n    // direction vectors and corresponding move characters\n    const int dr[4] = {-1, 1, 0, 0};\n    const int dc[4] = {0, 0, -1, 1};\n    const char move_char[4] = {'U', 'D', 'L', 'R'};\n\n    auto start_time = chrono::steady_clock::now();\n    const double time_limit = 2.9; // seconds\n    int iteration = 0;\n\n    while (steps < T) {\n        // time check every 20000 iterations\n        if ((iteration & 20000) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > time_limit) break;\n        }\n        ++iteration;\n\n        int dir = dir_dist(rng);\n        int nr = cur_er + dr[dir];\n        int nc = cur_ec + dc[dir];\n        if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n\n        // perform move\n        swap(cur_board[cur_er][cur_ec], cur_board[nr][nc]);\n        int new_S = compute_tree_size(cur_board);\n        double delta = new_S - cur_S;\n        bool accept = false;\n\n        if (delta > 0)\n            accept = true;\n        else if (temp > 1e-9) {\n            double prob = exp(delta / temp);\n            if (prob_dist(rng) < prob)\n                accept = true;\n        }\n\n        if (accept) {\n            cur_moves += move_char[dir];\n            ++steps;\n            cur_er = nr;\n            cur_ec = nc;\n            cur_S = new_S;\n\n            // if we reached a full tree, we are done (first full tree gives minimal K)\n            if (cur_S == total_tiles) {\n                best_moves = cur_moves;\n                break;\n            }\n\n            // otherwise update best score if improved\n            int K = steps;\n            int score;\n            if (cur_S == total_tiles)\n                score = (int)round(500000.0 * (2.0 - (double)K / T));\n            else\n                score = (int)round(500000.0 * cur_S / total_tiles);\n            if (score > best_score) {\n                best_score = score;\n                best_S = cur_S;\n                best_moves = cur_moves;\n            }\n        } else {\n            // revert move\n            swap(cur_board[cur_er][cur_ec], cur_board[nr][nc]);\n        }\n\n        // cool down\n        temp *= cooling;\n        if (temp < min_temp) temp = min_temp;\n    }\n\n    return best_moves;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> T;\n    for (int i = 0; i < N; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; ++j) {\n            board[i][j] = hex_to_int(s[j]);\n        }\n    }\n\n    string ans = solve();\n    cout << ans << endl;\n\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\nusing int64 = long long;\n\nstruct Line {\n    int64 px, py, qx, qy;\n    int64 dx, dy;\n};\n\nstruct ArrayHash {\n    size_t operator()(const array<uint64_t,2>& a) const {\n        return a[0] ^ (a[1] * 0x9e3779b97f4a7c15ULL);\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, K;\n    cin >> N >> K;\n    int a[11] = {0};\n    for (int d = 1; d <= 10; ++d) cin >> a[d];\n    vector<int64> xs(N), ys(N);\n    for (int i = 0; i < N; ++i) cin >> xs[i] >> ys[i];\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> coord_dist(-20000, 20000);\n    uniform_int_distribution<int> delta_dist(-5, 5);\n\n    // Helper to check that a line does not pass through any strawberry\n    auto is_valid_line = [&](const Line& line) -> bool {\n        if (line.px == line.qx && line.py == line.qy) return false;\n        for (int i = 0; i < N; ++i) {\n            int64 cross = line.dx * (ys[i] - line.py) - line.dy * (xs[i] - line.px);\n            if (cross == 0) return false;\n        }\n        return true;\n    };\n\n    // Helper to check that the line actually cuts the cake (distance < 10000)\n    auto line_cuts_circle = [&](const Line& line) -> bool {\n        int64 num = abs(line.qx * line.py - line.qy * line.px);\n        int64 len2 = line.dx * line.dx + line.dy * line.dy;\n        return num * num < 10000LL * 10000LL * len2;\n    };\n\n    // Generate initial K lines\n    vector<Line> lines(K);\n    for (int i = 0; i < K; ++i) {\n        while (true) {\n            Line line;\n            line.px = coord_dist(rng);\n            line.py = coord_dist(rng);\n            line.qx = coord_dist(rng);\n            line.qy = coord_dist(rng);\n            line.dx = line.qx - line.px;\n            line.dy = line.qy - line.py;\n            if (!is_valid_line(line)) continue;\n            if (!line_cuts_circle(line)) continue;\n            lines[i] = line;\n            break;\n        }\n    }\n\n    // Compute initial patterns and group counts\n    vector<array<uint64_t,2>> point_pat(N);\n    unordered_map<array<uint64_t,2>, int, ArrayHash> pat_cnt;\n    for (int i = 0; i < N; ++i) {\n        array<uint64_t,2> pat = {0, 0};\n        for (int l = 0; l < K; ++l) {\n            int side = (lines[l].dx * (ys[i] - lines[l].py) -\n                        lines[l].dy * (xs[i] - lines[l].px)) > 0 ? 1 : 0;\n            if (l < 64)\n                pat[0] |= (uint64_t(side) << l);\n            else\n                pat[1] |= (uint64_t(side) << (l - 64));\n        }\n        point_pat[i] = pat;\n        pat_cnt[pat]++;\n    }\n\n    int b[11] = {0};\n    for (auto& [pat, cnt] : pat_cnt) {\n        if (cnt >= 1 && cnt <= 10) b[cnt]++;\n    }\n\n    int current_score = 0;\n    for (int d = 1; d <= 10; ++d) current_score += min(a[d], b[d]);\n\n    // Simulated annealing parameters\n    double T = 50.0;\n    const double cooling = 0.9995;\n    const double large_prob = 0.01;\n    auto start_time = chrono::steady_clock::now();\n    const double time_limit = 2.8;  // seconds\n\n    for (int iter = 0; ; ++iter) {\n        // Time check every 1000 iterations\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 > time_limit) break;\n        }\n\n        int l = rng() % K;\n        bool large = (rng() % 100) < 1;\n\n        Line new_line;\n        bool valid = false;\n\n        if (!large) { // small perturbation\n            new_line = lines[l];\n            int which = rng() % 2;\n            if (which == 0) {\n                new_line.px += delta_dist(rng);\n                new_line.py += delta_dist(rng);\n            } else {\n                new_line.qx += delta_dist(rng);\n                new_line.qy += delta_dist(rng);\n            }\n            if (new_line.px == new_line.qx && new_line.py == new_line.qy) continue;\n            new_line.dx = new_line.qx - new_line.px;\n            new_line.dy = new_line.qy - new_line.py;\n            valid = true;\n            for (int i = 0; i < N; ++i) {\n                int64 cross = new_line.dx * (ys[i] - new_line.py) -\n                              new_line.dy * (xs[i] - new_line.px);\n                if (cross == 0) { valid = false; break; }\n            }\n        } else { // large change: completely new line\n            while (true) {\n                new_line.px = coord_dist(rng);\n                new_line.py = coord_dist(rng);\n                new_line.qx = coord_dist(rng);\n                new_line.qy = coord_dist(rng);\n                new_line.dx = new_line.qx - new_line.px;\n                new_line.dy = new_line.qy - new_line.py;\n                if (is_valid_line(new_line)) {\n                    valid = true;\n                    break;\n                }\n            }\n        }\n        if (!valid) continue;\n\n        // Apply changes incrementally\n        vector<pair<int, array<uint64_t,2>>> changed; // point index, old pattern\n\n        for (int i = 0; i < N; ++i) {\n            int64 cross = new_line.dx * (ys[i] - new_line.py) -\n                          new_line.dy * (xs[i] - new_line.px);\n            int new_side = cross > 0 ? 1 : 0;\n\n            // current side from pattern\n            uint64_t& low = point_pat[i][0];\n            uint64_t& high = point_pat[i][1];\n            int old_side;\n            if (l < 64) old_side = (low >> l) & 1;\n            else old_side = (high >> (l - 64)) & 1;\n\n            if (old_side == new_side) continue;\n\n            array<uint64_t,2> old_pat = {low, high};\n\n            // toggle the bit for line l\n            if (l < 64) low ^= (1ULL << l);\n            else high ^= (1ULL << (l - 64));\n            array<uint64_t,2> new_pat = {low, high};\n\n            // update map and b for old_pat -> new_pat\n            // decrement old_pat\n            auto it = pat_cnt.find(old_pat);\n            int c_old = it->second;\n            if (c_old >= 1 && c_old <= 10) b[c_old]--;\n            if (--c_old == 0) pat_cnt.erase(it);\n            else it->second = c_old;\n\n            // increment new_pat\n            auto it2 = pat_cnt.find(new_pat);\n            if (it2 != pat_cnt.end()) {\n                int c_new = it2->second;\n                if (c_new >= 1 && c_new <= 10) b[c_new]--;\n                it2->second = c_new + 1;\n                c_new++;\n                if (c_new >= 1 && c_new <= 10) b[c_new]++;\n            } else {\n                pat_cnt[new_pat] = 1;\n                if (1 <= 10) b[1]++;\n            }\n\n            changed.emplace_back(i, old_pat);\n        }\n\n        // Compute new score\n        int new_score = 0;\n        for (int d = 1; d <= 10; ++d) new_score += min(a[d], b[d]);\n\n        // Acceptance test\n        bool accept = false;\n        if (new_score >= current_score) {\n            accept = true;\n        } else {\n            double delta = new_score - current_score;\n            double prob = exp(delta / T);\n            uniform_real_distribution<double> real_dist(0.0, 1.0);\n            if (real_dist(rng) < prob) accept = true;\n        }\n\n        if (accept) {\n            lines[l] = new_line;\n            current_score = new_score;\n        } else {\n            // Revert all changes\n            for (auto& p : changed) {\n                int i = p.first;\n                array<uint64_t,2> old_pat = p.second;\n                array<uint64_t,2> new_pat = point_pat[i]; // current\n\n                // decrement new_pat\n                auto it = pat_cnt.find(new_pat);\n                int c_new = it->second;\n                if (c_new >= 1 && c_new <= 10) b[c_new]--;\n                if (--c_new == 0) pat_cnt.erase(it);\n                else it->second = c_new;\n\n                // increment old_pat\n                auto it2 = pat_cnt.find(old_pat);\n                if (it2 != pat_cnt.end()) {\n                    int c_old = it2->second;\n                    if (c_old >= 1 && c_old <= 10) b[c_old]--;\n                    it2->second = c_old + 1;\n                    c_old++;\n                    if (c_old >= 1 && c_old <= 10) b[c_old]++;\n                } else {\n                    pat_cnt[old_pat] = 1;\n                    if (1 <= 10) b[1]++;\n                }\n\n                point_pat[i] = old_pat;\n            }\n        }\n\n        T *= cooling;\n    }\n\n    // Output the final lines\n    cout << K << \"\\n\";\n    for (int i = 0; i < K; ++i) {\n        cout << lines[i].px << \" \" << lines[i].py << \" \"\n             << lines[i].qx << \" \" << lines[i].qy << \"\\n\";\n    }\n\n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <array>\n#include <random>\n#include <cmath>\n#include <chrono>\n#include <algorithm>\n\nusing namespace std;\n\nstruct MoveCandidate {\n    array<int, 8> pts;   // four points in cyclic order, starting with new dot\n    double score;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n\n    const int c = (N - 1) / 2;\n    vector<vector<int>> w(N, vector<int>(N));\n    long long totalS = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int dx = i - c, dy = j - c;\n            w[i][j] = dx * dx + dy * dy + 1;\n            totalS += w[i][j];\n        }\n    }\n\n    vector<pair<int, int>> init(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> init[i].first >> init[i].second;\n    }\n\n    const int TRIALS = 3;                 // number of independent greedy runs\n    vector<array<int, 8>> best_ops;\n    long long best_score = -1;\n\n    for (int trial = 0; trial < TRIALS; ++trial) {\n        // state\n        vector<vector<char>> dot(N, vector<char>(N, 0));\n        for (auto& p : init) dot[p.first][p.second] = 1;\n\n        // edge usage\n        vector<vector<char>> h_edge(N, vector<char>(N, 0));   // horizontal (x,y)-(x+1,y)\n        vector<vector<char>> v_edge(N, vector<char>(N, 0));   // vertical   (x,y)-(x,y+1)\n        vector<vector<char>> d1_edge(N, vector<char>(N, 0));  // diagonal up-right (x,y)-(x+1,y+1)\n        vector<vector<char>> d2_edge(N, vector<char>(N, 0));  // diagonal down-right (x,y)-(x+1,y-1)\n\n        vector<array<int, 8>> ops;   // performed operations\n\n        mt19937 rng(chrono::steady_clock::now().time_since_epoch().count() + trial);\n        uniform_real_distribution<double> noise(0.0, 0.5);\n\n        while (true) {\n            vector<MoveCandidate> candidates;\n            double max_score = -1.0;\n\n            for (int x = 0; x < N; ++x) {\n                for (int y = 0; y < N; ++y) {\n                    if (dot[x][y]) continue;\n                    int pw = w[x][y];\n\n                    // ---------- unit squares ----------\n                    // lower-left\n                    if (x + 1 < N && y + 1 < N) {\n                        if (dot[x+1][y] && dot[x][y+1] && dot[x+1][y+1]) {\n                            if (!h_edge[x][y] && !h_edge[x][y+1] && !v_edge[x][y] && !v_edge[x+1][y]) {\n                                array<int,8> pts = {x, y, x+1, y, x+1, y+1, x, y+1};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                    // lower-right\n                    if (x - 1 >= 0 && y + 1 < N) {\n                        if (dot[x-1][y] && dot[x-1][y+1] && dot[x][y+1]) {\n                            if (!h_edge[x-1][y] && !h_edge[x-1][y+1] && !v_edge[x-1][y] && !v_edge[x][y]) {\n                                array<int,8> pts = {x, y, x, y+1, x-1, y+1, x-1, y};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                    // upper-left\n                    if (x + 1 < N && y - 1 >= 0) {\n                        if (dot[x][y-1] && dot[x+1][y-1] && dot[x+1][y]) {\n                            if (!h_edge[x][y-1] && !h_edge[x][y] && !v_edge[x][y-1] && !v_edge[x+1][y-1]) {\n                                array<int,8> pts = {x, y, x+1, y, x+1, y-1, x, y-1};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                    // upper-right\n                    if (x - 1 >= 0 && y - 1 >= 0) {\n                        if (dot[x-1][y-1] && dot[x][y-1] && dot[x-1][y]) {\n                            if (!h_edge[x-1][y-1] && !h_edge[x-1][y] && !v_edge[x-1][y-1] && !v_edge[x][y-1]) {\n                                array<int,8> pts = {x, y, x-1, y, x-1, y-1, x, y-1};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n\n                    // ---------- unit diamonds (45\u00b0 rotated squares) ----------\n                    // case A : p is leftmost corner (lx,ly)\n                    if (x <= N-3 && y >= 1 && y <= N-2) {\n                        int lx = x, ly = y;\n                        if (dot[lx+1][ly+1] && dot[lx+2][ly] && dot[lx+1][ly-1]) {\n                            if (!d1_edge[lx][ly] && !d2_edge[lx+1][ly+1] && !d1_edge[lx+1][ly-1] && !d2_edge[lx][ly]) {\n                                array<int,8> pts = {lx, ly, lx+1, ly+1, lx+2, ly, lx+1, ly-1}; // A,B,C,D\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                    // case B : p is top corner (lx+1,ly+1)\n                    if (x >= 1 && x <= N-2 && y >= 2 && y <= N-1) {\n                        int lx = x-1, ly = y-1;\n                        if (dot[lx][ly] && dot[lx+2][ly] && dot[lx+1][ly-1]) {\n                            if (!d1_edge[lx][ly] && !d2_edge[lx+1][ly+1] && !d1_edge[lx+1][ly-1] && !d2_edge[lx][ly]) {\n                                // order B,C,D,A\n                                array<int,8> pts = {lx+1, ly+1, lx+2, ly, lx+1, ly-1, lx, ly};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                    // case C : p is rightmost corner (lx+2,ly)\n                    if (x >= 2 && y >= 1 && y <= N-2) {\n                        int lx = x-2, ly = y;\n                        if (dot[lx][ly] && dot[lx+1][ly+1] && dot[lx+1][ly-1]) {\n                            if (!d1_edge[lx][ly] && !d2_edge[lx+1][ly+1] && !d1_edge[lx+1][ly-1] && !d2_edge[lx][ly]) {\n                                // order C,D,A,B\n                                array<int,8> pts = {lx+2, ly, lx+1, ly-1, lx, ly, lx+1, ly+1};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                    // case D : p is bottom corner (lx+1,ly-1)\n                    if (x >= 1 && x <= N-2 && y >= 0 && y <= N-3) {\n                        int lx = x-1, ly = y+1;\n                        if (dot[lx][ly] && dot[lx+1][ly+1] && dot[lx+2][ly]) {\n                            if (!d1_edge[lx][ly] && !d2_edge[lx+1][ly+1] && !d1_edge[lx+1][ly-1] && !d2_edge[lx][ly]) {\n                                // order D,A,B,C\n                                array<int,8> pts = {lx+1, ly-1, lx, ly, lx+1, ly+1, lx+2, ly};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (candidates.empty()) break;\n\n            // collect all candidates with maximal score\n            vector<int> best_idx;\n            for (size_t i = 0; i < candidates.size(); ++i) {\n                if (candidates[i].score == max_score) best_idx.push_back(i);\n            }\n            // choose one uniformly at random\n            int chosen = best_idx[uniform_int_distribution<int>(0, best_idx.size()-1)(rng)];\n            MoveCandidate& mv = candidates[chosen];\n\n            // apply the move\n            int x1 = mv.pts[0], y1 = mv.pts[1];\n            dot[x1][y1] = 1;\n\n            // determine shape and mark edges\n            int minx = mv.pts[0], maxx = mv.pts[0], miny = mv.pts[1], maxy = mv.pts[1];\n            for (int i = 0; i < 4; ++i) {\n                int px = mv.pts[2*i], py = mv.pts[2*i+1];\n                if (px < minx) minx = px;\n                if (px > maxx) maxx = px;\n                if (py < miny) miny = py;\n                if (py > maxy) maxy = py;\n            }\n            if (maxx - minx == 1 && maxy - miny == 1) {   // unit square\n                h_edge[minx][miny] = 1;\n                h_edge[minx][maxy] = 1;\n                v_edge[minx][miny] = 1;\n                v_edge[maxx][miny] = 1;\n            } else {                                       // unit diamond\n                // recover lx,ly from the leftmost point (which has min x)\n                int lx = minx, ly = -1;\n                for (int i = 0; i < 4; ++i) {\n                    if (mv.pts[2*i] == lx) {\n                        ly = mv.pts[2*i+1];\n                        break;\n                    }\n                }\n                // mark the four diagonal edges\n                d1_edge[lx][ly] = 1;          // A-B\n                d2_edge[lx+1][ly+1] = 1;      // B-C\n                d1_edge[lx+1][ly-1] = 1;      // C-D\n                d2_edge[lx][ly] = 1;          // D-A\n            }\n\n            ops.push_back(mv.pts);\n        }\n\n        // compute score for this trial\n        long long sum_w = 0;\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                if (dot[i][j]) sum_w += w[i][j];\n\n        double factor = (double)(N * N) / M;\n        double ratio = (double)sum_w / totalS;\n        long long score = llround(1e6 * factor * ratio);\n\n        if (score > best_score) {\n            best_score = score;\n            best_ops = ops;\n        }\n    }\n\n    // output\n    cout << best_ops.size() << \"\\n\";\n    for (auto& op : best_ops) {\n        for (int i = 0; i < 8; ++i) {\n            if (i) cout << \" \";\n            cout << op[i];\n        }\n        cout << \"\\n\";\n    }\n\n    return 0;\n}","ahc015":"#include <iostream>\n#include <vector>\n#include <array>\n#include <queue>\n#include <utility>\n#include <algorithm>\n#include <cmath>\n#include <iomanip>\n\nusing namespace std;\n\n// global flavors (1-indexed)\nvector<int> flavors(101);\n\n// 10x10 grid: 0 = empty, 1..3 = flavor\nusing Grid = array<array<int, 10>, 10>;\n\n// ------------------------------------------------------------\n// tilt simulation\nGrid tilt(const Grid& g, char dir) {\n    Grid ng = {}; // zero-initialized\n    if (dir == 'F') {\n        for (int c = 0; c < 10; ++c) {\n            int idx = 0;\n            for (int r = 0; r < 10; ++r) {\n                if (g[r][c] != 0) {\n                    ng[idx++][c] = g[r][c];\n                }\n            }\n        }\n    } else if (dir == 'B') {\n        for (int c = 0; c < 10; ++c) {\n            int idx = 9;\n            for (int r = 9; r >= 0; --r) {\n                if (g[r][c] != 0) {\n                    ng[idx--][c] = g[r][c];\n                }\n            }\n        }\n    } else if (dir == 'L') {\n        for (int r = 0; r < 10; ++r) {\n            int idx = 0;\n            for (int c = 0; c < 10; ++c) {\n                if (g[r][c] != 0) {\n                    ng[r][idx++] = g[r][c];\n                }\n            }\n        }\n    } else if (dir == 'R') {\n        for (int r = 0; r < 10; ++r) {\n            int idx = 9;\n            for (int c = 9; c >= 0; --c) {\n                if (g[r][c] != 0) {\n                    ng[r][idx--] = g[r][c];\n                }\n            }\n        }\n    }\n    return ng;\n}\n\n// ------------------------------------------------------------\n// compute sum of squares of connected components\nint compute_sum_squares(const Grid& g) {\n    bool visited[10][10] = {};\n    int sum = 0;\n    for (int r = 0; r < 10; ++r) {\n        for (int c = 0; c < 10; ++c) {\n            if (g[r][c] != 0 && !visited[r][c]) {\n                int flavor = g[r][c];\n                int size = 0;\n                queue<pair<int, int>> q;\n                q.push({r, c});\n                visited[r][c] = true;\n                while (!q.empty()) {\n                    auto [x, y] = q.front(); q.pop();\n                    ++size;\n                    // four neighbors\n                    if (x > 0 && !visited[x-1][y] && g[x-1][y] == flavor) {\n                        visited[x-1][y] = true;\n                        q.push({x-1, y});\n                    }\n                    if (x < 9 && !visited[x+1][y] && g[x+1][y] == flavor) {\n                        visited[x+1][y] = true;\n                        q.push({x+1, y});\n                    }\n                    if (y > 0 && !visited[x][y-1] && g[x][y-1] == flavor) {\n                        visited[x][y-1] = true;\n                        q.push({x, y-1});\n                    }\n                    if (y < 9 && !visited[x][y+1] && g[x][y+1] == flavor) {\n                        visited[x][y+1] = true;\n                        q.push({x, y+1});\n                    }\n                }\n                sum += size * size;\n            }\n        }\n    }\n    return sum;\n}\n\n// ------------------------------------------------------------\n// compute total spread (sum of squared distances to centroid) for tie\u2011breaking\ndouble compute_spread(const Grid& g) {\n    vector<int> cnt(4, 0);\n    vector<double> sum_r(4, 0.0), sum_c(4, 0.0);\n    vector<double> sum_r2(4, 0.0), sum_c2(4, 0.0);\n    for (int r = 0; r < 10; ++r) {\n        for (int c = 0; c < 10; ++c) {\n            int f = g[r][c];\n            if (f != 0) {\n                cnt[f]++;\n                sum_r[f] += r;\n                sum_c[f] += c;\n                sum_r2[f] += r * r;\n                sum_c2[f] += c * c;\n            }\n        }\n    }\n    double total = 0.0;\n    for (int f = 1; f <= 3; ++f) {\n        if (cnt[f] > 0) {\n            double mean_r = sum_r[f] / cnt[f];\n            double mean_c = sum_c[f] / cnt[f];\n            total += (sum_r2[f] + sum_c2[f]) -\n                     (sum_r[f] * sum_r[f] + sum_c[f] * sum_c[f]) / cnt[f];\n        }\n    }\n    return total;\n}\n\n// ------------------------------------------------------------\n// recursive expectimax for remaining \u2264 3 candies\ndouble expected_score(const Grid& grid, int next_idx) {\n    if (next_idx > 100) {\n        return compute_sum_squares(grid);\n    }\n\n    // collect empty cells\n    vector<pair<int, int>> empties;\n    for (int r = 0; r < 10; ++r)\n        for (int c = 0; c < 10; ++c)\n            if (grid[r][c] == 0)\n                empties.emplace_back(r, c);\n\n    int E = empties.size();\n    double total = 0.0;\n\n    for (auto [r, c] : empties) {\n        // place the next candy\n        Grid g2 = grid;\n        g2[r][c] = flavors[next_idx];\n\n        // choose the best direction for this placement\n        double best = -1.0;\n        for (char dir : {'F', 'B', 'L', 'R'}) {\n            Grid g3 = tilt(g2, dir);\n            double val = expected_score(g3, next_idx + 1);\n            if (val > best) best = val;\n        }\n        total += best;\n    }\n    return total / E;\n}\n\n// ------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // read all flavors\n    for (int i = 1; i <= 100; ++i) {\n        cin >> flavors[i];\n    }\n\n    Grid grid = {};  // initially empty\n\n    for (int t = 1; t <= 100; ++t) {\n        int p;\n        cin >> p;\n\n        // place the t\u2011th candy in the p\u2011th empty cell (row\u2011major order)\n        int cnt = 0;\n        int r_place = -1, c_place = -1;\n        for (int r = 0; r < 10; ++r) {\n            for (int c = 0; c < 10; ++c) {\n                if (grid[r][c] == 0) {\n                    ++cnt;\n                    if (cnt == p) {\n                        r_place = r;\n                        c_place = c;\n                        break;\n                    }\n                }\n            }\n            if (cnt == p) break;\n        }\n        grid[r_place][c_place] = flavors[t];\n\n        // last tilt does nothing \u2013 output any direction and finish\n        if (t == 100) {\n            cout << 'F' << endl;\n            return 0;\n        }\n\n        int remaining = 100 - t;  // candies still to be placed after this step\n        char best_dir;\n        Grid best_grid;\n\n        if (remaining <= 3) {\n            // deep evaluation using expectimax\n            double best_val = -1.0;\n            for (char dir : {'F', 'B', 'L', 'R'}) {\n                Grid after_tilt = tilt(grid, dir);\n                double val = expected_score(after_tilt, t + 1);\n                if (val > best_val) {\n                    best_val = val;\n                    best_dir = dir;\n                    best_grid = after_tilt;\n                }\n            }\n        } else {\n            // greedy: maximise immediate sum of squares, tie\u2011break by lower spread\n            int best_sum_sq = -1;\n            double best_spread = 1e9;\n            for (char dir : {'F', 'B', 'L', 'R'}) {\n                Grid after_tilt = tilt(grid, dir);\n                int sum_sq = compute_sum_squares(after_tilt);\n                double spread = compute_spread(after_tilt);\n                if (sum_sq > best_sum_sq ||\n                    (sum_sq == best_sum_sq && spread < best_spread)) {\n                    best_sum_sq = sum_sq;\n                    best_spread = spread;\n                    best_dir = dir;\n                    best_grid = after_tilt;\n                }\n            }\n        }\n\n        cout << best_dir << endl;\n        grid = best_grid;\n    }\n\n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <string>\n#include <cmath>\n#include <cassert>\n\nusing namespace std;\n\nint main() {\n    // Problem parameters\n    int M;\n    double epsilon;\n    cin >> M >> epsilon;\n\n    // Fixed design choices\n    const int N = 30;                     // number of vertices\n    const int T = N * (N - 1) / 2;        // number of possible edges\n    const int TRIALS = 100;               // number of noise trials for precomputation\n\n    // ------------------------------------------------------------\n    // 1. Precompute all vertex pairs in lexicographic order\n    // ------------------------------------------------------------\n    vector<pair<int, int>> pairs;\n    pairs.reserve(T);\n    for (int i = 0; i < N; ++i)\n        for (int j = i + 1; j < N; ++j)\n            pairs.emplace_back(i, j);\n    assert(pairs.size() == T);\n\n    // ------------------------------------------------------------\n    // 2. Generate the M graphs G_0 ... G_{M-1}\n    // ------------------------------------------------------------\n    // Random generator for graph construction (deterministic seed)\n    mt19937 rng_graph(12345);\n    uniform_real_distribution<double> dist_graph(0.0, 1.0);\n\n    // Storage: adjacency matrices and the output strings\n    vector<vector<vector<bool>>> adj(M, vector<vector<bool>>(N, vector<bool>(N, false)));\n    vector<string> graph_strings(M);\n\n    for (int idx = 0; idx < M; ++idx) {\n        double p = (M > 1) ? double(idx) / (M - 1) : 0.0;   // edge probability for this graph\n        string s(T, '0');\n        for (int e = 0; e < T; ++e) {\n            auto [u, v] = pairs[e];\n            if (dist_graph(rng_graph) < p) {\n                adj[idx][u][v] = true;\n                s[e] = '1';\n            }\n        }\n        graph_strings[idx] = s;\n    }\n\n    // ------------------------------------------------------------\n    // 3. Output the chosen N and the M graphs\n    // ------------------------------------------------------------\n    cout << N << endl;\n    for (int i = 0; i < M; ++i)\n        cout << graph_strings[i] << endl;\n    cout.flush();\n\n    // ------------------------------------------------------------\n    // 4. Precompute mean and variance of sorted degree sequences\n    //    under the noise model (edge flips with probability epsilon)\n    // ------------------------------------------------------------\n    // Random generator for noise simulation (different seed)\n    mt19937 rng_noise(54321);\n    uniform_real_distribution<double> dist_noise(0.0, 1.0);\n\n    // Means and variances for each graph and each sorted position\n    vector<vector<double>> mean_deg(M, vector<double>(N, 0.0));\n    vector<vector<double>> var_deg(M, vector<double>(N, 0.0));\n\n    for (int g = 0; g < M; ++g) {\n        vector<double> sum(N, 0.0), sum_sq(N, 0.0);\n        for (int trial = 0; trial < TRIALS; ++trial) {\n            vector<int> deg(N, 0);\n            for (int e = 0; e < T; ++e) {\n                auto [u, v] = pairs[e];\n                bool present = adj[g][u][v];\n                // flip with probability epsilon\n                if (dist_noise(rng_noise) < epsilon)\n                    present = !present;\n                if (present) {\n                    deg[u]++;\n                    deg[v]++;\n                }\n            }\n            sort(deg.begin(), deg.end());\n            for (int j = 0; j < N; ++j) {\n                sum[j] += deg[j];\n                sum_sq[j] += deg[j] * deg[j];\n            }\n        }\n        for (int j = 0; j < N; ++j) {\n            mean_deg[g][j] = sum[j] / TRIALS;\n            double variance = sum_sq[j] / TRIALS - mean_deg[g][j] * mean_deg[g][j];\n            // avoid zero variance (can happen for empty/complete graphs with very low noise)\n            if (variance < 1e-9) variance = 1e-9;\n            var_deg[g][j] = variance;\n        }\n    }\n\n    // ------------------------------------------------------------\n    // 5. Process the 100 queries\n    // ------------------------------------------------------------\n    for (int q = 0; q < 100; ++q) {\n        string H_str;\n        cin >> H_str;\n        assert(H_str.size() == T);\n\n        // Compute degree sequence of H\n        vector<int> deg_H(N, 0);\n        for (int e = 0; e < T; ++e) {\n            if (H_str[e] == '1') {\n                auto [u, v] = pairs[e];\n                deg_H[u]++;\n                deg_H[v]++;\n            }\n        }\n        sort(deg_H.begin(), deg_H.end());\n\n        // Find the graph with smallest chi\u2011squared distance\n        int best_graph = 0;\n        double best_dist = 1e100;\n        for (int g = 0; g < M; ++g) {\n            double dist = 0.0;\n            for (int j = 0; j < N; ++j) {\n                double diff = deg_H[j] - mean_deg[g][j];\n                dist += (diff * diff) / var_deg[g][j];\n            }\n            if (dist < best_dist) {\n                best_dist = dist;\n                best_graph = g;\n            }\n        }\n\n        cout << best_graph << endl;\n        cout.flush();\n    }\n\n    return 0;\n}","ahc017":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <random>\n#include <cmath>\n#include <numeric>\n#include <tuple>\n#include <chrono>\n#include <cassert>\n\nusing namespace std;\n\ntypedef long double ld;\nconst ld INF = 1e18L;\n\nstruct Edge {\n    int u, v;\n    long long w;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n    vector<Edge> edges(M);\n    vector<vector<pair<int, pair<int, long long>>>> adj(N); // to, (edge_id, weight)\n    for (int i = 0; i < M; ++i) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        --u; --v;\n        edges[i] = {u, v, w};\n        adj[u].push_back({v, {i, w}});\n        adj[v].push_back({u, {i, w}});\n    }\n    // read and ignore coordinates\n    for (int i = 0; i < N; ++i) {\n        int x, y; cin >> x >> y;\n    }\n\n    // ------------------------------------------------------------\n    // 1. Edge betweenness centrality (weighted Brandes)\n    vector<ld> edge_betweenness(M, 0.0L);\n\n    for (int s = 0; s < N; ++s) {\n        vector<double> dist(N, INF);\n        vector<ld> sigma(N, 0.0L);\n        vector<vector<pair<int, int>>> pred(N); // (predecessor vertex, edge_id)\n\n        dist[s] = 0.0;\n        sigma[s] = 1.0;\n        priority_queue<pair<double, int>,\n                       vector<pair<double, int>>,\n                       greater<>> pq;\n        pq.push({0.0, s});\n\n        while (!pq.empty()) {\n            auto [d, v] = pq.top(); pq.pop();\n            if (d > dist[v]) continue;          // outdated entry\n            for (auto [to, info] : adj[v]) {\n                int eid = info.first;\n                long long w = info.second;\n                double nd = d + w;\n                if (nd < dist[to]) {\n                    dist[to] = nd;\n                    sigma[to] = sigma[v];\n                    pred[to].clear();\n                    pred[to].push_back({v, eid});\n                    pq.push({nd, to});\n                } else if (nd == dist[to]) {\n                    sigma[to] += sigma[v];\n                    pred[to].push_back({v, eid});\n                }\n            }\n        }\n\n        // order vertices by decreasing distance\n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(),\n             [&](int i, int j) { return dist[i] > dist[j]; });\n\n        vector<ld> delta(N, 0.0L);\n        for (int v : order) {\n            if (v == s) continue;\n            for (auto [u, eid] : pred[v]) {\n                ld coeff = sigma[u] / sigma[v];\n                edge_betweenness[eid] += coeff * (1.0L + delta[v]);\n                delta[u] += coeff * (1.0L + delta[v]);\n            }\n        }\n    }\n\n    // ------------------------------------------------------------\n    // 2. Normalise weights to [0,1]\n    ld max_ebc = 0.0L;\n    for (ld val : edge_betweenness)\n        if (val > max_ebc) max_ebc = val;\n    vector<ld> w_norm(M);\n    if (max_ebc == 0.0L) {\n        for (int i = 0; i < M; ++i) w_norm[i] = 1.0L;\n    } else {\n        for (int i = 0; i < M; ++i) w_norm[i] = edge_betweenness[i] / max_ebc;\n    }\n\n    // ------------------------------------------------------------\n    // 3. Precompute adjacency lists for edges (edges sharing a vertex)\n    vector<vector<int>> edge_adj(M);\n    for (int u = 0; u < N; ++u) {\n        const auto& list = adj[u];\n        for (size_t i = 0; i < list.size(); ++i) {\n            int e1 = list[i].second.first;\n            for (size_t j = i+1; j < list.size(); ++j) {\n                int e2 = list[j].second.first;\n                edge_adj[e1].push_back(e2);\n                edge_adj[e2].push_back(e1);\n            }\n        }\n    }\n\n    // ------------------------------------------------------------\n    // 4. Improved greedy initial assignment\n    const ld gamma = 100.0L;   // weight of adjacency term\n    vector<int> day_of(M, -1);\n    vector<int> cnt(D, 0);\n    vector<ld> sum_w(D, 0.0L);\n\n    // sort edges by weight descending\n    vector<int> order_edges(M);\n    iota(order_edges.begin(), order_edges.end(), 0);\n    sort(order_edges.begin(), order_edges.end(),\n         [&](int i, int j) { return w_norm[i] > w_norm[j]; });\n\n    for (int e : order_edges) {\n        int best_day = -1;\n        ld best_inc = INF;\n        for (int d = 0; d < D; ++d) {\n            if (cnt[d] >= K) continue;\n            // increase in sum_w^2\n            ld inc_sum = 2.0L * sum_w[d] * w_norm[e] + w_norm[e] * w_norm[e];\n            // increase in adjacency\n            int adj_inc = 0;\n            for (int nb : edge_adj[e]) {\n                if (day_of[nb] == d) ++adj_inc;\n            }\n            ld total_inc = inc_sum + gamma * adj_inc;\n            if (total_inc < best_inc) {\n                best_inc = total_inc;\n                best_day = d;\n            }\n        }\n        assert(best_day != -1);\n        day_of[e] = best_day;\n        cnt[best_day]++;\n        sum_w[best_day] += w_norm[e];\n    }\n\n    // ------------------------------------------------------------\n    // 5. Compute initial adjacency counts per day\n    vector<int> adj_count(D, 0);\n    for (int e = 0; e < M; ++e) {\n        int d = day_of[e];\n        for (int nb : edge_adj[e]) {\n            if (nb > e && day_of[nb] == d) {   // count each pair once\n                adj_count[d]++;\n            }\n        }\n    }\n\n    ld total_adj = 0.0L;\n    for (int d = 0; d < D; ++d) total_adj += adj_count[d];\n    ld total_sum_sq = 0.0L;\n    for (int d = 0; d < D; ++d) total_sum_sq += sum_w[d] * sum_w[d];\n    ld total_cost = total_sum_sq + gamma * total_adj;\n\n    // ------------------------------------------------------------\n    // 6. Simulated Annealing\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> edge_dist(0, M-1);\n    uniform_real_distribution<ld> real_dist(0.0L, 1.0L);\n\n    const int ITER = 4000000;\n    ld T = 10.0L;\n    const ld cooling = 0.999998L;   // after 4e6 steps T ~ 0.003\n\n    for (int iter = 0; iter < ITER; ++iter) {\n        int e = edge_dist(rng);\n        int f = edge_dist(rng);\n        if (e == f) continue;\n        int a = day_of[e];\n        int b = day_of[f];\n        if (a == b) continue;\n\n        ld we = w_norm[e];\n        ld wf = w_norm[f];\n        ld sum_a = sum_w[a];\n        ld sum_b = sum_w[b];\n        ld new_a = sum_a - we + wf;\n        ld new_b = sum_b - wf + we;\n\n        // change in sum of squares\n        ld old_contrib_sq = sum_a * sum_a + sum_b * sum_b;\n        ld new_contrib_sq = new_a * new_a + new_b * new_b;\n        ld delta_sq = new_contrib_sq - old_contrib_sq;\n\n        // change in adjacency counts\n        int delta_adj_a = 0, delta_adj_b = 0;\n\n        // day a: remove e, add f\n        int before_a = 0;\n        for (int nb : edge_adj[e]) {\n            if (day_of[nb] == a && nb != e) before_a++;\n        }\n        int after_a = 0;\n        for (int nb : edge_adj[f]) {\n            if (day_of[nb] == a && nb != e) after_a++;   // exclude e because it will be gone\n        }\n        delta_adj_a = after_a - before_a;\n\n        // day b: remove f, add e\n        int before_b = 0;\n        for (int nb : edge_adj[f]) {\n            if (day_of[nb] == b && nb != f) before_b++;\n        }\n        int after_b = 0;\n        for (int nb : edge_adj[e]) {\n            if (day_of[nb] == b && nb != f) after_b++;   // exclude f\n        }\n        delta_adj_b = after_b - before_b;\n\n        ld delta_adj = gamma * (delta_adj_a + delta_adj_b);\n        ld delta = delta_sq + delta_adj;\n\n        if (delta < 0 || exp(-delta / T) > real_dist(rng)) {\n            // perform swap\n            day_of[e] = b;\n            day_of[f] = a;\n            sum_w[a] = new_a;\n            sum_w[b] = new_b;\n            adj_count[a] += delta_adj_a;\n            adj_count[b] += delta_adj_b;\n            total_cost += delta;\n        }\n        T *= cooling;\n    }\n\n    // ------------------------------------------------------------\n    // 7. Output (convert to 1\u2011based days)\n    for (int i = 0; i < M; ++i)\n        cout << day_of[i] + 1 << \" \\n\"[i == M-1];\n\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAXD = 14;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    int D;\n    cin >> D;\n    vector<string> f1(D), r1(D), f2(D), r2(D);\n    for (int i = 0; i < D; ++i) cin >> f1[i];\n    for (int i = 0; i < D; ++i) cin >> r1[i];\n    for (int i = 0; i < D; ++i) cin >> f2[i];\n    for (int i = 0; i < D; ++i) cin >> r2[i];\n    \n    // Convert to boolean arrays for quick access\n    bool f1b[D][D] = {}, r1b[D][D] = {};\n    bool f2b[D][D] = {}, r2b[D][D] = {};\n    for (int z = 0; z < D; ++z) {\n        for (int x = 0; x < D; ++x) {\n            f1b[z][x] = (f1[z][x] == '1');\n            f2b[z][x] = (f2[z][x] == '1');\n        }\n        for (int y = 0; y < D; ++y) {\n            r1b[z][y] = (r1[z][y] == '1');\n            r2b[z][y] = (r2[z][y] == '1');\n        }\n    }\n    \n    // Allowed regions for each object\n    bool allowed1[D][D][D] = {};\n    bool allowed2[D][D][D] = {};\n    // Intersection I\n    bool I[D][D][D] = {};\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                allowed1[x][y][z] = f1b[z][x] && r1b[z][y];\n                allowed2[x][y][z] = f2b[z][x] && r2b[z][y];\n                I[x][y][z] = allowed1[x][y][z] && allowed2[x][y][z];\n            }\n        }\n    }\n    \n    // Connected components of I\n    int compI[D][D][D];\n    memset(compI, -1, sizeof(compI));\n    int num_components_I = 0;\n    const int dx[6] = {1,-1,0,0,0,0};\n    const int dy[6] = {0,0,1,-1,0,0};\n    const int dz[6] = {0,0,0,0,1,-1};\n    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 (I[x][y][z] && compI[x][y][z] == -1) {\n                    queue<tuple<int,int,int>> q;\n                    q.push({x, y, z});\n                    compI[x][y][z] = num_components_I;\n                    while (!q.empty()) {\n                        auto [cx, cy, cz] = q.front(); q.pop();\n                        for (int d = 0; d < 6; ++d) {\n                            int nx = cx + dx[d];\n                            int ny = cy + dy[d];\n                            int nz = cz + dz[d];\n                            if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D &&\n                                I[nx][ny][nz] && compI[nx][ny][nz] == -1) {\n                                compI[nx][ny][nz] = num_components_I;\n                                q.push({nx, ny, nz});\n                            }\n                        }\n                    }\n                    ++num_components_I;\n                }\n            }\n        }\n    }\n    \n    // Initialize objects with all cells from I (shared)\n    bool obj1[D][D][D] = {};\n    bool obj2[D][D][D] = {};\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 (I[x][y][z]) {\n                    obj1[x][y][z] = true;\n                    obj2[x][y][z] = true;\n                }\n    \n    // For each object, add minimal extra cells to satisfy silhouettes\n    for (int obj_id = 0; obj_id < 2; ++obj_id) {\n        bool (*obj)[D][D] = (obj_id == 0) ? obj1 : obj2;\n        bool (*fb)[D] = (obj_id == 0) ? f1b : f2b;\n        bool (*rb)[D] = (obj_id == 0) ? r1b : r2b;\n        for (int z = 0; z < D; ++z) {\n            // Lists of required x and y\n            vector<int> X, Y;\n            for (int x = 0; x < D; ++x) if (fb[z][x]) X.push_back(x);\n            for (int y = 0; y < D; ++y) if (rb[z][y]) Y.push_back(y);\n            \n            // Determine which x and y are already covered by I\n            vector<bool> x_covered(D, false), y_covered(D, false);\n            for (int x : X) {\n                for (int y = 0; y < D; ++y) {\n                    if (I[x][y][z]) {\n                        x_covered[x] = true;\n                        break;\n                    }\n                }\n            }\n            for (int y : Y) {\n                for (int x = 0; x < D; ++x) {\n                    if (I[x][y][z]) {\n                        y_covered[y] = true;\n                        break;\n                    }\n                }\n            }\n            \n            vector<int> X_rem, Y_rem;\n            for (int x : X) if (!x_covered[x]) X_rem.push_back(x);\n            for (int y : Y) if (!y_covered[y]) Y_rem.push_back(y);\n            \n            int a = X_rem.size(), b = Y_rem.size();\n            int M = max(a, b);\n            // Add cells to cover remaining requirements\n            if (a >= b) {\n                for (int i = 0; i < b; ++i) {\n                    int x = X_rem[i], y = Y_rem[i];\n                    obj[x][y][z] = true;\n                }\n                for (int i = b; i < a; ++i) {\n                    int x = X_rem[i];\n                    int y = Y.empty() ? 0 : Y[0]; // Y non\u2011empty because silhouette guarantees at least one y\n                    obj[x][y][z] = true;\n                }\n            } else {\n                for (int i = 0; i < a; ++i) {\n                    int x = X_rem[i], y = Y_rem[i];\n                    obj[x][y][z] = true;\n                }\n                for (int i = a; i < b; ++i) {\n                    int y = Y_rem[i];\n                    int x = X.empty() ? 0 : X[0];\n                    obj[x][y][z] = true;\n                }\n            }\n        }\n    }\n    \n    // Shared blocks are exactly the connected components of I\n    // Assign IDs to shared components\n    vector<int> comp_id(num_components_I);\n    int cur_id = 1;\n    for (int i = 0; i < num_components_I; ++i) comp_id[i] = cur_id++;\n    \n    // Prepare output arrays\n    vector<vector<vector<int>>> b1(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    vector<vector<vector<int>>> b2(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    \n    // Fill shared blocks in both objects\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 (I[x][y][z]) {\n                    int id = comp_id[compI[x][y][z]];\n                    b1[x][y][z] = id;\n                    b2[x][y][z] = id;\n                }\n    \n    // Unit blocks for non\u2011shared cells in obj1\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 (obj1[x][y][z] && !I[x][y][z])\n                    b1[x][y][z] = cur_id++;\n    \n    // Unit blocks for non\u2011shared cells in obj2\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 (obj2[x][y][z] && !I[x][y][z])\n                    b2[x][y][z] = cur_id++;\n    \n    // Output\n    int total_blocks = cur_id - 1;\n    cout << total_blocks << \"\\n\";\n    // b1\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                cout << b1[x][y][z];\n                if (x == D-1 && y == D-1 && z == D-1) cout << \"\\n\";\n                else cout << \" \";\n            }\n    // b2\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                cout << b2[x][y][z];\n                if (x == D-1 && y == D-1 && z == D-1) cout << \"\\n\";\n                else cout << \" \";\n            }\n    \n    return 0;\n}","ahc020":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <climits>\n#include <numeric>\n\nusing namespace std;\ntypedef long long ll;\n\nstruct Candidate {\n    int type;      // 0: active vertex, 1: inactive vertex\n    int idx;       // vertex index\n    int new_P;     // new output strength\n    ll cost;       // total cost of the action\n    int count;     // number of newly covered residents\n    int first_idx; // first index in sorted_res[idx] to cover\n    int last_idx;  // last index (exclusive) in sorted_res[idx] to cover\n};\n\n// integer ceil(sqrt(x))\nint ceil_sqrt(ll x) {\n    int r = sqrt(x);\n    while ((ll)r * r < x) ++r;\n    return r;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\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\n    vector<int> u(M), v(M), w(M);\n    vector<vector<pair<int, int>>> adj(N); // (neighbor, edge index)\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]].emplace_back(v[j], j);\n        adj[v[j]].emplace_back(u[j], j);\n    }\n\n    vector<int> a(K), b(K);\n    for (int k = 0; k < K; ++k) cin >> a[k] >> b[k];\n\n    // squared distances from vertices to residents\n    vector<vector<ll>> dist2(N, vector<ll>(K));\n    for (int i = 0; i < N; ++i) {\n        for (int k = 0; k < K; ++k) {\n            ll dx = x[i] - a[k];\n            ll dy = y[i] - b[k];\n            dist2[i][k] = dx * dx + dy * dy;\n        }\n    }\n\n    // for each vertex, residents sorted by distance\n    vector<vector<int>> sorted_res(N);\n    for (int i = 0; i < N; ++i) {\n        sorted_res[i].resize(K);\n        iota(sorted_res[i].begin(), sorted_res[i].end(), 0);\n        sort(sorted_res[i].begin(), sorted_res[i].end(),\n             [&](int k1, int k2) { return dist2[i][k1] < dist2[i][k2]; });\n    }\n\n    // state\n    vector<bool> covered(K, false);\n    int covered_cnt = 0;\n    vector<int> P(N, 0);\n    vector<int> next_uncovered(N, 0); // for active vertices\n    vector<bool> is_vertex_active(N, false);\n    is_vertex_active[0] = true; // station 1 (index 0)\n    vector<bool> is_edge_on(M, false);\n\n    // main loop\n    while (covered_cnt < K) {\n        // Dijkstra to compute additional connection costs\n        vector<ll> dist_conn(N, LLONG_MAX);\n        vector<int> prev_vertex(N, -1), prev_edge(N, -1);\n        priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<>> pq;\n        for (int i = 0; i < N; ++i) {\n            if (is_vertex_active[i]) {\n                dist_conn[i] = 0;\n                pq.emplace(0, i);\n            }\n        }\n        while (!pq.empty()) {\n            auto [d, u_idx] = pq.top(); pq.pop();\n            if (d != dist_conn[u_idx]) continue;\n            for (auto [v_idx, e_idx] : adj[u_idx]) {\n                ll cost = is_edge_on[e_idx] ? 0 : w[e_idx];\n                if (dist_conn[u_idx] + cost < dist_conn[v_idx]) {\n                    dist_conn[v_idx] = dist_conn[u_idx] + cost;\n                    prev_vertex[v_idx] = u_idx;\n                    prev_edge[v_idx] = e_idx;\n                    pq.emplace(dist_conn[v_idx], v_idx);\n                }\n            }\n        }\n\n        // evaluate all possible actions\n        Candidate best;\n        bool found = false;\n\n        // actions on active vertices\n        for (int i = 0; i < N; ++i) {\n            if (!is_vertex_active[i]) continue;\n            // move to first uncovered resident\n            while (next_uncovered[i] < K && covered[sorted_res[i][next_uncovered[i]]])\n                ++next_uncovered[i];\n            if (next_uncovered[i] == K) continue;\n\n            int first = next_uncovered[i];\n            int k = sorted_res[i][first];\n            ll d2 = dist2[i][k];\n            int new_P = ceil_sqrt(d2);\n            if (new_P > 5000) continue;\n            ll new_P2 = (ll)new_P * new_P;\n            ll old_P2 = (ll)P[i] * P[i];\n\n            // count newly covered residents\n            int cnt = 0;\n            int last = first;\n            for (int j = first; j < K; ++j) {\n                int res = sorted_res[i][j];\n                if (dist2[i][res] > new_P2) break;\n                if (!covered[res]) ++cnt;\n                last = j + 1;\n            }\n            if (cnt == 0) continue;\n\n            ll cost_inc = new_P2 - old_P2;\n            if (!found || (ll)cost_inc * best.count < (ll)best.cost * cnt) {\n                best = {0, i, new_P, cost_inc, cnt, first, last};\n                found = true;\n            }\n        }\n\n        // actions on inactive vertices\n        for (int i = 0; i < N; ++i) {\n            if (is_vertex_active[i]) continue;\n            if (dist_conn[i] == LLONG_MAX) continue; // should not happen\n\n            // first uncovered resident\n            int first = 0;\n            while (first < K && covered[sorted_res[i][first]]) ++first;\n            if (first == K) continue;\n\n            int k = sorted_res[i][first];\n            ll d2 = dist2[i][k];\n            int new_P = ceil_sqrt(d2);\n            if (new_P > 5000) continue;\n            ll new_P2 = (ll)new_P * new_P;\n\n            int cnt = 0;\n            int last = first;\n            for (int j = first; j < K; ++j) {\n                int res = sorted_res[i][j];\n                if (dist2[i][res] > new_P2) break;\n                if (!covered[res]) ++cnt;\n                last = j + 1;\n            }\n            if (cnt == 0) continue;\n\n            ll total_cost = dist_conn[i] + new_P2;\n            if (!found || (ll)total_cost * best.count < (ll)best.cost * cnt) {\n                best = {1, i, new_P, total_cost, cnt, first, last};\n                found = true;\n            }\n        }\n\n        if (!found) break; // should not happen\n\n        // apply the best action\n        if (best.type == 0) { // active vertex\n            int i = best.idx;\n            P[i] = best.new_P;\n            for (int j = best.first_idx; j < best.last_idx; ++j) {\n                int res = sorted_res[i][j];\n                if (!covered[res]) {\n                    covered[res] = true;\n                    ++covered_cnt;\n                }\n            }\n            next_uncovered[i] = best.last_idx;\n        } else { // inactive vertex\n            int j = best.idx;\n            // turn on edges along the shortest path\n            int cur = j;\n            while (!is_vertex_active[cur]) {\n                int e = prev_edge[cur];\n                if (!is_edge_on[e]) is_edge_on[e] = true;\n                int prev = prev_vertex[cur];\n                is_vertex_active[cur] = true;\n                next_uncovered[cur] = 0; // newly activated, P=0 initially\n                P[cur] = 0;\n                cur = prev;\n            }\n            P[j] = best.new_P;\n            for (int idx = best.first_idx; idx < best.last_idx; ++idx) {\n                int res = sorted_res[j][idx];\n                if (!covered[res]) {\n                    covered[res] = true;\n                    ++covered_cnt;\n                }\n            }\n            next_uncovered[j] = best.last_idx;\n        }\n    }\n\n    // output\n    for (int i = 0; i < N; ++i) {\n        cout << P[i] << (i + 1 == N ? \"\\n\" : \" \");\n    }\n    for (int j = 0; j < M; ++j) {\n        cout << (is_edge_on[j] ? 1 : 0) << (j + 1 == M ? \"\\n\" : \" \");\n    }\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30; // fixed pyramid size\n\nint main() {\n    // read input\n    vector<vector<int>> a(N);\n    for (int x = 0; x < N; ++x) {\n        a[x].resize(x + 1);\n        for (int y = 0; y <= x; ++y) {\n            cin >> a[x][y];\n        }\n    }\n\n    vector<array<int, 4>> ops; // stores swaps (x1,y1,x2,y2)\n\n    // swap two adjacent balls and record the operation\n    auto do_swap = [&](int x1, int y1, int x2, int y2) {\n        swap(a[x1][y1], a[x2][y2]);\n        ops.push_back({x1, y1, x2, y2});\n    };\n\n    // sift down a value starting from (x,y) until heap property holds\n    auto sift = [&](int x, int y) {\n        while (x < N - 1) { // while not a leaf\n            int x_left = x + 1, y_left = y;      // left child\n            int x_right = x + 1, y_right = y + 1; // right child\n            // choose the child with the smaller value\n            int nx, ny;\n            if (a[x_left][y_left] <= a[x_right][y_right]) {\n                nx = x_left; ny = y_left;\n            } else {\n                nx = x_right; ny = y_right;\n            }\n            if (a[x][y] > a[nx][ny]) {\n                do_swap(x, y, nx, ny);\n                x = nx; y = ny; // continue sifting with the moved value\n            } else {\n                break;\n            }\n        }\n    };\n\n    // process rows from bottom to top\n    for (int x = N - 2; x >= 0; --x) {\n        // collect nodes in this row and sort by value descending\n        vector<pair<int, int>> nodes;\n        for (int y = 0; y <= x; ++y) {\n            nodes.emplace_back(a[x][y], y);\n        }\n        sort(nodes.begin(), nodes.end(), greater<pair<int, int>>());\n        // sift each node in that order\n        for (auto& p : nodes) {\n            sift(x, p.second);\n        }\n    }\n\n    // output\n    cout << ops.size() << '\\n';\n    for (auto& sw : ops) {\n        cout << sw[0] << ' ' << sw[1] << ' ' << sw[2] << ' ' << sw[3] << '\\n';\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int D = 9;  // Grid size is fixed at 9\nint entrance_r = 0, entrance_c = (D - 1) / 2;  // (0,4)\n\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\n\nbool obstacle[D][D] = {false};\nbool occupied[D][D] = {false};\nint container_num[D][D];       // -1 if no container\n\nint dist[D][D];                // BFS distance from entrance\nint cell_rank[D][D];           // index in the sorted order (0..M-1)\nvector<pair<int, int>> order;  // free squares sorted by (dist, row, col)\nint M;                         // number of containers\n\n// ---------- preprocessing ----------\nvoid compute_bfs_distances() {\n    for (int i = 0; i < D; ++i)\n        for (int j = 0; j < D; ++j)\n            dist[i][j] = -1;\n\n    queue<pair<int, int>> q;\n    dist[entrance_r][entrance_c] = 0;\n    q.push({entrance_r, entrance_c});\n\n    while (!q.empty()) {\n        auto [r, c] = q.front(); q.pop();\n        for (int d = 0; d < 4; ++d) {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n            if (obstacle[nr][nc]) continue;\n            if (dist[nr][nc] == -1) {\n                dist[nr][nc] = dist[r][c] + 1;\n                q.push({nr, nc});\n            }\n        }\n    }\n}\n\nvoid build_order() {\n    order.clear();\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            if (i == entrance_r && j == entrance_c) continue;\n            if (obstacle[i][j]) continue;\n            order.push_back({i, j});\n        }\n    }\n    sort(order.begin(), order.end(),\n         [](const auto& a, const auto& b) {\n             int da = dist[a.first][a.second];\n             int db = dist[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    M = order.size();\n    for (int i = 0; i < D; ++i)\n        for (int j = 0; j < D; ++j)\n            cell_rank[i][j] = -1;\n    for (int i = 0; i < M; ++i) {\n        auto [r, c] = order[i];\n        cell_rank[r][c] = i;\n    }\n}\n\n// ---------- helper for articulation test ----------\n// temporarily block (br,bc) and count reachable empty squares from entrance\nint count_reachable_without(int br, int bc, bool is_empty[D][D]) {\n    bool original = is_empty[br][bc];\n    is_empty[br][bc] = false;          // block the square\n\n    bool visited[D][D] = {false};\n    int cnt = 0;\n    queue<pair<int, int>> q;\n    q.push({entrance_r, entrance_c});\n    visited[entrance_r][entrance_c] = true;\n    ++cnt;\n\n    while (!q.empty()) {\n        auto [r, c] = q.front(); q.pop();\n        for (int d = 0; d < 4; ++d) {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n            if (!is_empty[nr][nc]) continue;\n            if (!visited[nr][nc]) {\n                visited[nr][nc] = true;\n                q.push({nr, nc});\n                ++cnt;\n            }\n        }\n    }\n\n    is_empty[br][bc] = original;       // restore\n    return cnt;\n}\n\n// ---------- main ----------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    int input_D;  // We'll read D but ignore it since it's always 9\n    cin >> input_D >> N;\n\n    // read obstacles\n    for (int i = 0; i < N; ++i) {\n        int r, c;\n        cin >> r >> c;\n        obstacle[r][c] = true;\n    }\n\n    // preprocessing\n    compute_bfs_distances();\n    build_order();\n\n    // initialise container numbers\n    for (int i = 0; i < D; ++i)\n        for (int j = 0; j < D; ++j)\n            container_num[i][j] = -1;\n\n    // ---------- placement phase ----------\n    for (int step = 0; step < M; ++step) {\n        int t;\n        cin >> t;\n\n        // build current empty mask (entrance + all non\u2011occupied, non\u2011obstacle)\n        bool is_empty[D][D] = {false};\n        for (int i = 0; i < D; ++i)\n            for (int j = 0; j < D; ++j) {\n                if (obstacle[i][j]) is_empty[i][j] = false;\n                else if (occupied[i][j]) is_empty[i][j] = false;\n                else is_empty[i][j] = true;      // includes entrance\n            }\n\n        // collect all reachable empty squares (except entrance)\n        vector<pair<int, int>> reachable;\n        bool visited[D][D] = {false};\n        queue<pair<int, int>> q;\n        q.push({entrance_r, entrance_c});\n        visited[entrance_r][entrance_c] = true;\n\n        while (!q.empty()) {\n            auto [r, c] = q.front(); q.pop();\n            if (!(r == entrance_r && c == entrance_c))\n                reachable.push_back({r, c});\n            for (int d = 0; d < 4; ++d) {\n                int nr = r + dr[d], nc = c + dc[d];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (!is_empty[nr][nc]) continue;\n                if (!visited[nr][nc]) {\n                    visited[nr][nc] = true;\n                    q.push({nr, nc});\n                }\n            }\n        }\n\n        // among reachable squares, keep only those that are not articulation points\n        vector<pair<int, int>> safe;\n        int total_empty = reachable.size() + 1;   // +1 for entrance\n        for (auto& s : reachable) {\n            int r = s.first, c = s.second;\n            int cnt = count_reachable_without(r, c, is_empty);\n            if (cnt == total_empty - 1)          // graph stays connected\n                safe.push_back(s);\n        }\n\n        // choose a square\n        pair<int, int> chosen;\n        if (!safe.empty()) {\n            // pick the safe square whose rank is closest to t\n            int best_diff = 1e9, best_dist = 1e9;\n            for (auto& s : safe) {\n                int r = s.first, c = s.second;\n                int rnk = cell_rank[r][c];\n                int diff = abs(rnk - t);\n                int d = dist[r][c];\n                if (diff < best_diff || (diff == best_diff && d < best_dist)) {\n                    best_diff = diff;\n                    best_dist = d;\n                    chosen = s;\n                }\n            }\n        } else {\n            // fallback \u2013 should never happen, but choose the closest reachable square\n            int best_dist = 1e9;\n            for (auto& s : reachable) {\n                int d = dist[s.first][s.second];\n                if (d < best_dist) {\n                    best_dist = d;\n                    chosen = s;\n                }\n            }\n        }\n\n        // output placement\n        cout << chosen.first << \" \" << chosen.second << endl;\n\n        // update state\n        occupied[chosen.first][chosen.second] = true;\n        container_num[chosen.first][chosen.second] = t;\n    }\n\n    // ---------- retrieval phase ----------\n    int remaining = M;\n    while (remaining > 0) {\n        // rebuild empty mask\n        bool is_empty[D][D] = {false};\n        for (int i = 0; i < D; ++i)\n            for (int j = 0; j < D; ++j) {\n                if (obstacle[i][j]) is_empty[i][j] = false;\n                else if (occupied[i][j]) is_empty[i][j] = false;\n                else is_empty[i][j] = true;\n            }\n\n        // find all containers adjacent to an empty square\n        vector<pair<int, int>> accessible;\n        for (int i = 0; i < D; ++i) {\n            for (int j = 0; j < D; ++j) {\n                if (!occupied[i][j]) continue;\n                bool adj = false;\n                for (int d = 0; d < 4; ++d) {\n                    int ni = i + dr[d], nj = j + dc[d];\n                    if (ni < 0 || ni >= D || nj < 0 || nj >= D) continue;\n                    if (is_empty[ni][nj]) {\n                        adj = true;\n                        break;\n                    }\n                }\n                if (adj) accessible.push_back({i, j});\n            }\n        }\n\n        // choose the one with the smallest number\n        auto best = accessible[0];\n        int best_num = container_num[best.first][best.second];\n        for (auto& p : accessible) {\n            int num = container_num[p.first][p.second];\n            if (num < best_num) {\n                best_num = num;\n                best = p;\n            }\n        }\n\n        // output retrieval\n        cout << best.first << \" \" << best.second << endl;\n\n        // remove it\n        occupied[best.first][best.second] = false;\n        container_num[best.first][best.second] = -1;\n        --remaining;\n    }\n\n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <utility>\n#include <algorithm>\nusing namespace std;\n\nconst int MAXN = 50;\nconst int MAXM = 100;\n\nint n, m;\nint cur[MAXN][MAXN];\nint colorCount[MAXM+1] = {0};          // 0..100\nint edgeCount[MAXM+1][MAXM+1] = {0};   // only upper triangular used\nbool required[MAXM+1][MAXM+1] = {false};\nbool allowed[MAXM+1] = {false};        // colors that may touch 0\n\nconst int dx[4] = {1, -1, 0, 0};\nconst int dy[4] = {0, 0, 1, -1};\n\n// Check if we can safely recolor (i,j) to 0\nbool isRemovable(int i, int j) {\n    int c = cur[i][j];\n    if (c == 0) return false;\n    if (!allowed[c]) return false;\n    if (colorCount[c] <= 1) return false;\n\n    int cnt[MAXM+1] = {0};   // count of neighbor colors (0..m)\n    bool adj_to_0 = false;\n    int same_color_neighbors = 0;\n\n    // examine four neighbours (outside counts as color 0)\n    for (int d = 0; d < 4; ++d) {\n        int ni = i + dx[d], nj = j + dy[d];\n        int col;\n        if (ni >= 0 && ni < n && nj >= 0 && nj < n)\n            col = cur[ni][nj];\n        else\n            col = 0;   // outside\n        cnt[col]++;\n        if (col == 0) adj_to_0 = true;\n        else if (!allowed[col]) return false;   // would create forbidden 0\u2013col adjacency\n        if (col == c) same_color_neighbors++;\n    }\n    if (!adj_to_0) return false;\n\n    // Edge count constraints\n    for (int d = 0; d <= m; ++d) {\n        if (cnt[d] == 0 || d == c) continue;\n        if (d == 0) {\n            // need at least one edge between c and 0 after removal\n            if (edgeCount[0][c] - cnt[0] < 1) return false;\n        } else {\n            int a = min(c, d), b = max(c, d);\n            if (required[a][b] && edgeCount[a][b] - cnt[d] < 1) return false;\n        }\n    }\n\n    // Connectivity of color c after removal\n    if (same_color_neighbors == 0) return false;   // should not happen\n    if (same_color_neighbors == 1) return true;    // leaf \u2013 safe\n\n    // BFS on color c, excluding (i,j)\n    int start_i = -1, start_j = -1;\n    for (int d = 0; d < 4; ++d) {\n        int ni = i + dx[d], nj = j + dy[d];\n        if (ni >= 0 && ni < n && nj >= 0 && nj < n && cur[ni][nj] == c) {\n            start_i = ni; start_j = nj; break;\n        }\n    }\n    if (start_i == -1) return false;   // no neighbour of same colour \u2013 impossible\n\n    bool visited[MAXN][MAXN] = {false};\n    queue<pair<int,int>> q;\n    visited[start_i][start_j] = true;\n    q.push({start_i, start_j});\n    int count = 0;\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        count++;\n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (nx >= 0 && nx < n && ny >= 0 && ny < n && !visited[nx][ny] &&\n                cur[nx][ny] == c && !(nx == i && ny == j)) {\n                visited[nx][ny] = true;\n                q.push({nx, ny});\n            }\n        }\n    }\n    return (count == colorCount[c] - 1);\n}\n\n// Actually recolor (i,j) from its colour c to 0\nvoid removeCell(int i, int j) {\n    int c = cur[i][j];\n    // Update edge counts for all incident edges\n    for (int d = 0; d < 4; ++d) {\n        int ni = i + dx[d], nj = j + dy[d];\n        int col;\n        if (ni >= 0 && ni < n && nj >= 0 && nj < n)\n            col = cur[ni][nj];\n        else\n            col = 0;   // outside\n        if (col == c) continue;   // no edge between same colours\n        // Remove edge c\u2013col\n        if (col == 0) {\n            edgeCount[0][c]--;\n        } else {\n            int a = min(c, col), b = max(c, col);\n            edgeCount[a][b]--;\n        }\n        // After recoloring, add edge 0\u2013col (if col != 0)\n        if (col != 0) {\n            edgeCount[0][col]++;\n        }\n    }\n    // Perform the recolor\n    cur[i][j] = 0;\n    colorCount[c]--;\n    colorCount[0]++;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n >> m;\n    for (int i = 0; i < n; ++i)\n        for (int j = 0; j < n; ++j) {\n            cin >> cur[i][j];\n            colorCount[cur[i][j]]++;\n        }\n\n    // Determine which colours are allowed to touch 0 (i.e. appear on the boundary)\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (i == 0 || i == n-1 || j == 0 || j == n-1)\n                allowed[cur[i][j]] = true;\n        }\n    }\n\n    // Build required adjacency matrix\n    // First, adjacency to outside (0)\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (i == 0 || i == n-1 || j == 0 || j == n-1) {\n                int c = cur[i][j];\n                required[0][c] = true;   // 0 < c, so store as [0][c]\n            }\n        }\n    }\n    // Then, adjacencies between colours >0\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c = cur[i][j];\n            if (i+1 < n) {\n                int d = cur[i+1][j];\n                if (c != d) {\n                    int a = min(c,d), b = max(c,d);\n                    required[a][b] = true;\n                }\n            }\n            if (j+1 < n) {\n                int d = cur[i][j+1];\n                if (c != d) {\n                    int a = min(c,d), b = max(c,d);\n                    required[a][b] = true;\n                }\n            }\n        }\n    }\n\n    // Compute initial edge counts\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c = cur[i][j];\n            // down\n            if (i+1 < n) {\n                int d = cur[i+1][j];\n                if (c != d) {\n                    int a = min(c,d), b = max(c,d);\n                    edgeCount[a][b]++;\n                }\n            }\n            // right\n            if (j+1 < n) {\n                int d = cur[i][j+1];\n                if (c != d) {\n                    int a = min(c,d), b = max(c,d);\n                    edgeCount[a][b]++;\n                }\n            }\n            // outside sides\n            if (i == 0) edgeCount[0][c]++;\n            if (i == n-1) edgeCount[0][c]++;\n            if (j == 0) edgeCount[0][c]++;\n            if (j == n-1) edgeCount[0][c]++;\n        }\n    }\n\n    // Erosion: repeatedly turn removable cells into 0\n    bool changed;\n    do {\n        changed = false;\n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                if (cur[i][j] == 0) continue;\n                if (isRemovable(i, j)) {\n                    removeCell(i, j);\n                    changed = true;\n                }\n            }\n        }\n    } while (changed);\n\n    // Output the final map\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (j) cout << ' ';\n            cout << cur[i][j];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, D, Q;\nvector<vector<int>> cmp;   // -2 unknown, -1: <, 0: =, 1: >\nint queries_used = 0;\n\n// Compare items i and j\nint compare_items(int i, int j) {\n    if (i == j) return 0;\n    if (cmp[i][j] != -2) return cmp[i][j];\n    cout << \"1 1 \" << i << \" \" << j << endl;\n    cout.flush();\n    string res;\n    cin >> res;\n    ++queries_used;\n    int ans;\n    if (res == \"<\") ans = -1;\n    else if (res == \">\") ans = 1;\n    else ans = 0;\n    cmp[i][j] = ans;\n    cmp[j][i] = -ans;\n    return ans;\n}\n\n// Compare two groups by total weight\nint compare_groups(const vector<int>& A, const vector<int>& B) {\n    if (A.empty() || B.empty()) return 0;\n    cout << A.size() << \" \" << B.size();\n    for (int x : A) cout << \" \" << x;\n    for (int x : B) cout << \" \" << x;\n    cout << endl;\n    cout.flush();\n    string res;\n    cin >> res;\n    ++queries_used;\n    if (res == \"<\") return -1;\n    else if (res == \">\") return 1;\n    else return 0;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cout.tie(nullptr);\n\n    cin >> N >> D >> Q;\n    cmp.assign(N, vector<int>(N, -2));\n\n    // Decide allocation of queries\n    int sort_queries_budget = Q;\n    bool use_group_comparisons = (Q >= N * D);\n    if (use_group_comparisons) {\n        sort_queries_budget = max(0, Q - (N * D));  // Reserve queries for assignment\n    }\n\n    // Random order for sorting\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    mt19937 rng(123456);\n    shuffle(order.begin(), order.end(), rng);\n\n    // ---------- Phase 1: Sort items ----------\n    vector<int> sorted;\n    sorted.reserve(N);\n    for (int idx : order) {\n        if (queries_used >= sort_queries_budget) break;\n        int m = sorted.size();\n        int need = (m == 0) ? 0 : (32 - __builtin_clz(m)); // ceil(log2(m+1))\n        if (queries_used + need > sort_queries_budget) break;\n        \n        // Binary search insertion\n        int lo = 0, hi = m;\n        while (lo < hi) {\n            int mid = (lo + hi) / 2;\n            int res = compare_items(idx, sorted[mid]);\n            if (res < 0) hi = mid;\n            else lo = mid + 1;\n        }\n        sorted.insert(sorted.begin() + lo, idx);\n    }\n\n    // Add unsorted items\n    vector<bool> used(N, false);\n    for (int x : sorted) used[x] = true;\n    vector<int> unsorted;\n    for (int i = 0; i < N; ++i)\n        if (!used[i]) unsorted.push_back(i);\n    sorted.insert(sorted.end(), unsorted.begin(), unsorted.end());\n\n    // ---------- Phase 2: Assign to groups ----------\n    vector<vector<int>> groups(D);\n    \n    // Seed groups with D heaviest items\n    for (int i = 0; i < D && i < (int)sorted.size(); ++i) {\n        int item = sorted[sorted.size() - 1 - i]; // heaviest first\n        groups[i].push_back(item);\n    }\n\n    // Assign remaining items\n    if (use_group_comparisons) {\n        // Use LPT with group comparisons\n        for (int i = D; i < (int)sorted.size(); ++i) {\n            if (queries_used >= Q) break;\n            int item = sorted[sorted.size() - 1 - i];\n            \n            // Find lightest group\n            int lightest = 0;\n            for (int g = 1; g < D; ++g) {\n                if (queries_used >= Q) break;\n                int res = compare_groups(groups[lightest], groups[g]);\n                if (res > 0) { // current lightest is heavier\n                    lightest = g;\n                }\n            }\n            groups[lightest].push_back(item);\n        }\n    } else {\n        // Fallback: round-robin assignment\n        for (int i = D; i < (int)sorted.size(); ++i) {\n            int item = sorted[sorted.size() - 1 - i];\n            groups[i % D].push_back(item);\n        }\n    }\n\n    // ---------- Phase 3: Output assignment ----------\n    vector<int> ans(N);\n    for (int g = 0; g < D; ++g) {\n        for (int item : groups[g]) {\n            ans[item] = g;\n        }\n    }\n\n    // Dummy queries if needed\n    while (queries_used < Q) {\n        cout << \"1 1 0 1\" << endl;\n        cout.flush();\n        string dummy;\n        cin >> dummy;\n        ++queries_used;\n    }\n\n    // Output final division\n    for (int i = 0; i < N; ++i) {\n        cout << ans[i];\n        if (i < N - 1) cout << \" \";\n    }\n    cout << endl;\n    cout.flush();\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int n, m;\n    cin >> n >> m;\n    int k = n / m;\n    vector<vector<int>> stacks(m);\n    for (int i = 0; i < m; ++i) {\n        stacks[i].resize(k);\n        for (int j = 0; j < k; ++j) {\n            cin >> stacks[i][j];\n        }\n    }\n\n    vector<pair<int, int>> ops;\n\n    for (int v = 1; v <= n; ++v) {\n        // locate box v\n        int cur = -1, pos = -1;\n        for (int i = 0; i < m; ++i) {\n            for (int j = 0; j < (int)stacks[i].size(); ++j) {\n                if (stacks[i][j] == v) {\n                    cur = i;\n                    pos = j;\n                    break;\n                }\n            }\n            if (cur != -1) break;\n        }\n\n        // v is on top -> extract directly\n        if (pos == (int)stacks[cur].size() - 1) {\n            ops.emplace_back(v, 0);\n            stacks[cur].pop_back();\n        } else {\n            // move the block above v\n            int w = stacks[cur][pos + 1];   // box directly above v\n            \n            // Find maximum value in the block\n            int max_in_block = -1;\n            for (int j = pos + 1; j < (int)stacks[cur].size(); ++j) {\n                max_in_block = max(max_in_block, stacks[cur][j]);\n            }\n            \n            // choose destination stack with improved strategy\n            int dest = -1;\n            // first prefer an empty stack\n            for (int i = 0; i < m; ++i) {\n                if (i != cur && stacks[i].empty()) {\n                    dest = i;\n                    break;\n                }\n            }\n            \n            if (dest == -1) {\n                // Look for stacks where top > max_in_block\n                // Among these, choose the one with smallest top\n                int best_top = INT_MAX;\n                for (int i = 0; i < m; ++i) {\n                    if (i == cur || stacks[i].empty()) continue;\n                    int top_val = stacks[i].back();\n                    if (top_val > max_in_block && top_val < best_top) {\n                        best_top = top_val;\n                        dest = i;\n                    }\n                }\n                \n                // If no such stack, choose stack with largest top\n                if (dest == -1) {\n                    int max_top = -1;\n                    for (int i = 0; i < m; ++i) {\n                        if (i == cur) continue;\n                        if (!stacks[i].empty()) {\n                            int top_val = stacks[i].back();\n                            if (top_val > max_top) {\n                                max_top = top_val;\n                                dest = i;\n                            }\n                        }\n                    }\n                }\n            }\n\n            // perform the move\n            ops.emplace_back(w, dest + 1);\n            // extract the block from cur\n            vector<int> moved(stacks[cur].begin() + pos + 1, stacks[cur].end());\n            stacks[cur].erase(stacks[cur].begin() + pos + 1, stacks[cur].end());\n            // append to destination\n            stacks[dest].insert(stacks[dest].end(), moved.begin(), moved.end());\n\n            // now v is on top -> extract it\n            ops.emplace_back(v, 0);\n            stacks[cur].pop_back();\n        }\n    }\n\n    // output the operation sequence\n    for (auto& p : ops) {\n        cout << p.first << \" \" << p.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAX_MOVES = 100000;\n\n// directions: up, down, left, right\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\nconst char move_char[] = {'U', 'D', 'L', 'R'};\nconst char opposite_char[] = {'D', 'U', 'R', 'L'};\n\nint N;\nvector<string> h, v;\nvector<vector<int>> d;\n\n// adjacency list: for each cell (i,j) list of (ni,nj,move_char)\nvector<vector<vector<tuple<int,int,char>>>> adj;\n\n// for DFS\nvector<vector<bool>> visited;\nvector<int> next_neighbor_idx; // index of next neighbor to try for each cell (flattened)\n\n// distances to (0,0)\nvector<vector<int>> dist0;\n\nchar get_opposite(char c) {\n    for (int k = 0; k < 4; ++k)\n        if (move_char[k] == c) return opposite_char[k];\n    return '?';\n}\n\nvoid build_graph() {\n    adj.assign(N, vector<vector<tuple<int,int,char>>>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            // down\n            if (i+1 < N && h[i][j] == '0')\n                adj[i][j].emplace_back(i+1, j, 'D');\n            // up\n            if (i-1 >= 0 && h[i-1][j] == '0')\n                adj[i][j].emplace_back(i-1, j, 'U');\n            // right\n            if (j+1 < N && v[i][j] == '0')\n                adj[i][j].emplace_back(i, j+1, 'R');\n            // left\n            if (j-1 >= 0 && v[i][j-1] == '0')\n                adj[i][j].emplace_back(i, j-1, 'L');\n        }\n    }\n}\n\nvoid compute_dist0() {\n    dist0.assign(N, vector<int>(N, -1));\n    queue<pair<int,int>> q;\n    q.emplace(0, 0);\n    dist0[0][0] = 0;\n    while (!q.empty()) {\n        auto [i,j] = q.front(); q.pop();\n        for (auto [ni, nj, move] : adj[i][j]) {\n            if (dist0[ni][nj] == -1) {\n                dist0[ni][nj] = dist0[i][j] + 1;\n                q.emplace(ni, nj);\n            }\n        }\n    }\n}\n\n// returns the base route (DFS) and updates last_visit, current position, and time\nstring generate_base_route(vector<vector<int>>& last_visit, int& t, pair<int,int>& cur) {\n    visited.assign(N, vector<bool>(N, false));\n    next_neighbor_idx.assign(N*N, 0);\n    string route;\n    stack<pair<int,int>> st;\n    stack<char> move_stack;\n    st.emplace(0, 0);\n    visited[0][0] = true;\n    last_visit[0][0] = 0;\n    t = 0;\n    cur = {0,0};\n\n    while (!st.empty()) {\n        auto [i,j] = st.top();\n        int idx = i*N + j;\n        auto& neighbors = adj[i][j];\n        if (next_neighbor_idx[idx] < (int)neighbors.size()) {\n            auto [ni, nj, move] = neighbors[next_neighbor_idx[idx]++];\n            if (!visited[ni][nj]) {\n                visited[ni][nj] = true;\n                // move to child\n                route += move;\n                ++t;\n                last_visit[ni][nj] = t;\n                cur = {ni, nj};\n                move_stack.push(move);\n                st.emplace(ni, nj);\n            }\n        } else {\n            st.pop();\n            if (!move_stack.empty()) {\n                // backtrack to parent\n                char move_back = get_opposite(move_stack.top());\n                move_stack.pop();\n                route += move_back;\n                ++t;\n                auto [pi, pj] = st.top(); // parent is now on top\n                last_visit[pi][pj] = t;\n                cur = {pi, pj};\n            }\n        }\n    }\n    return route;\n}\n\n// greedy phase: returns the additional moves\nstring greedy_phase(pair<int,int> cur, int t, vector<vector<int>>& last_visit) {\n    string extra;\n    while (t < MAX_MOVES) {\n        int remaining = MAX_MOVES - t;\n        int ci = cur.first, cj = cur.second;\n        // if we must go directly to (0,0)\n        if (dist0[ci][cj] == remaining) {\n            // find neighbor with dist0 = remaining-1\n            for (auto [ni, nj, move] : adj[ci][cj]) {\n                if (dist0[ni][nj] == remaining - 1) {\n                    extra += move;\n                    ++t;\n                    last_visit[ni][nj] = t;\n                    cur = {ni, nj};\n                    break;\n                }\n            }\n        } else {\n            // choose neighbor with highest dirtiness among those with dist0 <= remaining-1\n            int best_dirt = -1;\n            char best_move = '?';\n            int best_ni = -1, best_nj = -1;\n            for (auto [ni, nj, move] : adj[ci][cj]) {\n                if (dist0[ni][nj] <= remaining - 1) {\n                    int dirt = (t - last_visit[ni][nj]) * d[ni][nj];\n                    if (dirt > best_dirt) {\n                        best_dirt = dirt;\n                        best_move = move;\n                        best_ni = ni;\n                        best_nj = nj;\n                    }\n                }\n            }\n            if (best_move != '?') {\n                extra += best_move;\n                ++t;\n                last_visit[best_ni][best_nj] = t;\n                cur = {best_ni, best_nj};\n            } else {\n                // should not happen, but fallback: move to any neighbor that reduces dist0\n                for (auto [ni, nj, move] : adj[ci][cj]) {\n                    if (dist0[ni][nj] < dist0[ci][cj]) {\n                        extra += move;\n                        ++t;\n                        last_visit[ni][nj] = t;\n                        cur = {ni, nj};\n                        break;\n                    }\n                }\n            }\n        }\n    }\n    return extra;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    h.resize(N-1);\n    for (int i = 0; i < N-1; ++i) cin >> h[i];\n    v.resize(N);\n    for (int i = 0; i < N; ++i) cin >> v[i];\n    d.assign(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> d[i][j];\n\n    build_graph();\n    compute_dist0();\n\n    vector<vector<int>> last_visit(N, vector<int>(N, 0));\n    int t = 0;\n    pair<int,int> cur = {0,0};\n    string base_route = generate_base_route(last_visit, t, cur);\n\n    string extra_route = greedy_phase(cur, t, last_visit);\n\n    cout << base_route << extra_route << endl;\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int INF = 1e9;\n\nstruct Solver {\n    int N, M, start_idx;\n    vector<int> xs, ys;\n    vector<vector<int>> cells;\n    vector<string> patterns;\n    vector<vector<char>> ov;\n\n    Solver(int N, int M, int start_idx, const vector<string>& grid, const vector<string>& patterns)\n        : N(N), M(M), start_idx(start_idx), patterns(patterns) {\n        int total = N * N;\n        xs.resize(total);\n        ys.resize(total);\n        cells.resize(26);\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                int idx = i * N + j;\n                xs[idx] = i;\n                ys[idx] = j;\n                int ch = grid[i][j] - 'A';\n                cells[ch].push_back(idx);\n            }\n        }\n\n        ov.assign(M, vector<char>(M, 0));\n        for (int i = 0; i < M; ++i) {\n            for (int j = 0; j < M; ++j) {\n                if (i == j) continue;\n                const string &a = patterns[i], &b = patterns[j];\n                for (int k = 4; k >= 1; --k) {\n                    if (a.compare(5 - k, k, b, 0, k) == 0) {\n                        ov[i][j] = k;\n                        break;\n                    }\n                }\n            }\n        }\n    }\n\n    vector<int> greedy_order_from(int start) const {\n        vector<bool> used(M, false);\n        vector<int> order;\n        order.push_back(start);\n        used[start] = true;\n        for (int step = 1; step < M; ++step) {\n            int last = order.back();\n            int best_ov = -1, best_next = -1;\n            for (int j = 0; j < M; ++j) {\n                if (!used[j]) {\n                    int o = ov[last][j];\n                    if (o > best_ov) {\n                        best_ov = o;\n                        best_next = j;\n                    }\n                }\n            }\n            order.push_back(best_next);\n            used[best_next] = true;\n        }\n        return order;\n    }\n\n    pair<int, vector<int>> solve_order(const vector<int>& order) const {\n        string S;\n        S.reserve(5 * M);\n        S += patterns[order[0]];\n        for (size_t i = 1; i < order.size(); ++i) {\n            int prev = order[i - 1];\n            int cur = order[i];\n            int k = ov[prev][cur];\n            S += patterns[cur].substr(k);\n        }\n        int L = S.size();\n        int total_cells = N * N;\n\n        vector<int> dp_prev(total_cells, INF);\n        vector<int> dp_curr(total_cells, INF);\n        vector<short> prev_cell(L * total_cells, -1);\n\n        int first_ch = S[0] - 'A';\n        for (int v : cells[first_ch]) {\n            int d = abs(xs[start_idx] - xs[v]) + abs(ys[start_idx] - ys[v]);\n            dp_prev[v] = d + 1;\n            prev_cell[0 * total_cells + v] = -1;\n        }\n\n        for (int pos = 1; pos < L; ++pos) {\n            int cur_ch = S[pos] - 'A';\n            int prev_ch = S[pos - 1] - 'A';\n            const auto& prev_cells = cells[prev_ch];\n            const auto& cur_cells = cells[cur_ch];\n\n            fill(dp_curr.begin(), dp_curr.end(), INF);\n            for (int v : cur_cells) {\n                int best = INF;\n                short best_u = -1;\n                for (int u : prev_cells) {\n                    if (dp_prev[u] == INF) continue;\n                    int d = abs(xs[u] - xs[v]) + abs(ys[u] - ys[v]);\n                    int cand = dp_prev[u] + d;\n                    if (cand < best) {\n                        best = cand;\n                        best_u = u;\n                    }\n                }\n                dp_curr[v] = best + 1;\n                prev_cell[pos * total_cells + v] = best_u;\n            }\n            swap(dp_prev, dp_curr);\n        }\n\n        int last_ch = S[L - 1] - 'A';\n        int best_cost = INF, best_end = -1;\n        for (int v : cells[last_ch]) {\n            if (dp_prev[v] < best_cost) {\n                best_cost = dp_prev[v];\n                best_end = v;\n            }\n        }\n\n        vector<int> path(L);\n        int cur_cell = best_end;\n        for (int pos = L - 1; pos >= 0; --pos) {\n            path[pos] = cur_cell;\n            cur_cell = prev_cell[pos * total_cells + cur_cell];\n        }\n\n        return {best_cost, path};\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n    int si, sj;\n    cin >> si >> sj;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n    vector<string> patterns(M);\n    for (int k = 0; k < M; ++k) cin >> patterns[k];\n\n    Solver solver(N, M, si * N + sj, grid, patterns);\n\n    int best_cost = INF;\n    vector<int> best_order;\n    for (int start = 0; start < M; ++start) {\n        vector<int> order = solver.greedy_order_from(start);\n        auto [cost, path] = solver.solve_order(order);\n        if (cost < best_cost) {\n            best_cost = cost;\n            best_order = order;\n        }\n        reverse(order.begin(), order.end());\n        auto [cost_rev, path_rev] = solver.solve_order(order);\n        if (cost_rev < best_cost) {\n            best_cost = cost_rev;\n            best_order = order;\n        }\n    }\n\n    auto [final_cost, final_path] = solver.solve_order(best_order);\n    for (int idx : final_path) {\n        int i = idx / N;\n        int j = idx % N;\n        cout << i << ' ' << j << '\\n';\n    }\n\n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <cmath>\n#include <numeric>\n#include <cstdint>\n#include <tuple>\n\nusing namespace std;\n\nstruct Placement {\n    vector<short> cells;          // indices of covered cells (0..N*N-1)\n    vector<uint8_t> contrib;      // contribution to each measurement\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cout.tie(nullptr);\n\n    int N, M;\n    double eps;\n    cin >> N >> M >> eps;\n    double alpha = 1.0 - 2.0 * eps;\n    double beta = eps;\n\n    // read shapes\n    vector<vector<pair<int, int>>> shape_cells(M);\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        shape_cells[k].resize(d);\n        for (int t = 0; t < d; ++t) {\n            cin >> shape_cells[k][t].first >> shape_cells[k][t].second;\n        }\n    }\n\n    // number of divine queries: enough for recovery but leave room for fallback drilling\n    int L = min(150, N * N - 10);\n    // random generator for subsets\n    mt19937 rng(123456);\n    uniform_real_distribution<double> prob(0.0, 1.0);\n\n    // generate random subsets and record which measurements contain each cell\n    vector<vector<int>> subsets(L);\n    vector<vector<int>> meas_including(N * N);\n    for (int l = 0; l < L; ++l) {\n        vector<int>& sub = subsets[l];\n        for (int idx = 0; idx < N * N; ++idx) {\n            if (prob(rng) < 0.5) {\n                sub.push_back(idx);\n                meas_including[idx].push_back(l);\n            }\n        }\n    }\n\n    // precompute all possible placements and their contributions\n    vector<vector<Placement>> placements(M);\n    for (int k = 0; k < M; ++k) {\n        const auto& cells = shape_cells[k];\n        int max_i = 0, max_j = 0;\n        for (auto& p : cells) {\n            max_i = max(max_i, p.first);\n            max_j = max(max_j, p.second);\n        }\n        int h = max_i + 1, w = max_j + 1;\n        for (int dx = 0; dx <= N - h; ++dx) {\n            for (int dy = 0; dy <= N - w; ++dy) {\n                Placement pl;\n                // compute cell indices\n                for (auto& p : cells) {\n                    int i = dx + p.first;\n                    int j = dy + p.second;\n                    pl.cells.push_back(i * N + j);\n                }\n                // compute contribution vector\n                pl.contrib.assign(L, 0);\n                for (int idx : pl.cells) {\n                    for (int l : meas_including[idx]) {\n                        pl.contrib[l]++;\n                    }\n                }\n                placements[k].push_back(move(pl));\n            }\n        }\n    }\n\n    // perform divine queries\n    vector<double> z_vals(L);\n    for (int l = 0; l < L; ++l) {\n        int k = subsets[l].size();\n        cout << \"q \" << k;\n        for (int idx : subsets[l]) {\n            int i = idx / N, j = idx % N;\n            cout << ' ' << i << ' ' << j;\n        }\n        cout << endl;\n        int y;\n        cin >> y;\n        z_vals[l] = (y - beta * k) / alpha;\n    }\n\n    // ----- Greedy OMP to obtain an initial assignment -----\n    vector<int> assignment(M, -1);\n    vector<double> residual = z_vals;\n    for (int iter = 0; iter < M; ++iter) {\n        double best_score = -1e100;\n        int best_shape = -1, best_place = -1;\n        for (int k = 0; k < M; ++k) {\n            if (assignment[k] != -1) continue;\n            const auto& plist = placements[k];\n            for (size_t p_idx = 0; p_idx < plist.size(); ++p_idx) {\n                const auto& p = plist[p_idx];\n                double dot = 0.0, norm2 = 0.0;\n                for (int l = 0; l < L; ++l) {\n                    double c = p.contrib[l];\n                    dot += residual[l] * c;\n                    norm2 += c * c;\n                }\n                if (norm2 == 0) continue;\n                double score = dot / sqrt(norm2);\n                if (score > best_score) {\n                    best_score = score;\n                    best_shape = k;\n                    best_place = p_idx;\n                }\n            }\n        }\n        // assign the best found\n        assignment[best_shape] = best_place;\n        const auto& p = placements[best_shape][best_place];\n        for (int l = 0; l < L; ++l) {\n            residual[l] -= p.contrib[l];\n        }\n    }\n\n    // ----- Simulated Annealing to refine the assignment -----\n    // current sums and error\n    vector<double> cur_sum(L, 0.0);\n    for (int k = 0; k < M; ++k) {\n        const auto& p = placements[k][assignment[k]];\n        for (int l = 0; l < L; ++l) cur_sum[l] += p.contrib[l];\n    }\n    double cur_err = 0.0;\n    for (int l = 0; l < L; ++l) {\n        double diff = z_vals[l] - cur_sum[l];\n        cur_err += diff * diff;\n    }\n\n    vector<int> best_assignment = assignment;\n    double best_err = cur_err;\n\n    const int SA_ITER = 50000;\n    const double INITIAL_TEMP = 1000.0;\n    const double COOLING = 0.9995;\n    double temp = INITIAL_TEMP;\n\n    mt19937 rng_sa(987654);\n    uniform_int_distribution<int> shape_dist(0, M - 1);\n    vector<uniform_int_distribution<int>> place_dist;\n    for (int k = 0; k < M; ++k) {\n        place_dist.emplace_back(0, placements[k].size() - 1);\n    }\n\n    for (int it = 0; it < SA_ITER; ++it) {\n        int k = shape_dist(rng_sa);\n        int old_idx = assignment[k];\n        int new_idx = place_dist[k](rng_sa);\n        if (new_idx == old_idx) continue;\n\n        const auto& p_old = placements[k][old_idx];\n        const auto& p_new = placements[k][new_idx];\n\n        double delta_err = 0.0;\n        for (int l = 0; l < L; ++l) {\n            double delta = (double)p_new.contrib[l] - (double)p_old.contrib[l];\n            double e_l = z_vals[l] - cur_sum[l];\n            delta_err += -2.0 * e_l * delta + delta * delta;\n        }\n\n        if (delta_err < 0 || uniform_real_distribution<double>(0, 1)(rng_sa) < exp(-delta_err / temp)) {\n            cur_err += delta_err;\n            for (int l = 0; l < L; ++l) {\n                cur_sum[l] += (p_new.contrib[l] - p_old.contrib[l]);\n            }\n            assignment[k] = new_idx;\n            if (cur_err < best_err) {\n                best_err = cur_err;\n                best_assignment = assignment;\n            }\n        }\n        temp *= COOLING;\n    }\n\n    // use the best assignment found\n    assignment = best_assignment;\n    // recompute current sums and error for this assignment\n    fill(cur_sum.begin(), cur_sum.end(), 0.0);\n    for (int k = 0; k < M; ++k) {\n        const auto& p = placements[k][assignment[k]];\n        for (int l = 0; l < L; ++l) cur_sum[l] += p.contrib[l];\n    }\n    cur_err = 0.0;\n    for (int l = 0; l < L; ++l) {\n        double diff = z_vals[l] - cur_sum[l];\n        cur_err += diff * diff;\n    }\n\n    // ----- Local hill climbing -----\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng_sa);\n        for (int k : order) {\n            int old_idx = assignment[k];\n            const auto& p_old = placements[k][old_idx];\n            for (size_t new_idx = 0; new_idx < placements[k].size(); ++new_idx) {\n                if (new_idx == static_cast<size_t>(old_idx)) continue;\n                const auto& p_new = placements[k][new_idx];\n                double delta_err = 0.0;\n                for (int l = 0; l < L; ++l) {\n                    double delta = (double)p_new.contrib[l] - (double)p_old.contrib[l];\n                    double e_l = z_vals[l] - cur_sum[l];\n                    delta_err += -2.0 * e_l * delta + delta * delta;\n                }\n                if (delta_err < -1e-9) {\n                    cur_err += delta_err;\n                    for (int l = 0; l < L; ++l) {\n                        double delta = (double)p_new.contrib[l] - (double)p_old.contrib[l];\n                        cur_sum[l] += delta;\n                    }\n                    assignment[k] = new_idx;\n                    improved = true;\n                    break; // go to next shape\n                }\n            }\n        }\n    }\n\n    // ----- Reconstruct the island from the assignment -----\n    vector<vector<int>> grid(N, vector<int>(N, 0));\n    for (int k = 0; k < M; ++k) {\n        const auto& p = placements[k][assignment[k]];\n        for (int idx : p.cells) {\n            int i = idx / N, j = idx % N;\n            grid[i][j]++;\n        }\n    }\n\n    // collect cells with positive oil reserves\n    vector<pair<int, int>> positive;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] > 0) {\n                positive.emplace_back(i, j);\n            }\n        }\n    }\n\n    // ----- First guess -----\n    cout << \"a \" << positive.size();\n    for (auto& p : positive) {\n        cout << ' ' << p.first << ' ' << p.second;\n    }\n    cout << endl;\n\n    int resp;\n    cin >> resp;\n    if (resp == 1) {\n        return 0;\n    }\n\n    // ----- Fallback: drill every cell -----\n    vector<bool> has_oil(N * N, false);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << \"q 1 \" << i << ' ' << j << endl;\n            int val;\n            cin >> val;\n            if (val > 0) {\n                has_oil[i * N + j] = true;\n            }\n        }\n    }\n\n    positive.clear();\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (has_oil[i * N + j]) {\n                positive.emplace_back(i, j);\n            }\n        }\n    }\n\n    cout << \"a \" << positive.size();\n    for (auto& p : positive) {\n        cout << ' ' << p.first << ' ' << p.second;\n    }\n    cout << endl;\n\n    cin >> resp; // should be 1\n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cstdint>\n\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    int W, D, N;\n    cin >> W >> D >> N;\n    \n    vector<vector<int>> a(D, vector<int>(N));\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            cin >> a[d][k];\n        }\n    }\n    \n    for (int d = 0; d < D; ++d) {\n        // sort desired areas descending\n        vector<pair<int, int>> order(N);\n        for (int k = 0; k < N; ++k) {\n            order[k] = {a[d][k], k};\n        }\n        sort(order.begin(), order.end(), greater<pair<int, int>>());\n        vector<int> sorted_areas(N);\n        vector<int> orig_idx(N);\n        for (int i = 0; i < N; ++i) {\n            sorted_areas[i] = order[i].first;\n            orig_idx[i] = order[i].second;\n        }\n        \n        // compute optimal widths for this day\n        vector<int> widths(N, 1);\n        int total = N;\n        for (int i = 0; i < N; ++i) {\n            int needed = (sorted_areas[i] + W - 1) / W;  // ceil(area/W)\n            int add = min(W - total, max(0, needed - 1));\n            widths[i] += add;\n            total += add;\n        }\n        // use any remaining width by adding to the first strip\n        if (total < W) {\n            widths[0] += (W - total);\n        }\n        \n        // build strips from left to right\n        vector<pair<int, int>> strip_lr(N);\n        int left = 0;\n        for (int i = 0; i < N; ++i) {\n            int right = left + widths[i];\n            strip_lr[i] = {left, right};\n            left = right;\n        }\n        \n        // assign strips to original reservations (largest area to widest strip)\n        vector<int> assign(N);\n        for (int i = 0; i < N; ++i) {\n            assign[orig_idx[i]] = i;\n        }\n        \n        // output rectangles in original order\n        for (int k = 0; k < N; ++k) {\n            int strip_idx = assign[k];\n            auto [l, r] = strip_lr[strip_idx];\n            // rectangle: top row 0, bottom row W, left column l, right column r\n            cout << \"0 \" << l << \" \" << W << \" \" << r << \"\\n\";\n        }\n    }\n    \n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <array>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <cstdint>\n\nusing namespace std;\n\nconst int MOD = 998244353;\nconst int N = 9, M = 20, K = 81;\n\nstruct Operation {\n    int stamp, p, q;\n    vector<pair<int, int>> cells;\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m, k;\n    cin >> n >> m >> k;\n\n    vector<int64_t> cur(81);\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cin >> cur[i * 9 + j];\n        }\n    }\n\n    vector<array<array<int, 3>, 3>> stamps(m);\n    for (int s = 0; s < m; ++s) {\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                cin >> stamps[s][i][j];\n            }\n        }\n    }\n\n    vector<Operation> ops;\n    for (int s = 0; s < m; ++s) {\n        for (int p = 0; p <= n - 3; ++p) {\n            for (int q = 0; q <= n - 3; ++q) {\n                Operation op;\n                op.stamp = s;\n                op.p = p;\n                op.q = q;\n                for (int i = 0; i < 3; ++i) {\n                    for (int j = 0; j < 3; ++j) {\n                        int cell = (p + i) * 9 + (q + j);\n                        int val = stamps[s][i][j];\n                        op.cells.emplace_back(cell, val);\n                    }\n                }\n                ops.push_back(move(op));\n            }\n        }\n    }\n    const int num_ops = ops.size();\n\n    int64_t score = 0;\n    for (int i = 0; i < 81; ++i) score += cur[i] % MOD;\n\n    auto delta_add = [&](int id) -> int64_t {\n        int64_t d = 0;\n        for (auto [idx, val] : ops[id].cells) {\n            int64_t old_rem = cur[idx] % MOD;\n            int64_t new_val = cur[idx] + val;\n            int64_t new_rem = new_val % MOD;\n            d += new_rem - old_rem;\n        }\n        return d;\n    };\n\n    auto apply_add = [&](int id) {\n        for (auto [idx, val] : ops[id].cells) {\n            cur[idx] += val;\n        }\n    };\n\n    auto delta_remove = [&](int id) -> int64_t {\n        int64_t d = 0;\n        for (auto [idx, val] : ops[id].cells) {\n            int64_t old_rem = cur[idx] % MOD;\n            int64_t new_val = cur[idx] - val;\n            int64_t new_rem = new_val % MOD;\n            d += new_rem - old_rem;\n        }\n        return d;\n    };\n\n    auto apply_remove = [&](int id) {\n        for (auto [idx, val] : ops[id].cells) {\n            cur[idx] -= val;\n        }\n    };\n\n    // Greedy initial solution\n    vector<int> cur_ops;\n    while (cur_ops.size() < K) {\n        int best_id = -1;\n        int64_t best_delta = 0;\n        for (int id = 0; id < num_ops; ++id) {\n            int64_t d = delta_add(id);\n            if (d > best_delta) {\n                best_delta = d;\n                best_id = id;\n            }\n        }\n        if (best_delta <= 0) break;\n        apply_add(best_id);\n        cur_ops.push_back(best_id);\n        score += best_delta;\n    }\n\n    // Simulated Annealing with increased iterations and adjusted probabilities\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> uni_real(0.0, 1.0);\n\n    const int max_iter = 3'000'000;  // Increased from 1M to 3M\n    const double T0 = 1e8;\n    double T = T0;\n\n    static int64_t contrib[81];\n    static vector<int> touched;\n\n    for (int iter = 0; iter < max_iter; ++iter) {\n        double r = uni_real(rng);\n        // Adjusted probabilities: 20% add, 20% remove, 60% replace\n        if (r < 0.2 && cur_ops.size() < K) {\n            // Add operation\n            int new_id = rng() % num_ops;\n            int64_t delta = delta_add(new_id);\n            if (delta > 0 || (delta <= 0 && exp(delta / T) > uni_real(rng))) {\n                apply_add(new_id);\n                cur_ops.push_back(new_id);\n                score += delta;\n            }\n        } else if (r < 0.4 && !cur_ops.empty()) {\n            // Remove operation\n            int idx = rng() % cur_ops.size();\n            int old_id = cur_ops[idx];\n            int64_t delta = delta_remove(old_id);\n            if (delta > 0 || (delta <= 0 && exp(delta / T) > uni_real(rng))) {\n                apply_remove(old_id);\n                cur_ops[idx] = cur_ops.back();\n                cur_ops.pop_back();\n                score += delta;\n            }\n        } else if (!cur_ops.empty()) {\n            // Replace operation (60% chance)\n            int idx = rng() % cur_ops.size();\n            int old_id = cur_ops[idx];\n            int new_id = rng() % num_ops;\n            if (new_id == old_id) continue;\n\n            // Compute net change using contrib array\n            touched.clear();\n            for (auto [i, v] : ops[old_id].cells) {\n                if (contrib[i] == 0) touched.push_back(i);\n                contrib[i] -= v;\n            }\n            for (auto [i, v] : ops[new_id].cells) {\n                if (contrib[i] == 0) touched.push_back(i);\n                contrib[i] += v;\n            }\n\n            int64_t delta = 0;\n            for (int i : touched) {\n                int64_t net = contrib[i];\n                int64_t old_rem = cur[i] % MOD;\n                int64_t new_val = cur[i] + net;\n                int64_t new_rem = new_val % MOD;\n                delta += new_rem - old_rem;\n            }\n\n            if (delta > 0 || (delta <= 0 && exp(delta / T) > uni_real(rng))) {\n                for (int i : touched) {\n                    cur[i] += contrib[i];\n                }\n                cur_ops[idx] = new_id;\n                score += delta;\n            }\n\n            for (int i : touched) {\n                contrib[i] = 0;\n            }\n        }\n\n        // Linear cooling\n        T = T0 * (1.0 - (double)iter / max_iter);\n    }\n\n    // Output\n    cout << cur_ops.size() << '\\n';\n    for (int id : cur_ops) {\n        cout << ops[id].stamp << ' ' << ops[id].p << ' ' << ops[id].q << '\\n';\n    }\n\n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <deque>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <climits>\n#include <cstdlib>\n#include <utility>\n\nusing namespace std;\n\nint main() {\n    const int N = 5;\n    int A[N][N];\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> A[i][j];\n\n    // queues of remaining containers for each receiving gate\n    deque<int> gate_rem[N];\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            gate_rem[i].push_back(A[i][j]);\n\n    int grid[N][N];\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            grid[i][j] = -1;          // -1 means empty\n\n    int hold = -1;                    // -1: not holding, otherwise container number\n    int posx = 0, posy = 0;           // position of the large crane\n\n    bool dispatched[25] = {false};\n    int next_exp[5];                  // next expected container for each row\n    for (int i = 0; i < N; ++i)\n        next_exp[i] = N * i;\n\n    pair<int, int> loc[25];           // location of container on the grid, (-1,-1) if not present\n    for (int i = 0; i < 25; ++i)\n        loc[i] = {-1, -1};\n\n    vector<string> ans(5);            // actions for the five cranes\n    int dispatched_cnt = 0;\n\n    const int INF = 1000000;\n\n    // helper lambdas\n    auto manhattan = [](int x1, int y1, int x2, int y2) {\n        return abs(x1 - x2) + abs(y1 - y2);\n    };\n\n    auto move_towards = [](int x, int y, int tx, int ty) -> char {\n        if (x < tx) return 'D';\n        if (x > tx) return 'U';\n        if (y < ty) return 'R';\n        if (y > ty) return 'L';\n        return '.';\n    };\n\n    auto find_buffer = [&](int x, int y, bool allow_active_gates) -> pair<int, int> {\n        int best_dist = INF;\n        pair<int, int> best = {-1, -1};\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N - 1; ++j) {   // columns 0..3 (col4 is dispatch)\n                if (grid[i][j] != -1) continue;\n                if (j == 0 && !allow_active_gates && !gate_rem[i].empty())\n                    continue;\n                int d = manhattan(x, y, i, j);\n                if (d < best_dist) {\n                    best_dist = d;\n                    best = {i, j};\n                }\n            }\n        }\n        return best;\n    };\n\n    auto estimated_store_distance = [&](int x, int y) -> int {\n        auto buf = find_buffer(x, y, false);\n        if (buf.first == -1) return INF;\n        return manhattan(x, y, buf.first, buf.second);\n    };\n\n    struct Candidate {\n        int cost;\n        int type;       // 0 = retrieve stored needed, 1 = pick up from gate\n        int b;          // container number\n        int px, py;     // pickup location\n        bool needed;    // for type 1: is it the next expected?\n    };\n\n    int turn = 0;\n    while (dispatched_cnt < N * N) {\n        ++turn;\n        if (turn > 10000) break;   // safety limit\n\n        // ---------- Step 1: place containers at receiving gates ----------\n        for (int i = 0; i < N; ++i) {\n            if (grid[i][0] == -1) {\n                // placement is blocked only if the large crane is at (i,0) and holding\n                if (!(posx == i && posy == 0 && hold != -1)) {\n                    if (!gate_rem[i].empty()) {\n                        int b = gate_rem[i].front();\n                        gate_rem[i].pop_front();\n                        grid[i][0] = b;\n                        loc[b] = {i, 0};\n                    }\n                }\n            }\n        }\n\n        // ---------- Step 2: decide action for the large crane ----------\n        char action;\n\n        if (hold != -1) {   // holding a container\n            int b = hold;\n            int r = b / N;\n            if (b == next_exp[r]) {   // should deliver\n                if (posx == r && posy == N - 1)\n                    action = 'Q';\n                else\n                    action = move_towards(posx, posy, r, N - 1);\n            } else {   // should store\n                // can we release here?\n                bool can_release_here = false;\n                if (posy != N - 1 && grid[posx][posy] == -1) {\n                    if (posy != 0 || gate_rem[posx].empty())\n                        can_release_here = true;\n                }\n                if (can_release_here) {\n                    action = 'Q';\n                } else {\n                    auto target = find_buffer(posx, posy, false);\n                    if (target.first == -1)   // no buffer -> fallback to deliver (causes inversion)\n                        target = {r, N - 1};\n                    action = move_towards(posx, posy, target.first, target.second);\n                }\n            }\n        } else {   // not holding\n            vector<Candidate> cand;\n\n            // retrieve stored needed containers\n            for (int r = 0; r < N; ++r) {\n                int b = next_exp[r];\n                if (b >= 0 && b < N * N && loc[b].first != -1) {\n                    int px = loc[b].first, py = loc[b].second;\n                    int d1 = manhattan(posx, posy, px, py);\n                    int d2 = manhattan(px, py, r, N - 1);\n                    int cost = d1 + d2 + 2;\n                    cand.push_back({cost, 0, b, px, py, true});\n                }\n            }\n\n            // pick up from gates\n            for (int i = 0; i < N; ++i) {\n                if (gate_rem[i].empty()) continue;\n                int head = gate_rem[i][0];\n                // only consider if the gate cell is empty or already contains the head\n                if (grid[i][0] != -1 && grid[i][0] != head) continue;\n                int px = i, py = 0;\n                int r = head / N;\n                bool needed = (head == next_exp[r]);\n                int d1 = manhattan(posx, posy, px, py);\n                int d2;\n                if (needed) {\n                    d2 = manhattan(px, py, r, N - 1);\n                } else {\n                    d2 = estimated_store_distance(px, py);\n                    if (d2 >= INF) d2 = 1000;   // large fallback\n                }\n                int cost = d1 + d2 + 2;\n                cand.push_back({cost, 1, head, px, py, needed});\n            }\n\n            if (cand.empty()) {\n                action = '.';\n            } else {\n                auto best = *min_element(cand.begin(), cand.end(),\n                    [](const Candidate& a, const Candidate& b) { return a.cost < b.cost; });\n                if (posx == best.px && posy == best.py)\n                    action = 'P';\n                else\n                    action = move_towards(posx, posy, best.px, best.py);\n            }\n        }\n\n        // execute the chosen action for crane 0\n        switch (action) {\n            case 'P':\n                hold = grid[posx][posy];\n                grid[posx][posy] = -1;\n                loc[hold] = {-1, -1};\n                break;\n            case 'Q':\n                grid[posx][posy] = hold;\n                loc[hold] = {posx, posy};\n                hold = -1;\n                break;\n            case 'U':\n                if (posx > 0) posx--;\n                break;\n            case 'D':\n                if (posx < N - 1) posx++;\n                break;\n            case 'L':\n                if (posy > 0) posy--;\n                break;\n            case 'R':\n                if (posy < N - 1) posy++;\n                break;\n            case '.':\n                break;\n            case 'B':\n                break;   // never used for crane 0\n        }\n\n        ans[0] += action;\n\n        // actions for the four small cranes (1..4)\n        for (int i = 1; i < N; ++i) {\n            if (turn == 1)\n                ans[i] += 'B';\n            else\n                ans[i] += '.';\n        }\n\n        // ---------- Step 3: dispatch containers at dispatch gates ----------\n        for (int i = 0; i < N; ++i) {\n            if (grid[i][N - 1] != -1) {\n                int b = grid[i][N - 1];\n                grid[i][N - 1] = -1;\n                dispatched[b] = true;\n                loc[b] = {-1, -1};\n                dispatched_cnt++;\n                // update next expected for this row\n                for (int c = N * i; c < N * (i + 1); ++c) {\n                    if (!dispatched[c]) {\n                        next_exp[i] = c;\n                        break;\n                    }\n                }\n            }\n        }\n\n        if (dispatched_cnt == N * N) break;\n    }\n\n    // output\n    for (int i = 0; i < N; ++i)\n        cout << ans[i] << endl;\n\n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <cassert>\n\nusing namespace std;\n\nstruct Square {\n    int x, y, h;\n};\n\ninline int manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\npair<long long, bool> evaluate(const vector<int>& perm, const vector<Square>& squares) {\n    long long total_steps = 0;\n    long long load_dist = 0;\n    int load = 0;\n    int cur_x = 0, cur_y = 0;\n    bool feasible = true;\n\n    for (int idx : perm) {\n        const Square& sq = squares[idx];\n        int d = manhattan(cur_x, cur_y, sq.x, sq.y);\n        total_steps += d;\n        load_dist += (long long)load * d;\n\n        load += sq.h;\n        if (load < 0) {\n            feasible = false;\n            break;\n        }\n\n        cur_x = sq.x;\n        cur_y = sq.y;\n    }\n\n    if (load != 0) feasible = false;\n\n    long long cost_without_base = 100 * total_steps + load_dist;\n    return {cost_without_base, feasible};\n}\n\nvector<int> greedy_permutation(const vector<Square>& squares) {\n    int M = squares.size();\n    vector<bool> used(M, false);\n    vector<int> perm;\n    int cur_x = 0, cur_y = 0;\n    int load = 0;\n    int remaining = M;\n\n    while (remaining > 0) {\n        int best_idx = -1;\n        int best_dist = 1e9;\n\n        for (int i = 0; i < M; ++i) {\n            if (used[i]) continue;\n            const Square& sq = squares[i];\n            int d = manhattan(cur_x, cur_y, sq.x, sq.y);\n            bool feasible = false;\n            if (sq.h > 0) {\n                feasible = true;\n            } else {\n                if (load >= -sq.h) feasible = true;\n            }\n            if (feasible && d < best_dist) {\n                best_dist = d;\n                best_idx = i;\n            }\n        }\n\n        assert(best_idx != -1);\n        used[best_idx] = true;\n        perm.push_back(best_idx);\n        cur_x = squares[best_idx].x;\n        cur_y = squares[best_idx].y;\n        load += squares[best_idx].h;\n        --remaining;\n    }\n\n    return perm;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<vector<int>> h(N, vector<int>(N));\n    long long base = 0;\n    vector<Square> squares;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> h[i][j];\n            if (h[i][j] != 0) {\n                squares.push_back({i, j, h[i][j]});\n                base += abs(h[i][j]);\n            }\n        }\n    }\n\n    int M = squares.size();\n    if (M == 0) {\n        return 0;\n    }\n\n    vector<int> init_perm = greedy_permutation(squares);\n\n    const int MAX_ITER = 300000;\n    double start_temp = 10000.0;\n    double end_temp = 1e-3;\n    double cooling = exp(log(end_temp / start_temp) / MAX_ITER);\n\n    random_device rd;\n    mt19937 rng(rd());\n    uniform_real_distribution<double> uni(0.0, 1.0);\n    uniform_int_distribution<int> rand_idx(0, M-1);\n\n    vector<int> best_perm = init_perm;\n    auto [best_cost, feasible_init] = evaluate(best_perm, squares);\n    assert(feasible_init);\n    vector<int> cur_perm = best_perm;\n    long long cur_cost = best_cost;\n\n    for (int iter = 0; iter < MAX_ITER; ++iter) {\n        double T = start_temp * pow(cooling, iter);\n        vector<int> new_perm = cur_perm;\n        double move_type = uni(rng);\n\n        if (move_type < 0.33) {\n            // swap two random positions\n            int i = rand_idx(rng);\n            int j = rand_idx(rng);\n            if (i != j) swap(new_perm[i], new_perm[j]);\n        } else if (move_type < 0.66) {\n            // reverse a random segment\n            int i = rand_idx(rng);\n            int j = rand_idx(rng);\n            if (i > j) swap(i, j);\n            reverse(new_perm.begin() + i, new_perm.begin() + j + 1);\n        } else {\n            // move a random element to another random position\n            int i = rand_idx(rng);\n            int j = rand_idx(rng);\n            if (i != j) {\n                int val = new_perm[i];\n                new_perm.erase(new_perm.begin() + i);\n                if (j > i) --j;\n                new_perm.insert(new_perm.begin() + j, val);\n            }\n        }\n\n        auto [new_cost, feasible] = evaluate(new_perm, squares);\n        if (!feasible) continue;\n\n        if (new_cost < cur_cost || uni(rng) < exp((cur_cost - new_cost) / T)) {\n            cur_perm = new_perm;\n            cur_cost = new_cost;\n            if (cur_cost < best_cost) {\n                best_perm = cur_perm;\n                best_cost = cur_cost;\n            }\n        }\n    }\n\n    // Output operations\n    int cur_x = 0, cur_y = 0, load = 0;\n    for (int idx : best_perm) {\n        const Square& sq = squares[idx];\n        while (cur_y < sq.y) { cout << \"R\\n\"; ++cur_y; }\n        while (cur_y > sq.y) { cout << \"L\\n\"; --cur_y; }\n        while (cur_x < sq.x) { cout << \"D\\n\"; ++cur_x; }\n        while (cur_x > sq.x) { cout << \"U\\n\"; --cur_x; }\n\n        if (sq.h > 0) {\n            cout << \"+\" << sq.h << \"\\n\";\n            load += sq.h;\n        } else {\n            cout << \"-\" << -sq.h << \"\\n\";\n            load += sq.h;\n        }\n    }\n\n    return 0;\n}","ahc035":"#include <cstdio>\n#include <vector>\n#include <array>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n#include <set>\n\nusing namespace std;\n\nconst int N = 6;\nconst int M = 15;\nconst int T = 10;\nconst int SEED_COUNT = 2 * N * (N - 1); // 60\n\nusing Seed = array<int, M>;\n\n// Complementarity score: sum of max values per attribute\nint complementarity(const Seed& a, const Seed& b) {\n    int res = 0;\n    for (int l = 0; l < M; ++l) {\n        res += max(a[l], b[l]);\n    }\n    return res;\n}\n\n// Select seeds with diversity and high potential\nvector<int> select_seeds(const vector<Seed>& seeds, const vector<int>& sums) {\n    vector<int> selected;\n    vector<bool> used(SEED_COUNT, false);\n    \n    // First, take top 10 by sum (high value seeds)\n    vector<int> by_sum(SEED_COUNT);\n    iota(by_sum.begin(), by_sum.end(), 0);\n    sort(by_sum.begin(), by_sum.end(), [&](int a, int b) { return sums[a] > sums[b]; });\n    \n    for (int i = 0; i < 10 && i < SEED_COUNT; ++i) {\n        selected.push_back(by_sum[i]);\n        used[by_sum[i]] = true;\n    }\n    \n    // Then add seeds that are complementary to existing ones\n    while (selected.size() < 36) {\n        int best_seed = -1;\n        int best_score = -1;\n        \n        for (int i = 0; i < SEED_COUNT; ++i) {\n            if (used[i]) continue;\n            \n            // Score: sum of complementarity with all selected seeds\n            int score = 0;\n            for (int s : selected) {\n                score += complementarity(seeds[i], seeds[s]);\n            }\n            score /= selected.size(); // Normalize by number of selected\n            \n            // Add a bonus for high individual sum\n            score += sums[i] / 10;\n            \n            if (score > best_score) {\n                best_score = score;\n                best_seed = i;\n            }\n        }\n        \n        if (best_seed != -1) {\n            selected.push_back(best_seed);\n            used[best_seed] = true;\n        } else {\n            break;\n        }\n    }\n    \n    // If we still need more, add by highest sum\n    if (selected.size() < 36) {\n        for (int i = 0; i < SEED_COUNT && selected.size() < 36; ++i) {\n            if (!used[i]) {\n                selected.push_back(i);\n                used[i] = true;\n            }\n        }\n    }\n    \n    return selected;\n}\n\n// Place seeds to maximize good pairings\nvoid place_seeds(const vector<Seed>& seeds, const vector<int>& sums, \n                 const vector<int>& selected, vector<vector<int>>& grid) {\n    // We'll use a greedy approach considering complementarity\n    vector<bool> used(SEED_COUNT, false);\n    for (int s : selected) used[s] = true;\n    \n    // Start with the highest sum seed in the center\n    vector<int> selected_copy = selected;\n    sort(selected_copy.begin(), selected_copy.end(), [&](int a, int b) { \n        return sums[a] > sums[b]; \n    });\n    \n    // Place highest sum seeds in interior cells first\n    vector<pair<int, int>> interior_cells;\n    vector<pair<int, int>> border_cells;\n    \n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            bool is_interior = (i > 0 && i < N-1 && j > 0 && j < N-1);\n            if (is_interior) {\n                interior_cells.push_back({i, j});\n            } else {\n                border_cells.push_back({i, j});\n            }\n        }\n    }\n    \n    // Place top seeds in interior\n    for (int i = 0; i < interior_cells.size() && i < selected_copy.size(); ++i) {\n        auto [r, c] = interior_cells[i];\n        grid[r][c] = selected_copy[i];\n    }\n    \n    // Fill remaining cells with remaining seeds\n    vector<int> remaining_seeds;\n    for (int s : selected_copy) {\n        bool placed = false;\n        for (int i = 0; i < N && !placed; ++i) {\n            for (int j = 0; j < N && !placed; ++j) {\n                if (grid[i][j] == s) {\n                    placed = true;\n                }\n            }\n        }\n        if (!placed) {\n            remaining_seeds.push_back(s);\n        }\n    }\n    \n    // Place border seeds\n    for (int i = 0; i < border_cells.size() && !remaining_seeds.empty(); ++i) {\n        auto [r, c] = border_cells[i];\n        grid[r][c] = remaining_seeds.back();\n        remaining_seeds.pop_back();\n    }\n    \n    // Fill any remaining empty cells\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] == -1 && !remaining_seeds.empty()) {\n                grid[i][j] = remaining_seeds.back();\n                remaining_seeds.pop_back();\n            }\n        }\n    }\n    \n    // Now optimize placement by swapping to increase complementarity\n    for (int iter = 0; iter < 100; ++iter) {\n        bool improved = false;\n        \n        for (int i1 = 0; i1 < N; ++i1) {\n            for (int j1 = 0; j1 < N; ++j1) {\n                for (int i2 = 0; i2 < N; ++i2) {\n                    for (int j2 = 0; j2 < N; ++j2) {\n                        if (i1 == i2 && j1 == j2) continue;\n                        \n                        // Calculate current complementarity for neighbors of both cells\n                        auto get_neighbors = [&](int i, int j) {\n                            vector<pair<int, int>> neighbors;\n                            if (i > 0) neighbors.push_back({i-1, j});\n                            if (i < N-1) neighbors.push_back({i+1, j});\n                            if (j > 0) neighbors.push_back({i, j-1});\n                            if (j < N-1) neighbors.push_back({i, j+1});\n                            return neighbors;\n                        };\n                        \n                        auto neighbors1 = get_neighbors(i1, j1);\n                        auto neighbors2 = get_neighbors(i2, j2);\n                        \n                        int current_score = 0;\n                        for (auto [ni, nj] : neighbors1) {\n                            current_score += complementarity(seeds[grid[i1][j1]], seeds[grid[ni][nj]]);\n                        }\n                        for (auto [ni, nj] : neighbors2) {\n                            current_score += complementarity(seeds[grid[i2][j2]], seeds[grid[ni][nj]]);\n                        }\n                        \n                        // Try swapping\n                        swap(grid[i1][j1], grid[i2][j2]);\n                        \n                        int new_score = 0;\n                        for (auto [ni, nj] : neighbors1) {\n                            new_score += complementarity(seeds[grid[i1][j1]], seeds[grid[ni][nj]]);\n                        }\n                        for (auto [ni, nj] : neighbors2) {\n                            new_score += complementarity(seeds[grid[i2][j2]], seeds[grid[ni][nj]]);\n                        }\n                        \n                        if (new_score > current_score) {\n                            improved = true;\n                        } else {\n                            swap(grid[i1][j1], grid[i2][j2]);\n                        }\n                    }\n                }\n            }\n        }\n        \n        if (!improved) break;\n    }\n}\n\nint main() {\n    vector<Seed> seeds(SEED_COUNT);\n    vector<int> sums(SEED_COUNT);\n    \n    // Read initial seeds\n    for (int i = 0; i < SEED_COUNT; ++i) {\n        for (int j = 0; j < M; ++j) {\n            scanf(\"%d\", &seeds[i][j]);\n        }\n        sums[i] = accumulate(seeds[i].begin(), seeds[i].end(), 0);\n    }\n    \n    for (int t = 0; t < T; ++t) {\n        // Select seeds\n        vector<int> selected = select_seeds(seeds, sums);\n        \n        // Place seeds\n        vector<vector<int>> grid(N, vector<int>(N, -1));\n        place_seeds(seeds, sums, selected, grid);\n        \n        // Output the grid\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                printf(\"%d\", grid[i][j]);\n                if (j < N - 1) printf(\" \");\n                else printf(\"\\n\");\n            }\n        }\n        fflush(stdout);\n        \n        // Read new seeds\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            for (int j = 0; j < M; ++j) {\n                scanf(\"%d\", &seeds[i][j]);\n            }\n            sums[i] = accumulate(seeds[i].begin(), seeds[i].end(), 0);\n        }\n    }\n    \n    return 0;\n}","ahc038":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <string>\n#include <cmath>\n#include <cassert>\n#include <climits>\n\nusing namespace std;\n\nstruct Point {\n    int x, y;\n    Point(int x = 0, int y = 0) : x(x), y(y) {}\n    bool operator==(const Point& other) const {\n        return x == other.x && y == other.y;\n    }\n};\n\nint manhattan(const Point& a, const Point& b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\nint N, M, V_arm; // V_arm = number of vertices in the arm (given V)\nvector<string> s_grid, t_grid;\nvector<Point> pickups;   // initial positions that need to be moved\nvector<Point> dropoffs;  // target positions that need to be filled\n\n// current state of the robotic arm\nPoint root;                     // current root position\nvector<int> cur_dir;            // current directions of edges (size = V_arm-1)\nvector<string> output_turns;    // sequence of operation strings\n\n// direction vectors: 0:right, 1:down, 2:left, 3:up\nconst int dx_dir[4] = {0, 1, 0, -1};\nconst int dy_dir[4] = {1, 0, -1, 0};\n\n// Helper: for a given cell, find the root position and offset (dx,dy) with Manhattan distance D\n// that minimizes distance from current root.\npair<Point, Point> find_best_root_offset(const Point& cell, const Point& cur_root, int D) {\n    int best_dist = INT_MAX;\n    Point best_root, best_offset;\n    for (int dx = -D; dx <= D; ++dx) {\n        int abs_dx = abs(dx);\n        int abs_dy = D - abs_dx;\n        for (int dy_sign : {1, -1}) {\n            int dy = dy_sign * abs_dy;\n            Point cand_root(cell.x - dx, cell.y - dy);\n            if (cand_root.x >= 0 && cand_root.x < N &&\n                cand_root.y >= 0 && cand_root.y < N) {\n                int dist = manhattan(cur_root, cand_root);\n                if (dist < best_dist) {\n                    best_dist = dist;\n                    best_root = cand_root;\n                    best_offset = Point(dx, dy);\n                }\n            }\n        }\n    }\n    return {best_root, best_offset};\n}\n\n// Move the root step by step to target_root, outputting moves.\nvoid move_to(const Point& target_root) {\n    while (root.x != target_root.x || root.y != target_root.y) {\n        char move_char = '.';\n        if (root.x < target_root.x) {\n            move_char = 'D';\n            root.x++;\n        } else if (root.x > target_root.x) {\n            move_char = 'U';\n            root.x--;\n        } else if (root.y < target_root.y) {\n            move_char = 'R';\n            root.y++;\n        } else if (root.y > target_root.y) {\n            move_char = 'L';\n            root.y--;\n        }\n        string turn(2 * V_arm, '.');\n        turn[0] = move_char;\n        output_turns.push_back(turn);\n    }\n}\n\n// Change the offset to (tx,ty) and perform action act ('P' for grab/release, '.' otherwise).\n// The function may output one or two turns.\nvoid change_offset_and_act(int tx, int ty, char act) {\n    int D = V_arm - 1; // number of edges\n    int H = abs(ty);   // number of horizontal edges needed\n    int V_edges = D - H; // = abs(tx)\n\n    int hor_sign = (ty > 0) ? 0 : 2; // 0:right, 2:left\n    int ver_sign = (tx > 0) ? 1 : 3; // 1:down, 3:up\n\n    // Compute target directions for each edge with min-cost assignment\n    vector<int> target_dir(D, 0);\n    vector<int> cost_hor(D), cost_ver(D);\n    for (int i = 0; i < D; ++i) {\n        int d = cur_dir[i];\n        cost_hor[i] = min(abs(d - hor_sign), 4 - abs(d - hor_sign));\n        cost_ver[i] = min(abs(d - ver_sign), 4 - abs(d - ver_sign));\n    }\n\n    vector<pair<int, int>> diff; // (cost_hor - cost_ver, index)\n    for (int i = 0; i < D; ++i) {\n        diff.emplace_back(cost_hor[i] - cost_ver[i], i);\n    }\n    sort(diff.begin(), diff.end());\n\n    vector<bool> is_hor(D, false);\n    for (int i = 0; i < H; ++i) {\n        is_hor[diff[i].second] = true;\n    }\n    for (int i = 0; i < D; ++i) {\n        if (is_hor[i])\n            target_dir[i] = hor_sign;\n        else\n            target_dir[i] = ver_sign;\n    }\n\n    // Compute required rotations (number of clockwise 90\u00b0 steps)\n    vector<int> need(D);\n    for (int i = 0; i < D; ++i) {\n        need[i] = (target_dir[i] - cur_dir[i] + 4) % 4;\n    }\n\n    bool has_180 = false;\n    for (int i = 0; i < D; ++i) {\n        if (need[i] == 2) {\n            has_180 = true;\n            break;\n        }\n    }\n\n    auto make_rotation_string = [&](bool final_turn) -> string {\n        string rot(D, '.');\n        for (int i = 0; i < D; ++i) {\n            if (need[i] == 0) rot[i] = '.';\n            else if (need[i] == 1) rot[i] = 'R';\n            else if (need[i] == 2) {\n                rot[i] = 'R'; // one rotation now, another later if needed\n            }\n            else if (need[i] == 3) rot[i] = 'L';\n        }\n        return rot;\n    };\n\n    if (!has_180) {\n        // One turn is enough\n        string rot_str = make_rotation_string(true);\n        // Update cur_dir\n        for (int i = 0; i < D; ++i) {\n            if (need[i] == 1) cur_dir[i] = (cur_dir[i] + 1) % 4;\n            else if (need[i] == 3) cur_dir[i] = (cur_dir[i] + 3) % 4;\n        }\n        // Build turn string\n        string turn(2 * V_arm, '.');\n        turn[0] = '.'; // no move\n        for (int i = 0; i < D; ++i) turn[1 + i] = rot_str[i];\n        if (act == 'P') turn[2 * V_arm - 1] = 'P'; // fingertip action at vertex V_arm-1\n        output_turns.push_back(turn);\n    } else {\n        // Need two turns\n        // First turn: rotate once where needed\n        string rot_str1 = make_rotation_string(false);\n        // Update cur_dir after first rotation\n        for (int i = 0; i < D; ++i) {\n            if (need[i] == 1 || need[i] == 2) cur_dir[i] = (cur_dir[i] + 1) % 4;\n            else if (need[i] == 3) cur_dir[i] = (cur_dir[i] + 3) % 4;\n        }\n        // Build first turn\n        string turn1(2 * V_arm, '.');\n        turn1[0] = '.';\n        for (int i = 0; i < D; ++i) turn1[1 + i] = rot_str1[i];\n        output_turns.push_back(turn1);\n\n        // Second turn: rotate the remaining 180\u00b0 edges\n        vector<int> need2(D, 0);\n        for (int i = 0; i < D; ++i) {\n            if (need[i] == 2) need2[i] = 1;\n        }\n        string rot_str2(D, '.');\n        for (int i = 0; i < D; ++i) {\n            if (need2[i] == 1) rot_str2[i] = 'R';\n        }\n        // Update cur_dir\n        for (int i = 0; i < D; ++i) {\n            if (need2[i] == 1) cur_dir[i] = (cur_dir[i] + 1) % 4;\n        }\n        string turn2(2 * V_arm, '.');\n        turn2[0] = '.';\n        for (int i = 0; i < D; ++i) turn2[1 + i] = rot_str2[i];\n        if (act == 'P') turn2[2 * V_arm - 1] = 'P';\n        output_turns.push_back(turn2);\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Read input\n    cin >> N >> M >> V_arm;\n    s_grid.resize(N);\n    t_grid.resize(N);\n    for (int i = 0; i < N; ++i) cin >> s_grid[i];\n    for (int i = 0; i < N; ++i) cin >> t_grid[i];\n\n    // Determine pickups and dropoffs\n    vector<vector<bool>> is_target(N, vector<bool>(N, false));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (t_grid[i][j] == '1') is_target[i][j] = true;\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (s_grid[i][j] == '1') {\n                if (is_target[i][j]) {\n                    // Already at a target, mark both as done\n                    is_target[i][j] = false;\n                } else {\n                    pickups.emplace_back(i, j);\n                }\n            }\n        }\n    }\n\n    // The remaining targets are dropoffs\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (is_target[i][j]) {\n                dropoffs.emplace_back(i, j);\n            }\n        }\n    }\n\n    // Design the arm: a chain of V_arm vertices, edges of length 1\n    cout << V_arm << '\\n';\n    for (int i = 1; i < V_arm; ++i) {\n        cout << i-1 << \" 1\\n\";\n    }\n\n    // Initial root position (0,0)\n    root = Point(0, 0);\n    cout << root.x << ' ' << root.y << '\\n';\n\n    // Initialize edge directions (all right)\n    cur_dir.assign(V_arm - 1, 0);\n\n    int D = V_arm - 1; // total length of the arm\n\n    // Process each takoyaki\n    while (!pickups.empty()) {\n        // Find the closest pickup\n        int best_pickup_idx = -1;\n        int best_pickup_dist = INT_MAX;\n        Point best_pickup_root, best_pickup_offset;\n        for (int idx = 0; idx < (int)pickups.size(); ++idx) {\n            auto [cand_root, cand_offset] = find_best_root_offset(pickups[idx], root, D);\n            int dist = manhattan(root, cand_root);\n            if (dist < best_pickup_dist) {\n                best_pickup_dist = dist;\n                best_pickup_idx = idx;\n                best_pickup_root = cand_root;\n                best_pickup_offset = cand_offset;\n            }\n        }\n\n        // Move to the pickup root position\n        move_to(best_pickup_root);\n        // Change offset and grab\n        change_offset_and_act(best_pickup_offset.x, best_pickup_offset.y, 'P');\n        // Remove the pickup from the list\n        pickups.erase(pickups.begin() + best_pickup_idx);\n\n        // Find the closest dropoff\n        int best_dropoff_idx = -1;\n        int best_dropoff_dist = INT_MAX;\n        Point best_dropoff_root, best_dropoff_offset;\n        for (int idx = 0; idx < (int)dropoffs.size(); ++idx) {\n            auto [cand_root, cand_offset] = find_best_root_offset(dropoffs[idx], root, D);\n            int dist = manhattan(root, cand_root);\n            if (dist < best_dropoff_dist) {\n                best_dropoff_dist = dist;\n                best_dropoff_idx = idx;\n                best_dropoff_root = cand_root;\n                best_dropoff_offset = cand_offset;\n            }\n        }\n\n        // Move to the dropoff root position\n        move_to(best_dropoff_root);\n        // Change offset and release\n        change_offset_and_act(best_dropoff_offset.x, best_dropoff_offset.y, 'P');\n        // Remove the dropoff from the list\n        dropoffs.erase(dropoffs.begin() + best_dropoff_idx);\n    }\n\n    // Output all turns\n    for (const string& turn : output_turns) {\n        cout << turn << '\\n';\n    }\n\n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <cstring>\n\nusing namespace std;\n\nstruct Point {\n    int x, y, w;\n};\n\nstruct Node {\n    int sum;\n    int max_prefix, max_prefix_end;\n    int max_suffix, max_suffix_start;\n    int max_sub, max_sub_start, max_sub_end;\n};\n\nNode merge(const Node& l, const Node& r) {\n    Node res;\n    res.sum = l.sum + r.sum;\n\n    // max_prefix\n    if (l.max_prefix >= l.sum + r.max_prefix) {\n        res.max_prefix = l.max_prefix;\n        res.max_prefix_end = l.max_prefix_end;\n    } else {\n        res.max_prefix = l.sum + r.max_prefix;\n        res.max_prefix_end = r.max_prefix_end;\n    }\n\n    // max_suffix\n    if (r.max_suffix >= r.sum + l.max_suffix) {\n        res.max_suffix = r.max_suffix;\n        res.max_suffix_start = r.max_suffix_start;\n    } else {\n        res.max_suffix = r.sum + l.max_suffix;\n        res.max_suffix_start = l.max_suffix_start;\n    }\n\n    // max_sub\n    res.max_sub = l.max_sub;\n    res.max_sub_start = l.max_sub_start;\n    res.max_sub_end = l.max_sub_end;\n    if (r.max_sub > res.max_sub) {\n        res.max_sub = r.max_sub;\n        res.max_sub_start = r.max_sub_start;\n        res.max_sub_end = r.max_sub_end;\n    }\n    int cross = l.max_suffix + r.max_prefix;\n    if (cross > res.max_sub) {\n        res.max_sub = cross;\n        res.max_sub_start = l.max_suffix_start;\n        res.max_sub_end = r.max_prefix_end;\n    }\n    return res;\n}\n\nclass SegTree {\n    int n;\n    vector<int> leaf_vals;\n    vector<Node> tree;\n\n    void build(int node, int l, int r) {\n        if (l == r) {\n            int v = leaf_vals[l];\n            tree[node].sum = v;\n            tree[node].max_prefix = v;\n            tree[node].max_prefix_end = l;\n            tree[node].max_suffix = v;\n            tree[node].max_suffix_start = l;\n            tree[node].max_sub = v;\n            tree[node].max_sub_start = l;\n            tree[node].max_sub_end = l;\n        } else {\n            int mid = (l + r) / 2;\n            build(node * 2, l, mid);\n            build(node * 2 + 1, mid + 1, r);\n            tree[node] = merge(tree[node * 2], tree[node * 2 + 1]);\n        }\n    }\n\n    void update_tree(int node, int l, int r, int idx) {\n        if (l == r) {\n            int v = leaf_vals[l];\n            tree[node].sum = v;\n            tree[node].max_prefix = v;\n            tree[node].max_suffix = v;\n            tree[node].max_sub = v;\n        } else {\n            int mid = (l + r) / 2;\n            if (idx <= mid)\n                update_tree(node * 2, l, mid, idx);\n            else\n                update_tree(node * 2 + 1, mid + 1, r, idx);\n            tree[node] = merge(tree[node * 2], tree[node * 2 + 1]);\n        }\n    }\n\npublic:\n    SegTree(int size) : n(size), leaf_vals(size, 0), tree(4 * size) {\n        build(1, 0, n - 1);\n    }\n\n    void reset() {\n        fill(leaf_vals.begin(), leaf_vals.end(), 0);\n        build(1, 0, n - 1);\n    }\n\n    void update(int idx, int delta) {\n        leaf_vals[idx] += delta;\n        update_tree(1, 0, n - 1, idx);\n    }\n\n    Node query() {\n        return tree[1];\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<Point> points(2 * N);\n    for (int i = 0; i < 2 * N; ++i) {\n        cin >> points[i].x >> points[i].y;\n        points[i].w = (i < N) ? 1 : -1;\n    }\n\n    // coordinate compression\n    vector<int> xs, ys;\n    for (auto& p : points) {\n        xs.push_back(p.x);\n        ys.push_back(p.y);\n    }\n    sort(xs.begin(), xs.end());\n    xs.erase(unique(xs.begin(), xs.end()), xs.end());\n    sort(ys.begin(), ys.end());\n    ys.erase(unique(ys.begin(), ys.end()), ys.end());\n\n    int X = xs.size();\n    int Y = ys.size();\n\n    // group points by compressed x\n    vector<vector<pair<int, int>>> points_by_x(X);\n    for (auto& p : points) {\n        int xi = lower_bound(xs.begin(), xs.end(), p.x) - xs.begin();\n        int yi = lower_bound(ys.begin(), ys.end(), p.y) - ys.begin();\n        points_by_x[xi].emplace_back(yi, p.w);\n    }\n\n    // 2D prefix sum for fast rectangle queries\n    vector<vector<int>> pref(X + 1, vector<int>(Y + 1, 0));\n    for (int i = 0; i < X; ++i) {\n        for (auto& [yi, w] : points_by_x[i]) {\n            pref[i + 1][yi + 1] += w;\n        }\n    }\n    for (int i = 1; i <= X; ++i) {\n        for (int j = 1; j <= Y; ++j) {\n            pref[i][j] += pref[i - 1][j] + pref[i][j - 1] - pref[i - 1][j - 1];\n        }\n    }\n\n    auto rect_sum = [&](int l, int r, int b, int t) -> int {\n        return pref[r + 1][t + 1] - pref[l][t + 1] - pref[r + 1][b] + pref[l][b];\n    };\n\n    // initial candidate: the whole bounding box (score = 1)\n    int best_sum = 0;\n    int best_L = 0, best_R = X - 1, best_B = 0, best_T = Y - 1;\n\n    // segment tree search for the best rectangle\n    SegTree seg(Y);\n    for (int L = 0; L < X; ++L) {\n        seg.reset();\n        for (int R = L; R < X; ++R) {\n            for (auto& [yi, w] : points_by_x[R]) {\n                seg.update(yi, w);\n            }\n            if (R == L) continue;   // need positive width\n            Node res = seg.query();\n            if (res.max_sub > best_sum && res.max_sub_end - res.max_sub_start >= 1) {\n                best_sum = res.max_sub;\n                best_L = L;\n                best_R = R;\n                best_B = res.max_sub_start;\n                best_T = res.max_sub_end;\n            }\n        }\n    }\n\n    // local optimization by moving boundaries\n    int cur_sum = best_sum;\n    int L = best_L, R = best_R, B = best_B, T = best_T;\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        int best_improve = 0;\n        char best_type = 0;\n        int best_new_idx = -1;\n\n        // try moving left edge\n        for (int newL = 0; newL < X; ++newL) {\n            if (newL >= R) continue;\n            int new_sum = rect_sum(newL, R, B, T);\n            if (new_sum > cur_sum) {\n                int improve = new_sum - cur_sum;\n                if (improve > best_improve) {\n                    best_improve = improve;\n                    best_type = 'L';\n                    best_new_idx = newL;\n                }\n            }\n        }\n\n        // try moving right edge\n        for (int newR = 0; newR < X; ++newR) {\n            if (newR <= L) continue;\n            int new_sum = rect_sum(L, newR, B, T);\n            if (new_sum > cur_sum) {\n                int improve = new_sum - cur_sum;\n                if (improve > best_improve) {\n                    best_improve = improve;\n                    best_type = 'R';\n                    best_new_idx = newR;\n                }\n            }\n        }\n\n        // try moving bottom edge\n        for (int newB = 0; newB < Y; ++newB) {\n            if (newB >= T) continue;\n            int new_sum = rect_sum(L, R, newB, T);\n            if (new_sum > cur_sum) {\n                int improve = new_sum - cur_sum;\n                if (improve > best_improve) {\n                    best_improve = improve;\n                    best_type = 'B';\n                    best_new_idx = newB;\n                }\n            }\n        }\n\n        // try moving top edge\n        for (int newT = 0; newT < Y; ++newT) {\n            if (newT <= B) continue;\n            int new_sum = rect_sum(L, R, B, newT);\n            if (new_sum > cur_sum) {\n                int improve = new_sum - cur_sum;\n                if (improve > best_improve) {\n                    best_improve = improve;\n                    best_type = 'T';\n                    best_new_idx = newT;\n                }\n            }\n        }\n\n        if (best_improve > 0) {\n            improved = true;\n            if (best_type == 'L') L = best_new_idx;\n            else if (best_type == 'R') R = best_new_idx;\n            else if (best_type == 'B') B = best_new_idx;\n            else if (best_type == 'T') T = best_new_idx;\n            cur_sum = rect_sum(L, R, B, T);\n        }\n    }\n\n    // output the rectangle as a 4\u2011vertex polygon\n    cout << 4 << '\\n';\n    cout << xs[L] << ' ' << ys[B] << '\\n';\n    cout << xs[R] << ' ' << ys[B] << '\\n';\n    cout << xs[R] << ' ' << ys[T] << '\\n';\n    cout << xs[L] << ' ' << ys[T] << '\\n';\n\n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <tuple>\n\nusing namespace std;\n\nconst double p_place = 0.9; // probability to attempt placing a rectangle\n\nstruct Rectangle {\n    int x, y, w, h;\n    int right() const { return x + w; }\n    int bottom() const { return y + h; }\n};\n\n// Compute y0 for U placement given left edge x0 and width\nint compute_y0(int x0, int width, const vector<int>& placed_indices, const Rectangle rect_of_index[]) {\n    int y0 = 0;\n    for (int idx : placed_indices) {\n        const Rectangle& R = rect_of_index[idx];\n        if (x0 < R.right() && x0 + width > R.x) {\n            y0 = max(y0, R.bottom());\n        }\n    }\n    return y0;\n}\n\n// Compute x0 for L placement given top edge y0 and height\nint compute_x0(int y0, int height, const vector<int>& placed_indices, const Rectangle rect_of_index[]) {\n    int x0 = 0;\n    for (int idx : placed_indices) {\n        const Rectangle& R = rect_of_index[idx];\n        if (y0 < R.bottom() && y0 + height > R.y) {\n            x0 = max(x0, R.right());\n        }\n    }\n    return x0;\n}\n\nvoid solve_turn(int turn, const vector<int>& w, const vector<int>& h, int N, mt19937& rng) {\n    vector<int> placed_indices;          // indices of placed rectangles\n    Rectangle rect_of_index[N];          // stores rectangle data when placed\n    bool is_placed[N] = {false};\n    int W = 0, H = 0;                    // current bounding box\n\n    vector<tuple<int, int, char, int>> ops; // (p, r, d, b)\n\n    uniform_real_distribution<double> dist_real(0.0, 1.0);\n    uniform_int_distribution<int> dist_binary(0, 1);\n\n    for (int i = 0; i < N; ++i) {\n        // Decide whether to attempt placement\n        if (dist_real(rng) >= p_place) continue;\n\n        // Choose random rotation and direction\n        int r = dist_binary(rng);\n        char d = (dist_binary(rng) == 0) ? 'U' : 'L';\n        int width = (r == 0) ? w[i] : h[i];\n        int height = (r == 0) ? h[i] : w[i];\n\n        // Find best reference b for the chosen d, r\n        int best_b = -1;\n        int best_newW = W, best_newH = H;\n        int best_score = -1;\n\n        // List of possible b: -1 and all placed indices\n        vector<int> b_candidates = {-1};\n        for (int idx : placed_indices) b_candidates.push_back(idx);\n\n        for (int b : b_candidates) {\n            int x0, y0;\n            if (d == 'U') {\n                x0 = (b == -1) ? 0 : rect_of_index[b].right();\n                y0 = compute_y0(x0, width, placed_indices, rect_of_index);\n            } else { // 'L'\n                y0 = (b == -1) ? 0 : rect_of_index[b].bottom();\n                x0 = compute_x0(y0, height, placed_indices, rect_of_index);\n            }\n            int newW = max(W, x0 + width);\n            int newH = max(H, y0 + height);\n            int score = newW + newH;\n            if (best_b == -1 || score < best_score) {\n                best_b = b;\n                best_score = score;\n                best_newW = newW;\n                best_newH = newH;\n            }\n        }\n\n        // Check if placing is beneficial (using measured dimensions)\n        if (best_score <= W + H + w[i] + h[i]) {\n            // Perform placement\n            int x0, y0;\n            if (d == 'U') {\n                x0 = (best_b == -1) ? 0 : rect_of_index[best_b].right();\n                y0 = compute_y0(x0, width, placed_indices, rect_of_index);\n            } else {\n                y0 = (best_b == -1) ? 0 : rect_of_index[best_b].bottom();\n                x0 = compute_x0(y0, height, placed_indices, rect_of_index);\n            }\n            // Update state\n            rect_of_index[i] = {x0, y0, width, height};\n            is_placed[i] = true;\n            placed_indices.push_back(i);\n            W = best_newW;\n            H = best_newH;\n            ops.emplace_back(i, r, d, best_b);\n        }\n    }\n\n    // Output operations\n    cout << ops.size() << '\\n';\n    for (auto [p, r, d, b] : ops) {\n        cout << p << ' ' << r << ' ' << d << ' ' << b << '\\n';\n    }\n    cout.flush();\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T, sigma;\n    cin >> N >> T >> sigma;\n    vector<int> w(N), h(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> w[i] >> h[i];\n    }\n\n    // Random number generator\n    random_device rd;\n    mt19937 rng(rd());\n\n    for (int t = 0; t < T; ++t) {\n        solve_turn(t, w, h, N, rng);\n        // Read measured box dimensions (not used in this simple strategy)\n        int Wp, Hp;\n        cin >> Wp >> Hp;\n    }\n\n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <random>\n#include <cmath>\n#include <numeric>\n#include <chrono>\nusing namespace std;\n\nint N, H;\nvector<vector<int>> adj;\nvector<int> A;\n\n// Check if changing vertex v to newd is feasible (without modifying state)\nbool can_change(int v, int newd, const vector<int>& depth) {\n    // check v itself if newd > 0\n    if (newd > 0) {\n        bool has = false;\n        for (int u : adj[v]) {\n            if (depth[u] == newd - 1) {\n                has = true;\n                break;\n            }\n        }\n        if (!has) return false;\n    }\n    // check all neighbours\n    for (int u : adj[v]) {\n        if (depth[u] == 0) continue; // root has no constraint\n        bool has = false;\n        for (int w : adj[u]) {\n            int d_w = (w == v) ? newd : depth[w];\n            if (d_w == depth[u] - 1) {\n                has = true;\n                break;\n            }\n        }\n        if (!has) return false;\n    }\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    cin >> N >> M >> H;\n    A.resize(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n    adj.resize(N);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n    // read coordinates (unused)\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // ---------- 1. Compute H-neighborhoods ----------\n    vector<vector<int>> cover(N);\n    for (int v = 0; v < N; ++v) {\n        vector<int> dist(N, -1);\n        queue<int> q;\n        dist[v] = 0;\n        q.push(v);\n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            if (dist[u] > H) continue;\n            cover[v].push_back(u);\n            if (dist[u] == H) continue;\n            for (int w : adj[u]) {\n                if (dist[w] == -1) {\n                    dist[w] = dist[u] + 1;\n                    q.push(w);\n                }\n            }\n        }\n    }\n\n    // ---------- 2. Greedy set cover to choose roots ----------\n    vector<bool> covered(N, false);\n    vector<int> roots;\n    int remaining = N;\n    while (remaining > 0) {\n        int best_v = -1, best_cnt = -1;\n        for (int v = 0; v < N; ++v) {\n            int cnt = 0;\n            for (int u : cover[v]) if (!covered[u]) cnt++;\n            if (cnt > best_cnt || (cnt == best_cnt && (best_v == -1 || A[v] < A[best_v]))) {\n                best_cnt = cnt;\n                best_v = v;\n            }\n        }\n        roots.push_back(best_v);\n        for (int u : cover[best_v]) if (!covered[u]) {\n            covered[u] = true;\n            --remaining;\n        }\n    }\n\n    // ---------- 3. Multi-source BFS to get initial depths ----------\n    vector<int> depth(N, -1);\n    queue<int> q;\n    for (int r : roots) {\n        depth[r] = 0;\n        q.push(r);\n    }\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (int v : adj[u]) {\n            if (depth[v] == -1) {\n                depth[v] = depth[u] + 1;\n                q.push(v);\n            }\n        }\n    }\n    long long cur_obj = 0;\n    for (int v = 0; v < N; ++v) cur_obj += depth[v] * A[v];\n\n    // ---------- 4. Simulated Annealing ----------\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> rand_v(0, N-1);\n    uniform_int_distribution<int> rand_d(0, H);\n    uniform_real_distribution<double> rand_float(0.0, 1.0);\n\n    const int ITER = 1500000;\n    double temp = 1000.0;\n    const double cooling = 0.999995;\n\n    for (int iter = 0; iter < ITER; ++iter) {\n        int v = rand_v(rng);\n        int oldd = depth[v];\n        int newd = rand_d(rng);\n        if (newd == oldd) continue;\n        int delta = (newd - oldd) * A[v];\n\n        // feasibility check\n        if (!can_change(v, newd, depth)) continue;\n\n        // SA acceptance\n        if (delta >= 0 || rand_float(rng) < exp(delta / temp)) {\n            depth[v] = newd;\n            cur_obj += delta;\n        }\n        temp *= cooling;\n    }\n\n    // ---------- 5. Greedy improvement (high beauty first) ----------\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    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int v : order) {\n            while (depth[v] < H) {\n                int newd = depth[v] + 1;\n                if (can_change(v, newd, depth)) {\n                    depth[v] = newd;\n                    cur_obj += A[v];\n                    improved = true;\n                } else {\n                    break;\n                }\n            }\n        }\n    }\n\n    // ---------- 6. Build parent pointers ----------\n    vector<int> parent(N, -1);\n    for (int v = 0; v < N; ++v) {\n        if (depth[v] == 0) continue;\n        for (int u : adj[v]) {\n            if (depth[u] == depth[v] - 1) {\n                parent[v] = u;\n                break;\n            }\n        }\n    }\n\n    // ---------- 7. Output ----------\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << parent[i];\n    }\n    cout << endl;\n\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 20;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    int n;\n    cin >> n;\n    vector<string> board(n);\n    for (int i = 0; i < n; ++i) {\n        cin >> board[i];\n    }\n    \n    // Convert to mutable 2D vector\n    vector<vector<char>> grid(n, vector<char>(n));\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            grid[i][j] = board[i][j];\n        }\n    }\n    \n    // Directions: 0=up,1=down,2=left,3=right\n    // Costs: up: i+1, down: n-i, left: j+1, right: n-j\n    auto is_safe = [&](int i, int j, int dir) -> bool {\n        if (dir == 0) { // up\n            for (int r = 0; r < i; ++r) {\n                if (grid[r][j] == 'o') return false;\n            }\n            return true;\n        } else if (dir == 1) { // down\n            for (int r = i+1; r < n; ++r) {\n                if (grid[r][j] == 'o') return false;\n            }\n            return true;\n        } else if (dir == 2) { // left\n            for (int c = 0; c < j; ++c) {\n                if (grid[i][c] == 'o') return false;\n            }\n            return true;\n        } else { // right\n            for (int c = j+1; c < n; ++c) {\n                if (grid[i][c] == 'o') return false;\n            }\n            return true;\n        }\n    };\n    \n    int total_ops = 0;\n    while (true) {\n        // Find all Oni\n        vector<pair<int,int>> oni_list;\n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                if (grid[i][j] == 'x') {\n                    oni_list.emplace_back(i, j);\n                }\n            }\n        }\n        if (oni_list.empty()) break;\n        \n        // For each Oni, find minimal safe cost\n        int best_cost = 1e9;\n        int best_i = -1, best_j = -1, best_dir = -1;\n        for (auto [i, j] : oni_list) {\n            for (int dir = 0; dir < 4; ++dir) {\n                if (is_safe(i, j, dir)) {\n                    int cost;\n                    if (dir == 0) cost = i + 1;\n                    else if (dir == 1) cost = n - i;\n                    else if (dir == 2) cost = j + 1;\n                    else cost = n - j;\n                    if (cost < best_cost) {\n                        best_cost = cost;\n                        best_i = i;\n                        best_j = j;\n                        best_dir = dir;\n                    }\n                }\n            }\n        }\n        \n        // Perform the sequence\n        if (best_dir == 0) { // up\n            int k = best_i + 1;\n            for (int t = 0; t < k; ++t) cout << \"U \" << best_j << \"\\n\";\n            for (int t = 0; t < k; ++t) cout << \"D \" << best_j << \"\\n\";\n            // Update grid: clear rows 0..best_i in column best_j\n            for (int r = 0; r <= best_i; ++r) grid[r][best_j] = '.';\n        } else if (best_dir == 1) { // down\n            int k = n - best_i;\n            for (int t = 0; t < k; ++t) cout << \"D \" << best_j << \"\\n\";\n            for (int t = 0; t < k; ++t) cout << \"U \" << best_j << \"\\n\";\n            // Update grid: clear rows best_i..n-1 in column best_j\n            for (int r = best_i; r < n; ++r) grid[r][best_j] = '.';\n        } else if (best_dir == 2) { // left\n            int k = best_j + 1;\n            for (int t = 0; t < k; ++t) cout << \"L \" << best_i << \"\\n\";\n            for (int t = 0; t < k; ++t) cout << \"R \" << best_i << \"\\n\";\n            // Update grid: clear columns 0..best_j in row best_i\n            for (int c = 0; c <= best_j; ++c) grid[best_i][c] = '.';\n        } else { // right\n            int k = n - best_j;\n            for (int t = 0; t < k; ++t) cout << \"R \" << best_i << \"\\n\";\n            for (int t = 0; t < k; ++t) cout << \"L \" << best_i << \"\\n\";\n            // Update grid: clear columns best_j..n-1 in row best_i\n            for (int c = best_j; c < n; ++c) grid[best_i][c] = '.';\n        }\n        total_ops += 2 * best_cost;\n    }\n    \n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, L;\n    cin >> N >> L;\n    vector<int> T(N);\n    for (int i = 0; i < N; ++i) cin >> T[i];\n\n    // Random generator\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    // ---------- Greedy initialization ----------\n    vector<int> a(N), b(N);\n    vector<int> need(N);\n    need[0] = max(0, T[0] - 1);   // employee 0 gets one initial visit\n    for (int i = 1; i < N; ++i) need[i] = T[i];\n\n    // Supplies: each employee i provides two edges with weights ceil(T_i/2) and floor(T_i/2)\n    vector<tuple<int, int, int>> supplies; // weight, employee i, type (0 for a, 1 for b)\n    for (int i = 0; i < N; ++i) {\n        int odd = (T[i] + 1) / 2;  // ceil(T_i/2)\n        int even = T[i] / 2;       // floor(T_i/2)\n        supplies.emplace_back(odd, i, 0);\n        supplies.emplace_back(even, i, 1);\n    }\n    // Sort supplies by weight descending\n    sort(supplies.begin(), supplies.end(),\n         [](const auto& x, const auto& y) { return get<0>(x) > get<0>(y); });\n\n    // Priority queue for demands (remaining need, employee j)\n    priority_queue<pair<int, int>> pq;\n    for (int j = 0; j < N; ++j) {\n        if (need[j] > 0) pq.emplace(need[j], j);\n    }\n\n    // Assign each supply to the current highest demand\n    for (const auto& [weight, i, type] : supplies) {\n        if (pq.empty()) break;\n        auto [rem, j] = pq.top();\n        pq.pop();\n        if (type == 0) a[i] = j;\n        else b[i] = j;\n        rem -= weight;\n        if (rem > 0) pq.emplace(rem, j);\n    }\n    // If any demand remains, it will be ignored (edges already assigned to some j, possibly 0)\n\n    // ---------- Build transition table ----------\n    // nxt[i][0] = b_i, nxt[i][1] = a_i\n    array<array<int, 2>, 100> nxt;\n    for (int i = 0; i < N; ++i) {\n        nxt[i][0] = b[i];\n        nxt[i][1] = a[i];\n    }\n\n    // ---------- Simulation function ----------\n    auto simulate = [&]() {\n        int cnt[100];\n        memset(cnt, 0, sizeof(cnt));\n        cnt[0] = 1;\n        int cur = 0;\n        int steps = L - 1;\n        while (steps--) {\n            int parity = cnt[cur] & 1;\n            int next_emp = nxt[cur][parity];\n            ++cnt[next_emp];\n            cur = next_emp;\n        }\n        int error = 0;\n        for (int i = 0; i < N; ++i) {\n            error += abs(cnt[i] - T[i]);\n        }\n        return error;\n    };\n\n    int cur_error = simulate();\n    int best_error = cur_error;\n    vector<int> best_a = a, best_b = b;\n\n    // ---------- Simulated Annealing ----------\n    double temp = 1000.0;\n    const double cooling = 0.998;\n    auto start_time = chrono::steady_clock::now();\n    const double time_limit = 1.9; // seconds\n    uniform_real_distribution<double> dist(0.0, 1.0);\n\n    int iter = 0;\n    while (true) {\n        if ((iter & 63) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > time_limit) break;\n        }\n        ++iter;\n\n        // Choose random edge\n        int i = rng() % N;\n        int type = rng() % 2; // 0 -> a_i, 1 -> b_i\n        int old_val = (type == 0) ? a[i] : b[i];\n        int new_val = rng() % N;\n        if (new_val == old_val) continue;\n\n        // Apply change\n        if (type == 0) {\n            a[i] = new_val;\n            nxt[i][1] = new_val;\n        } else {\n            b[i] = new_val;\n            nxt[i][0] = new_val;\n        }\n\n        int new_error = simulate();\n        int delta = new_error - cur_error;\n\n        bool accept = false;\n        if (delta < 0) {\n            accept = true;\n        } else {\n            double prob = exp(-delta / temp);\n            if (dist(rng) < prob) accept = true;\n        }\n\n        if (accept) {\n            cur_error = new_error;\n            if (cur_error < best_error) {\n                best_error = cur_error;\n                best_a = a;\n                best_b = b;\n                if (best_error == 0) break; // optimal\n            }\n        } else {\n            // Revert\n            if (type == 0) {\n                a[i] = old_val;\n                nxt[i][1] = old_val;\n            } else {\n                b[i] = old_val;\n                nxt[i][0] = old_val;\n            }\n        }\n\n        // Cool down\n        temp *= cooling;\n    }\n\n    // ---------- Output ----------\n    for (int i = 0; i < N; ++i) {\n        cout << best_a[i] << \" \" << best_b[i] << \"\\n\";\n    }\n\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\n#include <boost/geometry.hpp>\n#include <boost/geometry/index/rtree.hpp>\n\nnamespace bg = boost::geometry;\nnamespace bgi = boost::geometry::index;\n\nusing point = bg::model::point<double, 2, bg::cs::cartesian>;\nusing box = bg::model::box<point>;\nusing value = std::pair<box, int>;\n\n// Hilbert value computation for ordering\ninline uint32_t hilbertOrder(int x, int y, int iterations = 10) {\n    uint32_t d = 0;\n    for (int s = 1 << (iterations - 1); s > 0; s >>= 1) {\n        bool rx = (x & s) > 0;\n        bool ry = (y & s) > 0;\n        d = (d << 2) | ((rx ? 1 : 0) * 3) ^ (ry ? 1 : 0);\n        if (!ry) {\n            if (rx) {\n                x = (1 << iterations) - 1 - x;\n                y = (1 << iterations) - 1 - y;\n            }\n            std::swap(x, y);\n        }\n    }\n    return d;\n}\n\nint main() {\n    std::ios::sync_with_stdio(false);\n    std::cin.tie(nullptr);\n\n    int N, M, Q, L, W;\n    std::cin >> N >> M >> Q >> L >> W;\n\n    std::vector<int> G(M);\n    for (int i = 0; i < M; ++i) {\n        std::cin >> G[i];\n    }\n\n    std::vector<int> lx(N), rx(N), ly(N), ry(N);\n    std::vector<double> cx(N), cy(N);\n    std::vector<box> boxes(N);\n    \n    for (int i = 0; i < N; ++i) {\n        std::cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n        cx[i] = (lx[i] + rx[i]) / 2.0;\n        cy[i] = (ly[i] + ry[i]) / 2.0;\n        boxes[i] = box(point(lx[i], ly[i]), point(rx[i], ry[i]));\n    }\n\n    // Create R-tree for spatial queries\n    bgi::rtree<value, bgi::quadratic<16>> rtree;\n    for (int i = 0; i < N; ++i) {\n        rtree.insert(std::make_pair(boxes[i], i));\n    }\n\n    // Order cities by Hilbert curve for better spatial locality\n    std::vector<int> order(N);\n    std::iota(order.begin(), order.end(), 0);\n    std::sort(order.begin(), order.end(), [&](int i, int j) {\n        // Scale coordinates to [0, 2^20) for Hilbert curve\n        int xi = static_cast<int>((cx[i] / 10000.0) * (1 << 20));\n        int yi = static_cast<int>((cy[i] / 10000.0) * (1 << 20));\n        int xj = static_cast<int>((cx[j] / 10000.0) * (1 << 20));\n        int yj = static_cast<int>((cy[j] / 10000.0) * (1 << 20));\n        return hilbertOrder(xi, yi) < hilbertOrder(xj, yj);\n    });\n\n    // Cluster cities into groups using a balanced approach\n    std::vector<std::vector<int>> groups(M);\n    std::vector<bool> used(N, false);\n    \n    for (int k = 0; k < M; ++k) {\n        if (groups[k].size() == G[k]) continue;\n        \n        // Find the city with smallest uncertainty that hasn't been assigned\n        int start = -1;\n        double min_area = 1e18;\n        for (int i : order) {\n            if (!used[i]) {\n                double area = (rx[i] - lx[i]) * (ry[i] - ly[i]);\n                if (area < min_area) {\n                    min_area = area;\n                    start = i;\n                }\n            }\n        }\n        \n        // If no unassigned city, break (shouldn't happen)\n        if (start == -1) break;\n        \n        // Use BFS to collect nearby cities for this group\n        std::queue<int> q;\n        q.push(start);\n        used[start] = true;\n        groups[k].push_back(start);\n        \n        while (!q.empty() && groups[k].size() < G[k]) {\n            int curr = q.front();\n            q.pop();\n            \n            // Query R-tree for nearest cities\n            std::vector<value> results;\n            point center(cx[curr], cy[curr]);\n            rtree.query(bgi::nearest(center, 10), std::back_inserter(results));\n            \n            for (const auto& [box, idx] : results) {\n                if (!used[idx] && groups[k].size() < G[k]) {\n                    used[idx] = true;\n                    groups[k].push_back(idx);\n                    q.push(idx);\n                }\n            }\n        }\n        \n        // If we still need more cities, add the closest available\n        while (groups[k].size() < G[k]) {\n            double min_dist = 1e18;\n            int best = -1;\n            for (int i = 0; i < N; ++i) {\n                if (!used[i]) {\n                    double dx = cx[groups[k][0]] - cx[i];\n                    double dy = cy[groups[k][0]] - cy[i];\n                    double dist = dx*dx + dy*dy;\n                    if (dist < min_dist) {\n                        min_dist = dist;\n                        best = i;\n                    }\n                }\n            }\n            if (best != -1) {\n                used[best] = true;\n                groups[k].push_back(best);\n            } else {\n                break; // Shouldn't happen if sum G_i = N\n            }\n        }\n    }\n\n    std::vector<std::vector<std::pair<int, int>>> group_edges(M);\n    int query_count = 0;\n\n    // First pass: Use basic sliding window queries\n    for (int k = 0; k < M; ++k) {\n        const auto& cities = groups[k];\n        int g = cities.size();\n        if (g == 1) continue;\n\n        if (g <= L) {\n            std::cout << \"? \" << g;\n            for (int city : cities) std::cout << \" \" << city;\n            std::cout << std::endl;\n            std::cout.flush();\n            \n            for (int i = 0; i < g - 1; ++i) {\n                int a, b;\n                std::cin >> a >> b;\n                group_edges[k].emplace_back(a, b);\n            }\n            query_count++;\n        } else {\n            int step = L - 1;\n            int windows = (g - 1 + step - 1) / step;\n            for (int w = 0; w < windows; ++w) {\n                int start = w * step;\n                int end = std::min(start + L, g);\n                int sz = end - start;\n                \n                std::cout << \"? \" << sz;\n                for (int i = start; i < end; ++i) {\n                    std::cout << \" \" << cities[i];\n                }\n                std::cout << std::endl;\n                std::cout.flush();\n                \n                for (int i = 0; i < sz - 1; ++i) {\n                    int a, b;\n                    std::cin >> a >> b;\n                    group_edges[k].emplace_back(a, b);\n                }\n                query_count++;\n            }\n        }\n    }\n\n    // Second pass: Use remaining queries to improve largest groups\n    int remaining_queries = Q - query_count;\n    if (remaining_queries > 0) {\n        // Sort groups by size descending\n        std::vector<int> group_indices(M);\n        std::iota(group_indices.begin(), group_indices.end(), 0);\n        std::sort(group_indices.begin(), group_indices.end(), \n                 [&](int a, int b) { return groups[a].size() > groups[b].size(); });\n        \n        for (int k : group_indices) {\n            if (remaining_queries <= 0) break;\n            \n            const auto& cities = groups[k];\n            int g = cities.size();\n            if (g <= L) continue; // Already optimal\n            \n            // Add extra overlapping windows for this group\n            int extra_windows = std::min(remaining_queries, (g - L) / 2 + 1);\n            for (int w = 0; w < extra_windows; ++w) {\n                int start = w * 2; // Step of 2 for more overlap\n                if (start + L > g) break;\n                \n                std::cout << \"? \" << L;\n                for (int i = start; i < start + L; ++i) {\n                    std::cout << \" \" << cities[i];\n                }\n                std::cout << std::endl;\n                std::cout.flush();\n                \n                for (int i = 0; i < L - 1; ++i) {\n                    int a, b;\n                    std::cin >> a >> b;\n                    group_edges[k].emplace_back(a, b);\n                }\n                remaining_queries--;\n            }\n            \n            // Run Kruskal on collected edges using lower-bound distances\n            if (group_edges[k].size() > g - 1) {\n                // Build adjacency list with lower-bound distances\n                std::vector<std::tuple<double, int, int>> edges_with_weights;\n                for (const auto& [a, b] : group_edges[k]) {\n                    // Compute lower-bound distance between rectangles\n                    double dx = std::max({0.0, \n                                        static_cast<double>(lx[a] - rx[b]),\n                                        static_cast<double>(lx[b] - rx[a])});\n                    double dy = std::max({0.0, \n                                        static_cast<double>(ly[a] - ry[b]),\n                                        static_cast<double>(ly[b] - ry[a])});\n                    double lb_dist = std::sqrt(dx*dx + dy*dy);\n                    edges_with_weights.emplace_back(lb_dist, a, b);\n                }\n                \n                // Kruskal's algorithm\n                std::sort(edges_with_weights.begin(), edges_with_weights.end());\n                std::vector<int> parent(N);\n                std::iota(parent.begin(), parent.end(), 0);\n                \n                auto find = [&](int x) {\n                    while (parent[x] != x) {\n                        parent[x] = parent[parent[x]];\n                        x = parent[x];\n                    }\n                    return x;\n                };\n                \n                group_edges[k].clear();\n                for (const auto& [w, a, b] : edges_with_weights) {\n                    int ra = find(a), rb = find(b);\n                    if (ra != rb) {\n                        parent[ra] = rb;\n                        group_edges[k].emplace_back(a, b);\n                        if (group_edges[k].size() == g - 1) break;\n                    }\n                }\n            }\n        }\n    }\n\n    // Output answer\n    std::cout << \"!\" << std::endl;\n    for (int k = 0; k < M; ++k) {\n        // Output cities in the group\n        for (size_t i = 0; i < groups[k].size(); ++i) {\n            if (i > 0) std::cout << \" \";\n            std::cout << groups[k][i];\n        }\n        std::cout << std::endl;\n        \n        // Output edges\n        for (const auto& [a, b] : group_edges[k]) {\n            std::cout << a << \" \" << b << std::endl;\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n    vector<pair<int, int>> pts(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> pts[i].first >> pts[i].second;\n    }\n\n    vector<string> actions;\n\n    for (int i = 0; i < M - 1; ++i) {\n        int r1 = pts[i].first, c1 = pts[i].second;\n        int r2 = pts[i + 1].first, c2 = pts[i + 1].second;\n\n        // ----- compute costs of the nine possible plans -----\n        int direct = abs(r1 - r2) + abs(c1 - c2);\n\n        int costU = (r1 > 0 ? 1 : 0) + abs(c1 - c2) + r2;\n        int costD = (r1 < N - 1 ? 1 : 0) + abs(c1 - c2) + (N - 1 - r2);\n        int costL = (c1 > 0 ? 1 : 0) + abs(r1 - r2) + c2;\n        int costR = (c1 < N - 1 ? 1 : 0) + abs(r1 - r2) + (N - 1 - c2);\n\n        // Corner plans\n        int costTL = (r1 > 0 ? 1 : 0) + (c1 > 0 ? 1 : 0) + r2 + c2;\n        int costTR = (r1 > 0 ? 1 : 0) + (c1 < N - 1 ? 1 : 0) + r2 + (N - 1 - c2);\n        int costBL = (r1 < N - 1 ? 1 : 0) + (c1 > 0 ? 1 : 0) + (N - 1 - r2) + c2;\n        int costBR = (r1 < N - 1 ? 1 : 0) + (c1 < N - 1 ? 1 : 0) + (N - 1 - r2) + (N - 1 - c2);\n\n        // ----- choose the cheapest plan -----\n        int best = direct;\n        int option = 0; // 0:direct, 1:up, 2:down, 3:left, 4:right, 5:TL, 6:TR, 7:BL, 8:BR\n        if (costU < best) { best = costU; option = 1; }\n        if (costD < best) { best = costD; option = 2; }\n        if (costL < best) { best = costL; option = 3; }\n        if (costR < best) { best = costR; option = 4; }\n        if (costTL < best) { best = costTL; option = 5; }\n        if (costTR < best) { best = costTR; option = 6; }\n        if (costBL < best) { best = costBL; option = 7; }\n        if (costBR < best) { best = costBR; option = 8; }\n\n        // ----- generate the actions for the chosen plan -----\n        switch (option) {\n            case 0: // direct moves\n                if (r2 > r1) {\n                    for (int k = 0; k < r2 - r1; ++k) actions.push_back(\"M D\");\n                } else if (r2 < r1) {\n                    for (int k = 0; k < r1 - r2; ++k) actions.push_back(\"M U\");\n                }\n                if (c2 > c1) {\n                    for (int k = 0; k < c2 - c1; ++k) actions.push_back(\"M R\");\n                } else if (c2 < c1) {\n                    for (int k = 0; k < c1 - c2; ++k) actions.push_back(\"M L\");\n                }\n                break;\n\n            case 1: // Up\n                if (r1 > 0) actions.push_back(\"S U\");\n                if (c2 > c1) {\n                    for (int k = 0; k < c2 - c1; ++k) actions.push_back(\"M R\");\n                } else if (c2 < c1) {\n                    for (int k = 0; k < c1 - c2; ++k) actions.push_back(\"M L\");\n                }\n                if (r2 > 0) {\n                    for (int k = 0; k < r2; ++k) actions.push_back(\"M D\");\n                }\n                break;\n\n            case 2: // Down\n                if (r1 < N - 1) actions.push_back(\"S D\");\n                if (c2 > c1) {\n                    for (int k = 0; k < c2 - c1; ++k) actions.push_back(\"M R\");\n                } else if (c2 < c1) {\n                    for (int k = 0; k < c1 - c2; ++k) actions.push_back(\"M L\");\n                }\n                if (r2 < N - 1) {\n                    int steps = N - 1 - r2;\n                    for (int k = 0; k < steps; ++k) actions.push_back(\"M U\");\n                }\n                break;\n\n            case 3: // Left\n                if (c1 > 0) actions.push_back(\"S L\");\n                if (r2 > r1) {\n                    for (int k = 0; k < r2 - r1; ++k) actions.push_back(\"M D\");\n                } else if (r2 < r1) {\n                    for (int k = 0; k < r1 - r2; ++k) actions.push_back(\"M U\");\n                }\n                if (c2 > 0) {\n                    for (int k = 0; k < c2; ++k) actions.push_back(\"M R\");\n                }\n                break;\n\n            case 4: // Right\n                if (c1 < N - 1) actions.push_back(\"S R\");\n                if (r2 > r1) {\n                    for (int k = 0; k < r2 - r1; ++k) actions.push_back(\"M D\");\n                } else if (r2 < r1) {\n                    for (int k = 0; k < r1 - r2; ++k) actions.push_back(\"M U\");\n                }\n                if (c2 < N - 1) {\n                    int steps = N - 1 - c2;\n                    for (int k = 0; k < steps; ++k) actions.push_back(\"M L\");\n                }\n                break;\n\n            case 5: // Top-left corner\n                if (r1 > 0) actions.push_back(\"S U\");\n                if (c1 > 0) actions.push_back(\"S L\");\n                // now at (0,0)\n                if (c2 > 0) {\n                    for (int k = 0; k < c2; ++k) actions.push_back(\"M R\");\n                }\n                if (r2 > 0) {\n                    for (int k = 0; k < r2; ++k) actions.push_back(\"M D\");\n                }\n                break;\n\n            case 6: // Top-right corner\n                if (r1 > 0) actions.push_back(\"S U\");\n                if (c1 < N - 1) actions.push_back(\"S R\");\n                // now at (0,N-1)\n                if (r2 > 0) {\n                    for (int k = 0; k < r2; ++k) actions.push_back(\"M D\");\n                }\n                if (c2 < N - 1) {\n                    int steps = N - 1 - c2;\n                    for (int k = 0; k < steps; ++k) actions.push_back(\"M L\");\n                }\n                break;\n\n            case 7: // Bottom-left corner\n                if (r1 < N - 1) actions.push_back(\"S D\");\n                if (c1 > 0) actions.push_back(\"S L\");\n                // now at (N-1,0)\n                if (r2 < N - 1) {\n                    int steps = N - 1 - r2;\n                    for (int k = 0; k < steps; ++k) actions.push_back(\"M U\");\n                }\n                if (c2 > 0) {\n                    for (int k = 0; k < c2; ++k) actions.push_back(\"M R\");\n                }\n                break;\n\n            case 8: // Bottom-right corner\n                if (r1 < N - 1) actions.push_back(\"S D\");\n                if (c1 < N - 1) actions.push_back(\"S R\");\n                // now at (N-1,N-1)\n                if (r2 < N - 1) {\n                    int steps = N - 1 - r2;\n                    for (int k = 0; k < steps; ++k) actions.push_back(\"M U\");\n                }\n                if (c2 < N - 1) {\n                    int steps = N - 1 - c2;\n                    for (int k = 0; k < steps; ++k) actions.push_back(\"M L\");\n                }\n                break;\n        }\n    }\n\n    // ----- output all actions -----\n    for (const string& act : actions) {\n        cout << act << '\\n';\n    }\n\n    return 0;\n}"},"4":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\n\nstruct Company {\n    int x, y, r;\n};\n\nstruct Node {\n    int x1, y1, x2, y2;\n    vector<int> ids;\n    int cut_type;   // 0: leaf, 1: vertical, 2: horizontal\n    int cut_pos;\n    Node *left, *right;\n    ll total_r;\n    Node() : left(nullptr), right(nullptr) {}\n};\n\nint n;\nvector<Company> comps;\nvector<int> a, b, c, d;\n\nNode* build(int x1, int y1, int x2, int y2, vector<int>& ids) {\n    Node* node = new Node();\n    node->x1 = x1; node->y1 = y1; node->x2 = x2; node->y2 = y2;\n    node->ids = ids;\n\n    if (ids.size() == 1) {\n        node->cut_type = 0;\n        node->total_r = comps[ids[0]].r;\n        return node;\n    }\n\n    ll total_r = 0;\n    for (int i : ids) total_r += comps[i].r;\n    node->total_r = total_r;\n\n    int min_x = 10000, max_x = 0, min_y = 10000, max_y = 0;\n    for (int i : ids) {\n        min_x = min(min_x, comps[i].x);\n        max_x = max(max_x, comps[i].x);\n        min_y = min(min_y, comps[i].y);\n        max_y = max(max_y, comps[i].y);\n    }\n\n    ll best_cost = LLONG_MAX;\n    int best_type = -1;\n    int best_pos = -1;\n    double best_aspect = 1e9; // for tie-breaking\n\n    // Vertical cuts\n    if (max_x > min_x) {\n        for (int X = x1 + 1; X < x2; ++X) {\n            if (X <= min_x || X > max_x) continue;\n            ll left_sum = 0;\n            int left_count = 0;\n            for (int i : ids) {\n                if (comps[i].x < X) {\n                    left_sum += comps[i].r;\n                    left_count++;\n                }\n            }\n            if (left_count == 0 || left_count == ids.size()) continue;\n            \n            ll left_area = (ll)(X - x1) * (y2 - y1);\n            ll right_sum = total_r - left_sum;\n            ll right_area = (ll)(x2 - X) * (y2 - y1);\n            ll cost = abs(left_area - left_sum) + abs(right_area - right_sum);\n            \n            double aspect = max((double)(X - x1) / (y2 - y1), (double)(x2 - X) / (y2 - y1));\n            if (cost < best_cost || (cost == best_cost && aspect < best_aspect)) {\n                best_cost = cost;\n                best_type = 1;\n                best_pos = X;\n                best_aspect = aspect;\n            }\n        }\n    }\n\n    // Horizontal cuts\n    if (max_y > min_y) {\n        for (int Y = y1 + 1; Y < y2; ++Y) {\n            if (Y <= min_y || Y > max_y) continue;\n            ll bottom_sum = 0;\n            int bottom_count = 0;\n            for (int i : ids) {\n                if (comps[i].y < Y) {\n                    bottom_sum += comps[i].r;\n                    bottom_count++;\n                }\n            }\n            if (bottom_count == 0 || bottom_count == ids.size()) continue;\n            \n            ll bottom_area = (ll)(x2 - x1) * (Y - y1);\n            ll top_sum = total_r - bottom_sum;\n            ll top_area = (ll)(x2 - x1) * (y2 - Y);\n            ll cost = abs(bottom_area - bottom_sum) + abs(top_area - top_sum);\n            \n            double aspect = max((double)(x2 - x1) / (Y - y1), (double)(x2 - x1) / (y2 - Y));\n            if (cost < best_cost || (cost == best_cost && aspect < best_aspect)) {\n                best_cost = cost;\n                best_type = 2;\n                best_pos = Y;\n                best_aspect = aspect;\n            }\n        }\n    }\n\n    // If no valid cut found (shouldn't happen), split at midpoint\n    if (best_type == -1) {\n        if (max_x > min_x) {\n            best_type = 1;\n            best_pos = (min_x + max_x + 1) / 2;\n            best_pos = max(x1 + 1, min(x2 - 1, best_pos));\n        } else {\n            best_type = 2;\n            best_pos = (min_y + max_y + 1) / 2;\n            best_pos = max(y1 + 1, min(y2 - 1, best_pos));\n        }\n    }\n\n    if (best_type == 1) {\n        vector<int> left_ids, right_ids;\n        for (int i : ids) {\n            if (comps[i].x < best_pos) left_ids.push_back(i);\n            else right_ids.push_back(i);\n        }\n        node->cut_type = 1;\n        node->cut_pos = best_pos;\n        node->left = build(x1, y1, best_pos, y2, left_ids);\n        node->right = build(best_pos, y1, x2, y2, right_ids);\n    } else {\n        vector<int> bottom_ids, top_ids;\n        for (int i : ids) {\n            if (comps[i].y < best_pos) bottom_ids.push_back(i);\n            else top_ids.push_back(i);\n        }\n        node->cut_type = 2;\n        node->cut_pos = best_pos;\n        node->left = build(x1, y1, x2, best_pos, bottom_ids);\n        node->right = build(x1, best_pos, x2, y2, top_ids);\n    }\n\n    return node;\n}\n\nvoid optimize(Node* node) {\n    if (node->cut_type == 0) return;\n\n    if (node->cut_type == 1) {\n        Node* left = node->left;\n        Node* right = node->right;\n\n        // Find the range where we can move the cut without changing point assignments\n        int max_x_left = -1;\n        for (int i : left->ids) max_x_left = max(max_x_left, comps[i].x);\n        int min_x_right = 10000;\n        for (int i : right->ids) min_x_right = min(min_x_right, comps[i].x);\n\n        int lower = max(node->x1 + 1, max_x_left + 1);\n        int upper = min(node->x2 - 1, min_x_right);\n\n        // Also consider moving across point boundaries if it improves score\n        for (int X = node->x1 + 1; X < node->x2; ++X) {\n            if (X == node->cut_pos) continue;\n            \n            // Check if this move would change assignments\n            bool changes_assignment = false;\n            for (int i : node->ids) {\n                if ((comps[i].x < node->cut_pos && comps[i].x >= X) ||\n                    (comps[i].x >= node->cut_pos && comps[i].x < X)) {\n                    changes_assignment = true;\n                    break;\n                }\n            }\n            \n            if (!changes_assignment && X >= lower && X <= upper) {\n                // This move keeps assignments, compute potential improvement\n                ll left_sum = left->total_r;\n                ll right_sum = right->total_r;\n                int H = node->y2 - node->y1;\n                ll left_area = (ll)(X - node->x1) * H;\n                ll right_area = (ll)(node->x2 - X) * H;\n                ll new_cost = abs(left_area - left_sum) + abs(right_area - right_sum);\n                ll old_cost = abs((node->cut_pos - node->x1) * H - left_sum) + \n                             abs((node->x2 - node->cut_pos) * H - right_sum);\n                \n                if (new_cost < old_cost) {\n                    node->cut_pos = X;\n                    left->x2 = X;\n                    right->x1 = X;\n                }\n            }\n        }\n        \n        optimize(left);\n        optimize(right);\n    }\n    else if (node->cut_type == 2) {\n        Node* left = node->left;\n        Node* right = node->right;\n\n        int max_y_bottom = -1;\n        for (int i : left->ids) max_y_bottom = max(max_y_bottom, comps[i].y);\n        int min_y_top = 10000;\n        for (int i : right->ids) min_y_top = min(min_y_top, comps[i].y);\n\n        int lower = max(node->y1 + 1, max_y_bottom + 1);\n        int upper = min(node->y2 - 1, min_y_top);\n\n        for (int Y = node->y1 + 1; Y < node->y2; ++Y) {\n            if (Y == node->cut_pos) continue;\n            \n            bool changes_assignment = false;\n            for (int i : node->ids) {\n                if ((comps[i].y < node->cut_pos && comps[i].y >= Y) ||\n                    (comps[i].y >= node->cut_pos && comps[i].y < Y)) {\n                    changes_assignment = true;\n                    break;\n                }\n            }\n            \n            if (!changes_assignment && Y >= lower && Y <= upper) {\n                ll bottom_sum = left->total_r;\n                ll top_sum = right->total_r;\n                int W = node->x2 - node->x1;\n                ll bottom_area = (ll)W * (Y - node->y1);\n                ll top_area = (ll)W * (node->y2 - Y);\n                ll new_cost = abs(bottom_area - bottom_sum) + abs(top_area - top_sum);\n                ll old_cost = abs(W * (node->cut_pos - node->y1) - bottom_sum) + \n                             abs(W * (node->y2 - node->cut_pos) - top_sum);\n                \n                if (new_cost < old_cost) {\n                    node->cut_pos = Y;\n                    left->y2 = Y;\n                    right->y1 = Y;\n                }\n            }\n        }\n        \n        optimize(left);\n        optimize(right);\n    }\n}\n\nvoid collect(Node* node) {\n    if (node->cut_type == 0) {\n        int i = node->ids[0];\n        a[i] = node->x1;\n        b[i] = node->y1;\n        c[i] = node->x2;\n        d[i] = node->y2;\n        return;\n    }\n    collect(node->left);\n    collect(node->right);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n;\n    comps.resize(n);\n    for (int i = 0; i < n; ++i)\n        cin >> comps[i].x >> comps[i].y >> comps[i].r;\n\n    a.resize(n); b.resize(n); c.resize(n); d.resize(n);\n\n    // Try multiple random orders to escape local optima\n    vector<int> ids(n);\n    iota(ids.begin(), ids.end(), 0);\n    \n    Node* best_root = nullptr;\n    ll best_total_cost = LLONG_MAX;\n    \n    // Try 5 different random permutations\n    for (int trial = 0; trial < 5; ++trial) {\n        if (trial > 0) {\n            shuffle(ids.begin(), ids.end(), mt19937(random_device{}()));\n        }\n        \n        Node* root = build(0, 0, 10000, 10000, ids);\n        optimize(root);\n        \n        // Compute total cost\n        vector<int> temp_a(n), temp_b(n), temp_c(n), temp_d(n);\n        auto collect_temp = [&](Node* node, auto&& self) -> void {\n            if (node->cut_type == 0) {\n                int i = node->ids[0];\n                temp_a[i] = node->x1;\n                temp_b[i] = node->y1;\n                temp_c[i] = node->x2;\n                temp_d[i] = node->y2;\n                return;\n            }\n            self(node->left, self);\n            self(node->right, self);\n        };\n        collect_temp(root, collect_temp);\n        \n        ll total_cost = 0;\n        for (int i = 0; i < n; ++i) {\n            ll area = (ll)(temp_c[i] - temp_a[i]) * (temp_d[i] - temp_b[i]);\n            total_cost += abs(area - comps[i].r);\n        }\n        \n        if (total_cost < best_total_cost) {\n            best_total_cost = total_cost;\n            best_root = root;\n            a = temp_a;\n            b = temp_b;\n            c = temp_c;\n            d = temp_d;\n        }\n    }\n\n    for (int i = 0; i < n; ++i)\n        cout << a[i] << ' ' << b[i] << ' ' << c[i] << ' ' << d[i] << '\\n';\n\n    return 0;\n}","ahc002":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <cassert>\n#include <tuple>\n#include <set>\n\nusing namespace std;\n\nconst int N = 50;\nconst int dr[4] = {-1, 1, 0, 0};\nconst int dc[4] = {0, 0, -1, 1};\nconst char dir_char[4] = {'U', 'D', 'L', 'R'};\n\nstruct Neighbor {\n    int r, c;\n    char dir;\n};\n\n// Get valid neighbors from (r,c) given visited tiles.\nvector<Neighbor> get_neighbors(int r, int c, const vector<char>& visited,\n                               const vector<vector<int>>& tile_id) {\n    vector<Neighbor> res;\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) {\n            int tile = tile_id[nr][nc];\n            if (!visited[tile]) {\n                res.push_back({nr, nc, dir_char[d]});\n            }\n        }\n    }\n    return res;\n}\n\n// Count unvisited neighbors for a tile (considering all squares in the tile)\nint count_unvisited_neighbors(const pair<int,int>& square,\n                              const vector<char>& visited,\n                              const vector<vector<int>>& tile_id) {\n    int count = 0;\n    set<int> neighboring_tiles;\n    for (int d = 0; d < 4; ++d) {\n        int nr = square.first + dr[d], nc = square.second + dc[d];\n        if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n            int tile = tile_id[nr][nc];\n            if (!visited[tile] && neighboring_tiles.find(tile) == neighboring_tiles.end()) {\n                count++;\n                neighboring_tiles.insert(tile);\n            }\n        }\n    }\n    return count;\n}\n\n// Greedily extend the path from the last square with lookahead.\nvoid extend_greedy(vector<pair<int,int>>& path, vector<int>& tiles,\n                   vector<char>& visited, int& score,\n                   const vector<vector<int>>& p,\n                   const vector<vector<int>>& tile_id,\n                   mt19937& rng) {\n    while (true) {\n        int r = path.back().first, c = path.back().second;\n        auto candidates = get_neighbors(r, c, visited, tile_id);\n        if (candidates.empty()) break;\n        \n        // Score each candidate by p and number of unvisited neighbors\n        vector<pair<double, int>> candidate_scores;\n        for (size_t i = 0; i < candidates.size(); ++i) {\n            const auto& cand = candidates[i];\n            double score_val = p[cand.r][cand.c];\n            // Add bonus for having more unvisited neighbors (helps avoid dead ends)\n            int neighbor_count = count_unvisited_neighbors({cand.r, cand.c}, visited, tile_id);\n            score_val += 0.1 * neighbor_count;\n            candidate_scores.emplace_back(score_val, i);\n        }\n        \n        // Choose with probability proportional to score (softmax-like)\n        vector<double> weights;\n        for (const auto& cs : candidate_scores) {\n            weights.push_back(exp(cs.first / 10.0));\n        }\n        discrete_distribution<int> dist(weights.begin(), weights.end());\n        int idx = dist(rng);\n        \n        const auto& cand = candidates[idx];\n        path.push_back({cand.r, cand.c});\n        tiles.push_back(tile_id[cand.r][cand.c]);\n        visited[tile_id[cand.r][cand.c]] = 1;\n        score += p[cand.r][cand.c];\n    }\n}\n\n// Try to reverse a segment of the path\nbool try_reverse_segment(vector<pair<int,int>>& path, vector<int>& tiles,\n                         vector<char>& visited, int& score,\n                         const vector<vector<int>>& p,\n                         const vector<vector<int>>& tile_id,\n                         mt19937& rng) {\n    if (path.size() < 4) return false;\n    \n    uniform_int_distribution<int> len_dist(2, min(20, (int)path.size() - 2));\n    int seg_len = len_dist(rng);\n    uniform_int_distribution<int> start_dist(1, path.size() - seg_len - 1);\n    int start_idx = start_dist(rng);\n    \n    // Check if reversing this segment maintains validity\n    vector<pair<int,int>> new_path = path;\n    vector<int> new_tiles = tiles;\n    \n    // Temporarily mark tiles as unvisited for the segment\n    vector<char> temp_visited = visited;\n    for (int i = start_idx; i < start_idx + seg_len; ++i) {\n        temp_visited[tiles[i]] = 0;\n    }\n    \n    // Try to reverse\n    for (int i = 0; i < seg_len; ++i) {\n        int src_idx = start_idx + seg_len - 1 - i;\n        int dst_idx = start_idx + i;\n        new_path[dst_idx] = path[src_idx];\n        new_tiles[dst_idx] = tiles[src_idx];\n        \n        // Check if this tile is already used in the rest of the path\n        if (temp_visited[tiles[src_idx]]) return false;\n        temp_visited[tiles[src_idx]] = 1;\n    }\n    \n    // Check connectivity between segments\n    auto check_connection = [&](int from_idx, int to_idx) {\n        const auto& from = new_path[from_idx];\n        const auto& to = new_path[to_idx];\n        int dr = abs(from.first - to.first);\n        int dc = abs(from.second - to.second);\n        return (dr + dc == 1);\n    };\n    \n    if (!check_connection(start_idx - 1, start_idx)) return false;\n    if (!check_connection(start_idx + seg_len - 1, start_idx + seg_len)) return false;\n    \n    // If valid, apply the reversal\n    path = new_path;\n    tiles = new_tiles;\n    visited = temp_visited;\n    \n    // Recalculate score (could optimize but it's fine)\n    score = 0;\n    for (const auto& sq : path) {\n        score += p[sq.first][sq.second];\n    }\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Read input.\n    int si, sj;\n    cin >> si >> sj;\n    vector<vector<int>> tile_id(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> tile_id[i][j];\n    vector<vector<int>> 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    // Determine number of tiles.\n    int M = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            M = max(M, tile_id[i][j] + 1);\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    // Generate multiple initial paths and keep the best\n    vector<pair<int,int>> best_initial_path;\n    int best_initial_score = -1;\n    \n    for (int trial = 0; trial < 5; ++trial) {\n        vector<pair<int,int>> cur_path;\n        vector<int> cur_tiles;\n        vector<char> cur_visited(M, 0);\n        int cur_score = 0;\n\n        cur_path.emplace_back(si, sj);\n        cur_tiles.push_back(tile_id[si][sj]);\n        cur_visited[tile_id[si][sj]] = 1;\n        cur_score += p[si][sj];\n        \n        if (trial == 0) {\n            extend_greedy(cur_path, cur_tiles, cur_visited, cur_score, p, tile_id, rng);\n        } else {\n            // For other trials, use a more exploratory initial walk\n            uniform_int_distribution<int> walk_dist(50, 200);\n            int walk_length = walk_dist(rng);\n            for (int step = 0; step < walk_length; ++step) {\n                auto candidates = get_neighbors(cur_path.back().first, cur_path.back().second,\n                                               cur_visited, tile_id);\n                if (candidates.empty()) break;\n                \n                uniform_int_distribution<int> cand_dist(0, candidates.size() - 1);\n                int idx = cand_dist(rng);\n                const auto& cand = candidates[idx];\n                cur_path.push_back({cand.r, cand.c});\n                cur_tiles.push_back(tile_id[cand.r][cand.c]);\n                cur_visited[tile_id[cand.r][cand.c]] = 1;\n                cur_score += p[cand.r][cand.c];\n            }\n            // Then extend greedily\n            extend_greedy(cur_path, cur_tiles, cur_visited, cur_score, p, tile_id, rng);\n        }\n        \n        if (cur_score > best_initial_score) {\n            best_initial_score = cur_score;\n            best_initial_path = cur_path;\n        }\n    }\n\n    vector<pair<int,int>> cur_path = best_initial_path;\n    vector<int> cur_tiles;\n    vector<char> cur_visited(M, 0);\n    int cur_score = 0;\n    \n    // Rebuild tiles and visited from path\n    for (const auto& sq : cur_path) {\n        cur_tiles.push_back(tile_id[sq.first][sq.second]);\n        cur_visited[tile_id[sq.first][sq.second]] = 1;\n        cur_score += p[sq.first][sq.second];\n    }\n\n    vector<pair<int,int>> best_path = cur_path;\n    int best_score = cur_score;\n\n    // Simulated annealing parameters\n    const int ITER = 150000;\n    const double T_start = 200.0;\n    const double T_min = 1e-3;\n    double T = T_start;\n    double cooling_rate = pow(T_min / T_start, 1.0 / ITER);\n    \n    uniform_real_distribution<double> real_dist(0.0, 1.0);\n    auto start_time = chrono::steady_clock::now();\n    const chrono::milliseconds time_limit(1900); // 1.9 seconds\n    \n    int restart_count = 0;\n    const int RESTART_THRESHOLD = 50000; // restart if no improvement for this many iterations\n    int iterations_without_improvement = 0;\n\n    for (int iter = 0; iter < ITER; ++iter) {\n        // Time check\n        if (iter % 1000 == 0) {\n            auto now = chrono::steady_clock::now();\n            if (chrono::duration_cast<chrono::milliseconds>(now - start_time) > time_limit)\n                break;\n        }\n        \n        // Temperature restart if stuck\n        if (iterations_without_improvement > RESTART_THRESHOLD && restart_count < 3) {\n            // Revert to best solution found so far and reheat\n            cur_path = best_path;\n            cur_tiles.clear();\n            cur_visited.assign(M, 0);\n            cur_score = 0;\n            for (const auto& sq : cur_path) {\n                cur_tiles.push_back(tile_id[sq.first][sq.second]);\n                cur_visited[tile_id[sq.first][sq.second]] = 1;\n                cur_score += p[sq.first][sq.second];\n            }\n            T = T_start * pow(0.5, restart_count);\n            restart_count++;\n            iterations_without_improvement = 0;\n            continue;\n        }\n\n        // Copy current state\n        vector<pair<int,int>> new_path = cur_path;\n        vector<int> new_tiles = cur_tiles;\n        vector<char> new_visited = cur_visited;\n        int new_score = cur_score;\n\n        double op = real_dist(rng);\n        if (op < 0.3) {\n            // Extend: add one move at the end\n            if (!new_path.empty()) {\n                int r = new_path.back().first, c = new_path.back().second;\n                auto candidates = get_neighbors(r, c, new_visited, tile_id);\n                if (!candidates.empty()) {\n                    uniform_int_distribution<int> dist(0, candidates.size() - 1);\n                    int idx = dist(rng);\n                    auto& cand = candidates[idx];\n                    new_path.push_back({cand.r, cand.c});\n                    new_tiles.push_back(tile_id[cand.r][cand.c]);\n                    new_visited[tile_id[cand.r][cand.c]] = 1;\n                    new_score += p[cand.r][cand.c];\n                }\n            }\n        } else if (op < 0.5) {\n            // Shrink: remove last move\n            if (new_path.size() > 1) {\n                auto last = new_path.back();\n                int tile = new_tiles.back();\n                new_path.pop_back();\n                new_tiles.pop_back();\n                new_visited[tile] = 0;\n                new_score -= p[last.first][last.second];\n            }\n        } else if (op < 0.8) {\n            // Modify: truncate at random index, change next move, then extend\n            if (new_path.size() <= 1) {\n                // Fallback to extend\n                if (!new_path.empty()) {\n                    int r = new_path.back().first, c = new_path.back().second;\n                    auto candidates = get_neighbors(r, c, new_visited, tile_id);\n                    if (!candidates.empty()) {\n                        uniform_int_distribution<int> dist(0, candidates.size() - 1);\n                        int idx = dist(rng);\n                        auto& cand = candidates[idx];\n                        new_path.push_back({cand.r, cand.c});\n                        new_tiles.push_back(tile_id[cand.r][cand.c]);\n                        new_visited[tile_id[cand.r][cand.c]] = 1;\n                        new_score += p[cand.r][cand.c];\n                    }\n                }\n            } else {\n                int L = new_path.size();\n                uniform_int_distribution<int> idx_dist(1, L - 1);\n                int k = idx_dist(rng);\n                \n                // Remove squares from index k onward\n                for (int i = k; i < L; ++i) {\n                    int tile = new_tiles[i];\n                    new_visited[tile] = 0;\n                    new_score -= p[new_path[i].first][new_path[i].second];\n                }\n                new_path.resize(k);\n                new_tiles.resize(k);\n                \n                // Choose a new move from the square at index k-1\n                int r_prev = new_path.back().first, c_prev = new_path.back().second;\n                auto candidates = get_neighbors(r_prev, c_prev, new_visited, tile_id);\n                if (!candidates.empty()) {\n                    uniform_int_distribution<int> dist(0, candidates.size() - 1);\n                    int idx = dist(rng);\n                    auto& cand = candidates[idx];\n                    new_path.push_back({cand.r, cand.c});\n                    new_tiles.push_back(tile_id[cand.r][cand.c]);\n                    new_visited[tile_id[cand.r][cand.c]] = 1;\n                    new_score += p[cand.r][cand.c];\n                    \n                    // Extend greedily with lookahead\n                    extend_greedy(new_path, new_tiles, new_visited, new_score, p, tile_id, rng);\n                }\n            }\n        } else {\n            // Try to reverse a segment\n            if (try_reverse_segment(new_path, new_tiles, new_visited, new_score, p, tile_id, rng)) {\n                // Success - path was improved by reversal\n            } else {\n                // If reversal fails, do a simple extend\n                if (!new_path.empty()) {\n                    int r = new_path.back().first, c = new_path.back().second;\n                    auto candidates = get_neighbors(r, c, new_visited, tile_id);\n                    if (!candidates.empty()) {\n                        uniform_int_distribution<int> dist(0, candidates.size() - 1);\n                        int idx = dist(rng);\n                        auto& cand = candidates[idx];\n                        new_path.push_back({cand.r, cand.c});\n                        new_tiles.push_back(tile_id[cand.r][cand.c]);\n                        new_visited[tile_id[cand.r][cand.c]] = 1;\n                        new_score += p[cand.r][cand.c];\n                    }\n                }\n            }\n        }\n\n        // Metropolis criterion\n        int delta = new_score - cur_score;\n        bool accept = false;\n        if (delta > 0) {\n            accept = true;\n        } else {\n            double prob = exp(delta / T);\n            if (real_dist(rng) < prob) accept = true;\n        }\n\n        if (accept) {\n            cur_path = std::move(new_path);\n            cur_tiles = std::move(new_tiles);\n            cur_visited = std::move(new_visited);\n            cur_score = new_score;\n            if (cur_score > best_score) {\n                best_score = cur_score;\n                best_path = cur_path;\n                iterations_without_improvement = 0;\n            } else {\n                iterations_without_improvement++;\n            }\n        } else {\n            iterations_without_improvement++;\n        }\n\n        // Cooling\n        T *= cooling_rate;\n    }\n\n    // Convert best_path to move string\n    string moves;\n    for (size_t i = 1; i < best_path.size(); ++i) {\n        int dr = best_path[i].first - best_path[i-1].first;\n        int dc = best_path[i].second - best_path[i-1].second;\n        if (dr == -1 && dc == 0) moves += 'U';\n        else if (dr == 1 && dc == 0) moves += 'D';\n        else if (dr == 0 && dc == -1) moves += 'L';\n        else if (dr == 0 && dc == 1) moves += 'R';\n        else assert(false);\n    }\n\n    cout << moves << endl;\n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <string>\n\nusing namespace std;\n\nconst int N = 30;\n\ndouble h_est[N][N-1];\ndouble v_est[N-1][N];\nint h_count[N][N-1] = {0};\nint v_count[N-1][N] = {0};\n\nstruct Node {\n    int i, j;\n    bool operator==(const Node& other) const { return i == other.i && j == other.j; }\n    bool operator!=(const Node& other) const { return !(*this == other); }\n};\n\nusing PQElement = pair<double, Node>;\n\nstruct Compare {\n    bool operator()(const PQElement& a, const PQElement& b) const {\n        return a.first > b.first;\n    }\n};\n\ndouble getEdgeEstimate(int i, int j, int ni, int nj) {\n    if (i == ni) {\n        if (nj == j+1) return h_est[i][j];\n        else if (nj == j-1) return h_est[i][j-1];\n    } else if (j == nj) {\n        if (ni == i+1) return v_est[i][j];\n        else if (ni == i-1) return v_est[i-1][j];\n    }\n    return 0.0;\n}\n\nvoid updateEdge(int i, int j, int ni, int nj, double factor, double global_lr) {\n    if (i == ni) {\n        if (nj == j+1) {\n            h_count[i][j]++;\n            double lr = global_lr / (1.0 + sqrt(h_count[i][j]));\n            h_est[i][j] *= (1.0 + lr * (factor - 1.0));\n            if (h_est[i][j] < 1000.0) h_est[i][j] = 1000.0;\n            if (h_est[i][j] > 9000.0) h_est[i][j] = 9000.0;\n        } else if (nj == j-1) {\n            h_count[i][j-1]++;\n            double lr = global_lr / (1.0 + sqrt(h_count[i][j-1]));\n            h_est[i][j-1] *= (1.0 + lr * (factor - 1.0));\n            if (h_est[i][j-1] < 1000.0) h_est[i][j-1] = 1000.0;\n            if (h_est[i][j-1] > 9000.0) h_est[i][j-1] = 9000.0;\n        }\n    } else if (j == nj) {\n        if (ni == i+1) {\n            v_count[i][j]++;\n            double lr = global_lr / (1.0 + sqrt(v_count[i][j]));\n            v_est[i][j] *= (1.0 + lr * (factor - 1.0));\n            if (v_est[i][j] < 1000.0) v_est[i][j] = 1000.0;\n            if (v_est[i][j] > 9000.0) v_est[i][j] = 9000.0;\n        } else if (ni == i-1) {\n            v_count[i-1][j]++;\n            double lr = global_lr / (1.0 + sqrt(v_count[i-1][j]));\n            v_est[i-1][j] *= (1.0 + lr * (factor - 1.0));\n            if (v_est[i-1][j] < 1000.0) v_est[i-1][j] = 1000.0;\n            if (v_est[i-1][j] > 9000.0) v_est[i-1][j] = 9000.0;\n        }\n    }\n}\n\nvoid updateEstimates(const vector<Node>& path, int obs, int k) {\n    int path_length = path.size() - 1;\n    if (path_length == 0) return;\n    \n    double pred = 0.0;\n    for (int idx = 0; idx < path_length; idx++) {\n        auto& from = path[idx];\n        auto& to = path[idx+1];\n        pred += getEdgeEstimate(from.i, from.j, to.i, to.j);\n    }\n    \n    double factor = obs / pred;\n    double global_lr = 0.25 * pow(0.998, k); // Exponential decay\n    \n    for (int idx = 0; idx < path_length; idx++) {\n        auto& from = path[idx];\n        auto& to = path[idx+1];\n        updateEdge(from.i, from.j, to.i, to.j, factor, global_lr);\n    }\n}\n\npair<string, vector<Node>> computePath(int si, int sj, int ti, int tj) {\n    vector<vector<double>> dist(N, vector<double>(N, 1e18));\n    vector<vector<Node>> prev(N, vector<Node>(N, {-1,-1}));\n    dist[si][sj] = 0.0;\n    priority_queue<PQElement, vector<PQElement>, Compare> pq;\n    pq.push({0.0, {si, sj}});\n    \n    while (!pq.empty()) {\n        auto [d, node] = pq.top(); pq.pop();\n        if (d > dist[node.i][node.j]) continue;\n        if (node.i == ti && node.j == tj) break;\n        \n        // right\n        if (node.j+1 < N) {\n            double w = h_est[node.i][node.j];\n            if (dist[node.i][node.j] + w < dist[node.i][node.j+1]) {\n                dist[node.i][node.j+1] = dist[node.i][node.j] + w;\n                prev[node.i][node.j+1] = {node.i, node.j};\n                pq.push({dist[node.i][node.j+1], {node.i, node.j+1}});\n            }\n        }\n        // left\n        if (node.j-1 >= 0) {\n            double w = h_est[node.i][node.j-1];\n            if (dist[node.i][node.j] + w < dist[node.i][node.j-1]) {\n                dist[node.i][node.j-1] = dist[node.i][node.j] + w;\n                prev[node.i][node.j-1] = {node.i, node.j};\n                pq.push({dist[node.i][node.j-1], {node.i, node.j-1}});\n            }\n        }\n        // down\n        if (node.i+1 < N) {\n            double w = v_est[node.i][node.j];\n            if (dist[node.i][node.j] + w < dist[node.i+1][node.j]) {\n                dist[node.i+1][node.j] = dist[node.i][node.j] + w;\n                prev[node.i+1][node.j] = {node.i, node.j};\n                pq.push({dist[node.i+1][node.j], {node.i+1, node.j}});\n            }\n        }\n        // up\n        if (node.i-1 >= 0) {\n            double w = v_est[node.i-1][node.j];\n            if (dist[node.i][node.j] + w < dist[node.i-1][node.j]) {\n                dist[node.i-1][node.j] = dist[node.i][node.j] + w;\n                prev[node.i-1][node.j] = {node.i, node.j};\n                pq.push({dist[node.i-1][node.j], {node.i-1, node.j}});\n            }\n        }\n    }\n    \n    // reconstruct path\n    vector<Node> path_nodes;\n    Node cur = {ti, tj};\n    while (cur.i != si || cur.j != sj) {\n        path_nodes.push_back(cur);\n        cur = prev[cur.i][cur.j];\n    }\n    path_nodes.push_back({si, sj});\n    reverse(path_nodes.begin(), path_nodes.end());\n    \n    // convert to string\n    string path_str;\n    for (size_t idx = 0; idx < path_nodes.size()-1; idx++) {\n        auto& from = path_nodes[idx];\n        auto& to = path_nodes[idx+1];\n        if (to.i == from.i && to.j == from.j+1) path_str += 'R';\n        else if (to.i == from.i && to.j == from.j-1) path_str += 'L';\n        else if (to.i == from.i+1 && to.j == from.j) path_str += 'D';\n        else if (to.i == from.i-1 && to.j == from.j) path_str += 'U';\n    }\n    return {path_str, path_nodes};\n}\n\nint main() {\n    // Initialize estimates to midpoint of range\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N-1; ++j)\n            h_est[i][j] = 5000.0;\n    for (int i = 0; i < N-1; ++i)\n        for (int j = 0; j < N; ++j)\n            v_est[i][j] = 5000.0;\n\n    for (int k = 0; k < 1000; ++k) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n        \n        auto [path_str, path_nodes] = computePath(si, sj, ti, tj);\n        \n        cout << path_str << endl;\n        cout.flush();\n        \n        int obs;\n        cin >> obs;\n        \n        updateEstimates(path_nodes, obs, k);\n    }\n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <cmath>\n#include <numeric>\n#include <array>\n#include <chrono>\n#include <cassert>\n#include <bitset>\n#include <cstring>\n\nusing namespace std;\n\nint N = 20;\nconst int ALPHABET = 8;\nconst char ALPHABET_CHARS[] = \"ABCDEFGH\";\n\nstruct Placement {\n    int str_idx;\n    int row, col;\n    int dir; // 0 horizontal, 1 vertical\n    int len;\n};\n\nvector<string> strings;\nvector<Placement> placements;\nvector<vector<int>> placements_by_str;\nvector<vector<pair<int, char>>> cell_lists;\n\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// Optimized placement generation - only store placements that could potentially match\nvoid generate_placements() {\n    int M = strings.size();\n    placements_by_str.resize(M);\n    placements.clear();\n    placements.reserve(M * 100); // Fewer placements than before\n    \n    for (int s = 0; s < M; ++s) {\n        int len = strings[s].size();\n        // For each string, generate placements that could match based on first character\n        for (int dir = 0; dir < 2; ++dir) {\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    // Quick check: if first character doesn't match, skip\n                    // We'll check this during placement anyway\n                    placements.push_back({s, r, c, dir, len});\n                    placements_by_str[s].push_back(placements.size() - 1);\n                }\n            }\n        }\n    }\n}\n\nvoid build_cell_lists() {\n    cell_lists.assign(N * N, {});\n    for (int pid = 0; pid < (int)placements.size(); ++pid) {\n        const Placement& p = placements[pid];\n        for (int off = 0; off < p.len; ++off) {\n            int r, c;\n            if (p.dir == 0) {\n                r = p.row;\n                c = (p.col + off) % N;\n            } else {\n                r = (p.row + off) % N;\n                c = p.col;\n            }\n            int cell = r * N + c;\n            char req = strings[p.str_idx][off];\n            cell_lists[cell].emplace_back(pid, req);\n        }\n    }\n}\n\nbool is_subsequence(const vector<vector<char>>& mat, const string& s) {\n    int len = s.size();\n    // Check horizontal\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            bool ok = true;\n            for (int p = 0; p < len; ++p) {\n                if (mat[i][(j + p) % N] != s[p]) {\n                    ok = false;\n                    break;\n                }\n            }\n            if (ok) return true;\n        }\n    }\n    // Check vertical\n    for (int j = 0; j < N; ++j) {\n        for (int i = 0; i < N; ++i) {\n            bool ok = true;\n            for (int p = 0; p < len; ++p) {\n                if (mat[(i + p) % N][j] != s[p]) {\n                    ok = false;\n                    break;\n                }\n            }\n            if (ok) return true;\n        }\n    }\n    return false;\n}\n\nint evaluate(const vector<vector<char>>& mat) {\n    int cnt = 0;\n    for (const string& s : strings) {\n        if (is_subsequence(mat, s)) ++cnt;\n    }\n    return cnt;\n}\n\n// Simplified greedy - only try a limited number of placements per string\nvector<vector<char>> greedy(int seed) {\n    mt19937 gen(seed);\n    vector<vector<char>> mat(N, vector<char>(N, '.'));\n    int M = strings.size();\n    \n    // Process strings in random order\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    shuffle(order.begin(), order.end(), gen);\n    \n    for (int idx : order) {\n        const string& s = strings[idx];\n        int len = s.size();\n        \n        // Only try a subset of placements to save time\n        vector<int> plist = placements_by_str[idx];\n        shuffle(plist.begin(), plist.end(), gen);\n        \n        int attempts = min(50, (int)plist.size()); // Limit attempts per string\n        bool placed = false;\n        \n        for (int i = 0; i < attempts && !placed; ++i) {\n            int pid = plist[i];\n            const Placement& p = placements[pid];\n            \n            // Check compatibility\n            bool compatible = true;\n            for (int off = 0; off < len; ++off) {\n                int r, c;\n                if (p.dir == 0) {\n                    r = p.row;\n                    c = (p.col + off) % N;\n                } else {\n                    r = (p.row + off) % N;\n                    c = p.col;\n                }\n                if (mat[r][c] != '.' && mat[r][c] != s[off]) {\n                    compatible = false;\n                    break;\n                }\n            }\n            \n            if (compatible) {\n                // Place the string\n                for (int off = 0; off < len; ++off) {\n                    int r, c;\n                    if (p.dir == 0) {\n                        r = p.row;\n                        c = (p.col + off) % N;\n                    } else {\n                        r = (p.row + off) % N;\n                        c = p.col;\n                    }\n                    if (mat[r][c] == '.') {\n                        mat[r][c] = s[off];\n                    }\n                }\n                placed = true;\n            }\n        }\n    }\n    \n    // Fill remaining dots with 'A'\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (mat[i][j] == '.')\n                mat[i][j] = 'A';\n    \n    return mat;\n}\n\n// Optimized simulated annealing with fewer iterations\nvector<vector<char>> simulated_annealing(vector<vector<char>> mat) {\n    int M = strings.size();\n    int P = placements.size();\n    \n    // Initialize counts\n    vector<int> placement_match_count(P, 0);\n    vector<int> string_sat_count(M, 0);\n    int global_c = 0;\n    \n    // Compute initial counts\n    for (int pid = 0; pid < P; ++pid) {\n        const Placement& p = placements[pid];\n        int cnt = 0;\n        for (int off = 0; off < p.len; ++off) {\n            int r, c;\n            if (p.dir == 0) {\n                r = p.row;\n                c = (p.col + off) % N;\n            } else {\n                r = (p.row + off) % N;\n                c = p.col;\n            }\n            if (mat[r][c] == strings[p.str_idx][off]) ++cnt;\n        }\n        placement_match_count[pid] = cnt;\n        if (cnt == p.len) {\n            ++string_sat_count[p.str_idx];\n        }\n    }\n    \n    for (int s = 0; s < M; ++s)\n        if (string_sat_count[s] > 0) ++global_c;\n    \n    // SA parameters - reduced iterations\n    const int ITER = 20000;\n    double T = 5.0;\n    double cooling = 0.9999;\n    uniform_int_distribution<int> cell_dist(0, N*N - 1);\n    uniform_int_distribution<int> char_dist(0, ALPHABET - 1);\n    uniform_real_distribution<double> prob_dist(0.0, 1.0);\n    \n    for (int iter = 0; iter < ITER; ++iter) {\n        int cell = cell_dist(rng);\n        char old_char = mat[cell / N][cell % N];\n        char new_char = ALPHABET_CHARS[char_dist(rng)];\n        if (new_char == old_char) continue;\n        \n        // Compute changes\n        int delta_c = 0;\n        vector<pair<int, int>> changed_placements;\n        vector<pair<int, int>> changed_strings;\n        \n        for (const auto& [pid, req] : cell_lists[cell]) {\n            int cur_cnt = placement_match_count[pid];\n            int new_cnt = cur_cnt;\n            if (old_char == req) --new_cnt;\n            if (new_char == req) ++new_cnt;\n            if (new_cnt == cur_cnt) continue;\n            \n            int len = placements[pid].len;\n            bool was_sat = (cur_cnt == len);\n            bool now_sat = (new_cnt == len);\n            \n            changed_placements.emplace_back(pid, cur_cnt);\n            placement_match_count[pid] = new_cnt;\n            \n            if (was_sat != now_sat) {\n                int str_idx = placements[pid].str_idx;\n                int delta = now_sat ? 1 : -1;\n                changed_strings.emplace_back(str_idx, delta);\n                string_sat_count[str_idx] += delta;\n                if (delta == 1 && string_sat_count[str_idx] == 1) ++delta_c;\n                if (delta == -1 && string_sat_count[str_idx] == 0) --delta_c;\n            }\n        }\n        \n        // Decide acceptance\n        bool accept = false;\n        if (delta_c >= 0) {\n            accept = true;\n        } else {\n            double prob = exp(delta_c / T);\n            if (prob_dist(rng) < prob) accept = true;\n        }\n        \n        if (accept) {\n            mat[cell / N][cell % N] = new_char;\n            global_c += delta_c;\n            if (global_c == M) break;\n        } else {\n            // Revert changes\n            for (auto& [pid, old_cnt] : changed_placements) {\n                placement_match_count[pid] = old_cnt;\n            }\n            for (auto& [str_idx, delta] : changed_strings) {\n                string_sat_count[str_idx] -= delta;\n            }\n        }\n        \n        T *= cooling;\n    }\n    \n    return mat;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int M;\n    cin >> N >> M;\n    strings.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> strings[i];\n    }\n    \n    generate_placements();\n    build_cell_lists();\n    \n    // Run fewer greedy attempts\n    vector<vector<char>> best_mat;\n    int best_c = -1;\n    const int GREEDY_TRIES = 3;\n    \n    for (int t = 0; t < GREEDY_TRIES; ++t) {\n        auto mat = greedy(rng());\n        int c = evaluate(mat);\n        if (c > best_c) {\n            best_c = c;\n            best_mat = mat;\n        }\n        if (best_c == M) break;\n    }\n    \n    // Only run SA if not already perfect\n    if (best_c < M) {\n        best_mat = simulated_annealing(best_mat);\n    }\n    \n    // Output\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << best_mat[i][j];\n        }\n        cout << '\\n';\n    }\n    \n    return 0;\n}","ahc005":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <utility>\n\nusing namespace std;\n\nconst int INF = 1e9;\nconst int dr[4] = {-1, 1, 0, 0};\nconst int dc[4] = {0, 0, -1, 1};\nconst char dir_char[4] = {'U', 'D', 'L', 'R'};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, si, sj;\n    cin >> N >> si >> sj;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> grid[i];\n    }\n\n    // assign indices to road squares\n    vector<vector<int>> idx(N, vector<int>(N, -1));\n    vector<int> row, col, w;\n    int V = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != '#') {\n                idx[i][j] = V;\n                row.push_back(i);\n                col.push_back(j);\n                w.push_back(grid[i][j] - '0');\n                ++V;\n            }\n        }\n    }\n\n    // ---------- horizontal segments ----------\n    vector<int> seg_id_h(V, -1);\n    vector<vector<int>> seg_nodes_h;\n    int h_cnt = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != '#' && seg_id_h[idx[i][j]] == -1) {\n                int sid = h_cnt++;\n                seg_nodes_h.push_back({});\n                int jj = j;\n                while (jj < N && grid[i][jj] != '#') {\n                    int id = idx[i][jj];\n                    seg_id_h[id] = sid;\n                    seg_nodes_h[sid].push_back(id);\n                    ++jj;\n                }\n            }\n        }\n    }\n\n    // ---------- vertical segments ----------\n    vector<int> seg_id_v(V, -1);\n    vector<vector<int>> seg_nodes_v;\n    int v_cnt = 0;\n    for (int j = 0; j < N; ++j) {\n        for (int i = 0; i < N; ++i) {\n            if (grid[i][j] != '#' && seg_id_v[idx[i][j]] == -1) {\n                int sid = v_cnt++;\n                seg_nodes_v.push_back({});\n                int ii = i;\n                while (ii < N && grid[ii][j] != '#') {\n                    int id = idx[ii][j];\n                    seg_id_v[id] = sid;\n                    seg_nodes_v[sid].push_back(id);\n                    ++ii;\n                }\n            }\n        }\n    }\n\n    // choose the orientation with fewer segments\n    bool use_horiz = (h_cnt <= v_cnt);\n    int seg_cnt;\n    vector<int> seg_id(V);\n    vector<vector<int>> seg_nodes;\n    if (use_horiz) {\n        seg_cnt = h_cnt;\n        seg_id = seg_id_h;\n        seg_nodes = seg_nodes_h;\n    } else {\n        seg_cnt = v_cnt;\n        seg_id = seg_id_v;\n        seg_nodes = seg_nodes_v;\n    }\n\n    int start_idx = idx[si][sj];\n    int start_seg = seg_id[start_idx];\n    vector<bool> seg_visited(seg_cnt, false);\n    seg_visited[start_seg] = true;\n    int remaining = seg_cnt - 1;\n\n    string moves;\n    int cur = start_idx;\n\n    // Dijkstra from a source, filling dist and pred\n    auto dijkstra = [&](int src, vector<int>& dist, vector<int>& pred) {\n        dist.assign(V, INF);\n        pred.assign(V, -1);\n        dist[src] = 0;\n        using P = pair<int, int>;\n        priority_queue<P, vector<P>, greater<P>> pq;\n        pq.emplace(0, src);\n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop();\n            if (d != dist[u]) continue;\n            int r = row[u], c = col[u];\n            for (int k = 0; k < 4; ++k) {\n                int nr = r + dr[k];\n                int nc = c + dc[k];\n                if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n                int v = idx[nr][nc];\n                if (v == -1) continue;\n                int nd = d + w[v];\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    pred[v] = u;\n                    pq.emplace(nd, v);\n                }\n            }\n        }\n    };\n\n    // main loop: visit all segments\n    while (remaining > 0) {\n        vector<int> dist(V), pred(V);\n        dijkstra(cur, dist, pred);\n\n        // find the closest unvisited segment and its closest square\n        int best_seg = -1, best_node = -1, best_dist = INF;\n        for (int s = 0; s < seg_cnt; ++s) {\n            if (seg_visited[s]) continue;\n            int min_d = INF, node = -1;\n            for (int v : seg_nodes[s]) {\n                if (dist[v] < min_d) {\n                    min_d = dist[v];\n                    node = v;\n                }\n            }\n            if (min_d < best_dist) {\n                best_dist = min_d;\n                best_seg = s;\n                best_node = node;\n            }\n        }\n\n        // reconstruct the path from cur to best_node\n        vector<int> path;\n        for (int v = best_node; v != cur; v = pred[v]) {\n            path.push_back(v);\n        }\n        path.push_back(cur);\n        reverse(path.begin(), path.end());   // now path[0] = cur, path[last] = best_node\n\n        // walk along the path, record moves and mark newly visited segments\n        for (size_t i = 0; i + 1 < path.size(); ++i) {\n            int from = path[i];\n            int to = path[i+1];\n            int dr = row[to] - row[from];\n            int dc = col[to] - col[from];\n            char move;\n            if (dr == -1) move = 'U';\n            else if (dr == 1) move = 'D';\n            else if (dc == -1) move = 'L';\n            else if (dc == 1) move = 'R';\n            else { /* should not happen */ }\n            moves += move;\n            int s = seg_id[to];\n            if (!seg_visited[s]) {\n                seg_visited[s] = true;\n                --remaining;\n            }\n        }\n        cur = best_node;\n    }\n\n    // return to the start square\n    if (cur != start_idx) {\n        vector<int> dist(V), pred(V);\n        dijkstra(cur, dist, pred);\n        vector<int> path;\n        for (int v = start_idx; v != cur; v = pred[v]) {\n            path.push_back(v);\n        }\n        path.push_back(cur);\n        reverse(path.begin(), path.end());\n        for (size_t i = 0; i + 1 < path.size(); ++i) {\n            int from = path[i];\n            int to = path[i+1];\n            int dr = row[to] - row[from];\n            int dc = col[to] - col[from];\n            char move;\n            if (dr == -1) move = 'U';\n            else if (dr == 1) move = 'D';\n            else if (dc == -1) move = 'L';\n            else if (dc == 1) move = 'R';\n            moves += move;\n        }\n    }\n\n    cout << moves << '\\n';\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K, R;\n    cin >> N >> M >> K >> R;\n    \n    vector<vector<int>> d(N, vector<int>(K));\n    vector<double> d_sum_per_skill(K, 0.0);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < K; ++j) {\n            cin >> d[i][j];\n            d_sum_per_skill[j] += d[i][j];\n        }\n    }\n\n    // Compute average required skill per dimension\n    vector<double> avg_d(K);\n    for (int k = 0; k < K; ++k) {\n        avg_d[k] = d_sum_per_skill[k] / N;\n    }\n\n    vector<vector<int>> succ(N);\n    vector<vector<int>> pred(N);\n    vector<int> prereq_count(N, 0);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        succ[u].push_back(v);\n        pred[v].push_back(u);\n        ++prereq_count[v];\n    }\n\n    // Compute longest path (depth) for each task\n    vector<int> depth(N, 0);\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        return a < b;  // Process in natural order due to u<v guarantee\n    });\n    \n    for (int i = N-1; i >= 0; --i) {\n        int task = order[i];\n        if (succ[task].empty()) {\n            depth[task] = 1;\n        } else {\n            int max_depth = 0;\n            for (int next : succ[task]) {\n                max_depth = max(max_depth, depth[next]);\n            }\n            depth[task] = max_depth + 1;\n        }\n    }\n\n    vector<int> task_status(N, -1);\n    vector<int> task_start_day(N, -1);\n    vector<int> prereq_rem = prereq_count;\n    vector<int> member_task(M, -1);\n    vector<int> member_load(M, 0);\n    \n    // Initialize skill estimates based on s_j generation range\n    vector<vector<double>> est_s(M, vector<double>(K));\n    for (int j = 0; j < M; ++j) {\n        for (int k = 0; k < K; ++k) {\n            // s_j generation: norm between 20-60, so per dimension ~20/sqrt(K) to 60/sqrt(K)\n            // For K=15, that's about 5-15. Start with 10 as initial guess\n            est_s[j][k] = 10.0 + avg_d[k] * 0.5;\n        }\n    }\n\n    int day = 0;\n    int total_observations = 0;\n    while (true) {\n        ++day;\n        if (day > 2000) break;\n\n        if (day > 1) {\n            int n;\n            cin >> n;\n            if (n == -1) break;\n            for (int i = 0; i < n; ++i) {\n                int f;\n                cin >> f;\n                --f;\n                int task = member_task[f];\n                if (task != -1) {\n                    task_status[task] = 1;\n                    int t_obs = (day - 1) - task_start_day[task] + 1;\n                    ++total_observations;\n                    \n                    double w_pred = 0.0;\n                    int deficit_count = 0;\n                    for (int k = 0; k < K; ++k) {\n                        if (d[task][k] > est_s[f][k]) {\n                            w_pred += d[task][k] - est_s[f][k];\n                            ++deficit_count;\n                        }\n                    }\n                    \n                    // Learning rate decreases as we get more observations\n                    double lr = 0.7 / (1.0 + total_observations * 0.01);\n                    \n                    if (t_obs > 1) {\n                        double error = t_obs - w_pred;\n                        if (deficit_count > 0 && abs(error) > 1e-9) {\n                            double delta = lr * error / deficit_count;\n                            for (int k = 0; k < K; ++k) {\n                                if (d[task][k] > est_s[f][k]) {\n                                    est_s[f][k] = max(0.0, est_s[f][k] - delta);\n                                }\n                            }\n                        }\n                    } else {\n                        if (w_pred > 0 && deficit_count > 0) {\n                            double delta = lr * w_pred / deficit_count;\n                            for (int k = 0; k < K; ++k) {\n                                if (d[task][k] > est_s[f][k]) {\n                                    est_s[f][k] = min(double(d[task][k]), est_s[f][k] + delta);\n                                }\n                            }\n                        }\n                    }\n                    \n                    for (int s : succ[task]) {\n                        --prereq_rem[s];\n                    }\n                    member_task[f] = -1;\n                    member_load[f] = max(0, member_load[f] - 1);\n                }\n            }\n        }\n\n        vector<int> free_members;\n        for (int j = 0; j < M; ++j) {\n            if (member_task[j] == -1) free_members.push_back(j);\n        }\n\n        vector<int> ready_tasks;\n        for (int i = 0; i < N; ++i) {\n            if (task_status[i] == -1 && prereq_rem[i] == 0) {\n                ready_tasks.push_back(i);\n            }\n        }\n\n        if (free_members.empty() || ready_tasks.empty()) {\n            cout << \"0\\n\";\n            cout.flush();\n            continue;\n        }\n\n        // Sort tasks by criticality (longest path) descending, then by predicted difficulty\n        sort(ready_tasks.begin(), ready_tasks.end(), [&](int a, int b) {\n            if (depth[a] != depth[b]) return depth[a] > depth[b];\n            // If same depth, prefer tasks with higher total requirement\n            double sum_a = 0, sum_b = 0;\n            for (int k = 0; k < K; ++k) {\n                sum_a += d[a][k];\n                sum_b += d[b][k];\n            }\n            return sum_a > sum_b;\n        });\n\n        vector<pair<int, int>> assignments;\n        for (int task : ready_tasks) {\n            if (free_members.empty()) break;\n            \n            // Find best member considering both skill and load\n            int best_member = -1;\n            double best_score = -1e18;\n            \n            for (int j : free_members) {\n                double w = 0.0;\n                for (int k = 0; k < K; ++k) {\n                    if (d[task][k] > est_s[j][k]) {\n                        w += d[task][k] - est_s[j][k];\n                    }\n                }\n                double t_pred = max(1.0, w);\n                \n                // Score considers both predicted time and current load\n                // Lower predicted time is better, lower load is better\n                double score = -t_pred - member_load[j] * 0.5;\n                \n                if (score > best_score) {\n                    best_score = score;\n                    best_member = j;\n                }\n            }\n            \n            if (best_member != -1) {\n                task_status[task] = 0;\n                task_start_day[task] = day;\n                member_task[best_member] = task;\n                member_load[best_member]++;\n                assignments.emplace_back(best_member, task);\n                free_members.erase(find(free_members.begin(), free_members.end(), best_member));\n            }\n        }\n\n        cout << assignments.size();\n        for (auto [member, task] : assignments) {\n            cout << ' ' << member + 1 << ' ' << task + 1;\n        }\n        cout << '\\n';\n        cout.flush();\n    }\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point {\n    int x, y;\n    Point() {}\n    Point(int x, int y) : x(x), y(y) {}\n};\n\nint manhattan(const Point& a, const Point& b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    // Read 1000 orders\n    vector<Point> restaurants(1000), destinations(1000);\n    for (int i = 0; i < 1000; ++i) {\n        cin >> restaurants[i].x >> restaurants[i].y >> destinations[i].x >> destinations[i].y;\n    }\n\n    const Point depot(400, 400);\n\n    // Step 1: Select 50 orders with smallest max distance to depot\n    vector<int> order_cost(1000);\n    for (int i = 0; i < 1000; ++i) {\n        order_cost[i] = max(manhattan(depot, restaurants[i]), manhattan(depot, destinations[i]));\n    }\n    vector<int> indices(1000);\n    iota(indices.begin(), indices.end(), 0);\n    sort(indices.begin(), indices.end(), [&](int i, int j) {\n        return order_cost[i] < order_cost[j];\n    });\n\n    vector<int> selected_orders;\n    for (int i = 0; i < 50; ++i) {\n        selected_orders.push_back(indices[i]);\n    }\n\n    // Create points for selected orders\n    vector<Point> points;\n    vector<pair<int, int>> point_info; // (order_index, type) type: 0=pickup, 1=delivery\n    for (int i = 0; i < 50; ++i) {\n        int order_idx = selected_orders[i];\n        points.push_back(restaurants[order_idx]);\n        point_info.push_back({i, 0});\n        points.push_back(destinations[order_idx]);\n        point_info.push_back({i, 1});\n    }\n\n    // Step 2: Build initial tour using cheapest insertion with multiple starting points\n    const int total_points = 100;\n    // Precompute distances\n    vector<vector<int>> dist_mat(total_points, vector<int>(total_points));\n    vector<int> dist_to_depot(total_points);\n    for (int i = 0; i < total_points; ++i) {\n        for (int j = 0; j < total_points; ++j) {\n            dist_mat[i][j] = manhattan(points[i], points[j]);\n        }\n        dist_to_depot[i] = manhattan(points[i], depot);\n    }\n\n    // Try multiple starting orders and keep the best initial tour\n    vector<int> best_tour;\n    int best_tour_length = INT_MAX;\n    \n    // Try first 5 orders as starting points\n    for (int start_order = 0; start_order < 5 && start_order < 50; ++start_order) {\n        vector<int> tour = {start_order * 2, start_order * 2 + 1};\n        vector<bool> used(50, false);\n        used[start_order] = true;\n        \n        // Insert remaining orders\n        for (int step = 1; step < 50; ++step) {\n            int best_increase = INT_MAX;\n            int best_order = -1;\n            int best_pickup_pos = -1;\n            int best_delivery_pos = -1;\n\n            // Try each unused order\n            for (int order = 0; order < 50; ++order) {\n                if (used[order]) continue;\n                int pickup_idx = order * 2;\n                int delivery_idx = order * 2 + 1;\n\n                // Try all insertion positions\n                int tour_size = tour.size();\n                for (int i = 0; i <= tour_size; ++i) {\n                    for (int j = i; j <= tour_size; ++j) {\n                        int increase = 0;\n                        if (i == j) {\n                            Point A = (i == 0) ? depot : points[tour[i-1]];\n                            Point B = (i == tour_size) ? depot : points[tour[i]];\n                            int dAB = (i == 0 || i == tour_size) ? 0 : manhattan(A, B);\n                            increase = manhattan(A, points[pickup_idx]) + \n                                       dist_mat[pickup_idx][delivery_idx] + \n                                       manhattan(points[delivery_idx], B) - dAB;\n                        } else {\n                            Point A1 = (i == 0) ? depot : points[tour[i-1]];\n                            Point B1 = (i == tour_size) ? depot : points[tour[i]];\n                            int dA1B1 = (i == 0 || i == tour_size) ? 0 : manhattan(A1, B1);\n                            int inc_pickup = manhattan(A1, points[pickup_idx]) + \n                                             manhattan(points[pickup_idx], B1) - dA1B1;\n                            \n                            Point C = (j == 0) ? depot : points[tour[j-1]];\n                            Point D = (j == tour_size) ? depot : points[tour[j]];\n                            int dCD = (j == 0 || j == tour_size) ? 0 : manhattan(C, D);\n                            int inc_delivery = manhattan(C, points[delivery_idx]) + \n                                               manhattan(points[delivery_idx], D) - dCD;\n                            increase = inc_pickup + inc_delivery;\n                        }\n\n                        if (increase < best_increase) {\n                            best_increase = increase;\n                            best_order = order;\n                            best_pickup_pos = i;\n                            best_delivery_pos = j;\n                        }\n                    }\n                }\n            }\n\n            // Insert the best order\n            int pickup_idx = best_order * 2;\n            int delivery_idx = best_order * 2 + 1;\n            \n            if (best_pickup_pos == best_delivery_pos) {\n                tour.insert(tour.begin() + best_pickup_pos, pickup_idx);\n                tour.insert(tour.begin() + best_pickup_pos + 1, delivery_idx);\n            } else {\n                tour.insert(tour.begin() + best_pickup_pos, pickup_idx);\n                if (best_delivery_pos > best_pickup_pos) {\n                    best_delivery_pos++;\n                }\n                tour.insert(tour.begin() + best_delivery_pos, delivery_idx);\n            }\n            used[best_order] = true;\n        }\n        \n        // Calculate tour length\n        int tour_length = dist_to_depot[tour[0]] + dist_to_depot[tour.back()];\n        for (size_t i = 0; i < tour.size() - 1; ++i) {\n            tour_length += dist_mat[tour[i]][tour[i+1]];\n        }\n        \n        if (tour_length < best_tour_length) {\n            best_tour_length = tour_length;\n            best_tour = tour;\n        }\n    }\n    \n    vector<int> seq = best_tour;\n\n    // Step 3: Simulated annealing with 2-opt moves\n    auto is_feasible = [&](const vector<int>& sequence) {\n        vector<int> first_pickup(50, -1);\n        vector<int> first_delivery(50, -1);\n        for (int idx = 0; idx < sequence.size(); ++idx) {\n            int point_idx = sequence[idx];\n            auto [order, type] = point_info[point_idx];\n            if (type == 0 && first_pickup[order] == -1) {\n                first_pickup[order] = idx;\n            }\n            if (type == 1 && first_delivery[order] == -1) {\n                first_delivery[order] = idx;\n            }\n        }\n        for (int i = 0; i < 50; ++i) {\n            if (first_pickup[i] > first_delivery[i]) {\n                return false;\n            }\n        }\n        return true;\n    };\n\n    // Calculate tour length\n    auto calculate_length = [&](const vector<int>& sequence) {\n        int length = dist_to_depot[sequence[0]] + dist_to_depot[sequence.back()];\n        for (size_t i = 0; i < sequence.size() - 1; ++i) {\n            length += dist_mat[sequence[i]][sequence[i+1]];\n        }\n        return length;\n    };\n\n    // Simulated annealing\n    srand(42); // Fixed seed for reproducibility\n    double temperature = 1000.0;\n    double cooling_rate = 0.9997;\n    int sa_iterations = 150000;\n    int current_length = calculate_length(seq);\n    int best_length = current_length;\n    vector<int> best_seq = seq;\n    \n    for (int iter = 0; iter < sa_iterations && temperature > 0.1; ++iter) {\n        // Generate a random 2-opt move\n        int i = rand() % (total_points - 1);\n        int j = i + 1 + rand() % (total_points - i - 1);\n        \n        // Calculate delta\n        int a = seq[i];\n        int b = seq[i + 1];\n        int c = seq[j];\n        int d = (j + 1 < total_points) ? seq[j + 1] : -1;\n\n        int old_len = dist_mat[a][b];\n        if (d == -1) old_len += dist_to_depot[c];\n        else old_len += dist_mat[c][d];\n\n        int new_len = dist_mat[a][c];\n        if (d == -1) new_len += dist_to_depot[b];\n        else new_len += dist_mat[b][d];\n\n        int delta = new_len - old_len;\n        \n        // Check feasibility if move improves\n        bool feasible = true;\n        if (delta < 0) {\n            vector<int> new_seq = seq;\n            reverse(new_seq.begin() + i + 1, new_seq.begin() + j + 1);\n            feasible = is_feasible(new_seq);\n        }\n        \n        // Accept move based on simulated annealing criterion\n        if (feasible && (delta < 0 || exp(-delta / temperature) > (rand() / (RAND_MAX + 1.0)))) {\n            if (delta < 0) {\n                // Apply the move\n                reverse(seq.begin() + i + 1, seq.begin() + j + 1);\n                current_length += delta;\n                \n                // Update best solution\n                if (current_length < best_length) {\n                    best_length = current_length;\n                    best_seq = seq;\n                }\n            } else {\n                // For accepting worse moves, we need to apply the move\n                reverse(seq.begin() + i + 1, seq.begin() + j + 1);\n                current_length += delta;\n            }\n        }\n        \n        temperature *= cooling_rate;\n    }\n    \n    // Use the best solution found\n    seq = best_seq;\n    \n    // Final deterministic 2-opt improvement\n    bool improved = true;\n    int passes = 0;\n    const int max_passes = 100;\n    while (improved && passes < max_passes) {\n        improved = false;\n        passes++;\n        int best_delta = 0;\n        int best_i = -1, best_j = -1;\n        bool best_feasible = false;\n        \n        for (int i = 0; i < total_points - 1; ++i) {\n            for (int j = i + 1; j < total_points; ++j) {\n                int a = seq[i];\n                int b = seq[i + 1];\n                int c = seq[j];\n                int d = (j + 1 < total_points) ? seq[j + 1] : -1;\n\n                int old_len = dist_mat[a][b];\n                if (d == -1) old_len += dist_to_depot[c];\n                else old_len += dist_mat[c][d];\n\n                int new_len = dist_mat[a][c];\n                if (d == -1) new_len += dist_to_depot[b];\n                else new_len += dist_mat[b][d];\n\n                int delta = new_len - old_len;\n                \n                if (delta < 0) {\n                    vector<int> new_seq = seq;\n                    reverse(new_seq.begin() + i + 1, new_seq.begin() + j + 1);\n                    if (is_feasible(new_seq)) {\n                        if (delta < best_delta) {\n                            best_delta = delta;\n                            best_i = i;\n                            best_j = j;\n                            best_feasible = true;\n                        }\n                    }\n                }\n            }\n        }\n        \n        if (best_feasible) {\n            reverse(seq.begin() + best_i + 1, seq.begin() + best_j + 1);\n            improved = true;\n        }\n    }\n\n    // Step 4: Output results\n    cout << 50 << \" \";\n    for (int i = 0; i < 50; ++i) {\n        cout << selected_orders[i] + 1 << \" \";\n    }\n    cout << \"\\n\";\n\n    cout << 102 << \" 400 400 \";\n    for (int idx : seq) {\n        cout << points[idx].x << \" \" << points[idx].y << \" \";\n    }\n    cout << \"400 400\\n\";\n\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Edge {\n    int u, v, d;\n};\n\nstruct DSU {\n    vector<int> parent, sz;\n    DSU(int n) : parent(n), sz(n, 1) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        if (parent[x] != x) parent[x] = find(parent[x]);\n        return parent[x];\n    }\n    bool unite(int x, int y) {\n        x = find(x), y = find(y);\n        if (x == y) return false;\n        if (sz[x] < sz[y]) swap(x, y);\n        parent[y] = x;\n        sz[x] += sz[y];\n        return true;\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(N), y(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> x[i] >> y[i];\n    }\n\n    const int M = 5 * (N - 1);   // 1995\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        int dx = x[u] - x[v];\n        int dy = y[u] - y[v];\n        double dist = sqrt(dx * dx + dy * dy);\n        int d = (int)(dist + 0.5);   // round to nearest integer\n        edges[i] = {u, v, d};\n    }\n\n    // Precompute for each edge whether it is a bridge in the suffix graph (edges i..M-1)\n    vector<bool> is_bridge(M, false);\n    for (int i = 0; i < M; ++i) {\n        // build adjacency for edges i..M-1\n        vector<vector<pair<int, int>>> adj(N);\n        for (int j = i; j < M; ++j) {\n            int u = edges[j].u, v = edges[j].v;\n            adj[u].emplace_back(v, j);\n            adj[v].emplace_back(u, j);\n        }\n\n        vector<int> disc(N, -1), low(N, -1);\n        int timer = 0;\n        vector<bool> bridge_this(M, false);\n\n        function<void(int, int)> dfs = [&](int v, int parent_edge) {\n            disc[v] = low[v] = timer++;\n            for (auto [to, id] : adj[v]) {\n                if (id == parent_edge) continue;\n                if (disc[to] == -1) {\n                    dfs(to, id);\n                    low[v] = min(low[v], low[to]);\n                    if (low[to] > disc[v]) {\n                        bridge_this[id] = true;\n                    }\n                } else {\n                    low[v] = min(low[v], disc[to]);\n                }\n            }\n        };\n\n        for (int v = 0; v < N; ++v) {\n            if (disc[v] == -1) {\n                dfs(v, -1);\n            }\n        }\n        is_bridge[i] = bridge_this[i];\n    }\n\n    DSU dsu(N);\n    for (int i = 0; i < M; ++i) {\n        int l;\n        cin >> l;\n        int u = edges[i].u, v = edges[i].v;\n        bool accept = false;\n        if (dsu.find(u) == dsu.find(v)) {\n            accept = false;   // would create a cycle\n        } else {\n            if (is_bridge[i]) {\n                accept = true;   // forced to keep connectivity\n            } else {\n                // accept if weight is at most twice the lower bound (mean)\n                if (l <= 2 * edges[i].d) {\n                    accept = true;\n                } else {\n                    accept = false;\n                }\n            }\n        }\n        cout << (accept ? 1 : 0) << endl;\n        if (accept) {\n            dsu.unite(u, v);\n        }\n    }\n    return 0;\n}","ahc008":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <string>\n#include <algorithm>\n#include <utility>\n#include <cmath>\n\nusing namespace std;\n\nconst int MAXN = 30;\nconst int dirs[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};\n\n// Global grids\nbool wall[MAXN][MAXN] = {false};\nbool to_build[MAXN][MAXN] = {false};\nint owner[MAXN][MAXN];\n\nstruct HumanState {\n    int state; // 0: building non-gate walls, 1: waiting (gate not built), 2: done (gate built)\n    int gate_x, gate_y;\n    int out_x, out_y;\n    vector<pair<int, int>> non_gate_walls;\n};\n\n// BFS returning distances and parent pointers\npair<vector<vector<int>>, vector<vector<pair<int, int>>>> bfs(int sx, int sy, int owner_idx, bool allow_all_owners = false) {\n    vector<vector<int>> dist(MAXN, vector<int>(MAXN, -1));\n    vector<vector<pair<int, int>>> parent(MAXN, vector<pair<int, int>>(MAXN, {-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 + dirs[d][0], ny = y + dirs[d][1];\n            if (nx < 0 || nx >= MAXN || ny < 0 || ny >= MAXN) continue;\n            if (wall[nx][ny]) continue;\n            if (!allow_all_owners && owner[nx][ny] != owner_idx) continue;\n            if (dist[nx][ny] != -1) continue;\n            dist[nx][ny] = dist[x][y] + 1;\n            parent[nx][ny] = {x, y};\n            q.push({nx, ny});\n        }\n    }\n    return {dist, parent};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N;\n    vector<pair<int, int>> pets(N);\n    vector<int> pet_types(N);\n    for (int i = 0; i < N; ++i) {\n        int x, y, t;\n        cin >> x >> y >> t;\n        pets[i] = {x - 1, y - 1};\n        pet_types[i] = t;\n    }\n    cin >> M;\n    vector<pair<int, int>> humans(M);\n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        humans[i] = {x - 1, y - 1};\n    }\n\n    // compute owner based on initial human positions\n    for (int x = 0; x < MAXN; ++x) {\n        for (int y = 0; y < MAXN; ++y) {\n            int best_dist = 1000000, best_idx = -1;\n            for (int i = 0; i < M; ++i) {\n                int d = abs(x - humans[i].first) + abs(y - humans[i].second);\n                if (d < best_dist) {\n                    best_dist = d;\n                    best_idx = i;\n                }\n            }\n            owner[x][y] = best_idx;\n        }\n    }\n\n    // mark boundary cells as to_build\n    for (int x = 0; x < MAXN; ++x) {\n        for (int y = 0; y < MAXN; ++y) {\n            bool is_human = false;\n            for (int i = 0; i < M; ++i) {\n                if (humans[i].first == x && humans[i].second == y) {\n                    is_human = true;\n                    break;\n                }\n            }\n            if (is_human) continue;\n\n            bool boundary = false;\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 >= MAXN || ny < 0 || ny >= MAXN) continue;\n                if (owner[nx][ny] != owner[x][y]) {\n                    boundary = true;\n                    break;\n                }\n            }\n            if (boundary) {\n                to_build[x][y] = true;\n            }\n        }\n    }\n\n    // initialize human states with gate and outside cell\n    vector<HumanState> human_states(M);\n    for (int i = 0; i < M; ++i) {\n        HumanState hs;\n        hs.state = 0;\n\n        // collect all to_build cells owned by this human\n        vector<pair<int, int>> walls;\n        for (int x = 0; x < MAXN; ++x) {\n            for (int y = 0; y < MAXN; ++y) {\n                if (to_build[x][y] && owner[x][y] == i) {\n                    walls.push_back({x, y});\n                }\n            }\n        }\n\n        // choose gate: closest to initial human position\n        int best_dist = 1000000;\n        pair<int, int> gate = {-1, -1};\n        for (auto& w : walls) {\n            int d = abs(w.first - humans[i].first) + abs(w.second - humans[i].second);\n            if (d < best_dist) {\n                best_dist = d;\n                gate = w;\n            }\n        }\n        hs.gate_x = gate.first;\n        hs.gate_y = gate.second;\n\n        // find outside cell (neighbor with different owner)\n        for (int d = 0; d < 4; ++d) {\n            int nx = gate.first + dirs[d][0], ny = gate.second + dirs[d][1];\n            if (nx < 0 || nx >= MAXN || ny < 0 || ny >= MAXN) continue;\n            if (owner[nx][ny] != i) {\n                hs.out_x = nx;\n                hs.out_y = ny;\n                break;\n            }\n        }\n\n        // non-gate walls\n        for (auto& w : walls) {\n            if (w.first != gate.first || w.second != gate.second) {\n                hs.non_gate_walls.push_back(w);\n            }\n        }\n        human_states[i] = hs;\n    }\n\n    // main loop for 300 turns\n    for (int turn = 0; turn < 300; ++turn) {\n        string actions(M, '.');\n\n        for (int i = 0; i < M; ++i) {\n            auto& hs = human_states[i];\n            if (hs.state == 2) {\n                actions[i] = '.';\n                continue;\n            }\n\n            bool handled = false;\n            if (hs.state == 0) {\n                if (hs.non_gate_walls.empty()) {\n                    hs.state = 1;\n                    // fall through to state 1\n                } else {\n                    // state 0: build non-gate walls\n                    auto [dist, parent] = bfs(humans[i].first, humans[i].second, i);\n                    int best_wall_x = -1, best_wall_y = -1;\n                    int best_adj_x = -1, best_adj_y = -1;\n                    int best_dist = -1;\n\n                    for (auto& w : hs.non_gate_walls) {\n                        int wx = w.first, wy = w.second;\n                        if (wall[wx][wy]) continue;\n                        for (int d = 0; d < 4; ++d) {\n                            int nx = wx + dirs[d][0], ny = wy + dirs[d][1];\n                            if (nx < 0 || nx >= MAXN || ny < 0 || ny >= MAXN) continue;\n                            if (wall[nx][ny]) continue;\n                            if (owner[nx][ny] != i) continue;\n                            if (dist[nx][ny] == -1) continue;\n                            if (dist[nx][ny] > best_dist) {\n                                best_dist = dist[nx][ny];\n                                best_wall_x = wx;\n                                best_wall_y = wy;\n                                best_adj_x = nx;\n                                best_adj_y = ny;\n                            }\n                        }\n                    }\n\n                    if (best_wall_x == -1) {\n                        actions[i] = '.';\n                    } else {\n                        if (abs(humans[i].first - best_wall_x) + abs(humans[i].second - best_wall_y) == 1) {\n                            // try to build\n                            bool safe = true;\n                            for (const auto& p : pets) {\n                                if (p.first == best_wall_x && p.second == best_wall_y) {\n                                    safe = false;\n                                    break;\n                                }\n                            }\n                            if (safe) {\n                                for (int d = 0; d < 4; ++d) {\n                                    int nx = best_wall_x + dirs[d][0], ny = best_wall_y + dirs[d][1];\n                                    if (nx < 0 || nx >= MAXN || ny < 0 || ny >= MAXN) continue;\n                                    for (const auto& p : pets) {\n                                        if (p.first == nx && p.second == ny) {\n                                            safe = false;\n                                            break;\n                                        }\n                                    }\n                                    if (!safe) break;\n                                }\n                            }\n                            if (safe) {\n                                if (best_wall_x == humans[i].first - 1 && best_wall_y == humans[i].second)\n                                    actions[i] = 'u';\n                                else if (best_wall_x == humans[i].first + 1 && best_wall_y == humans[i].second)\n                                    actions[i] = 'd';\n                                else if (best_wall_x == humans[i].first && best_wall_y == humans[i].second - 1)\n                                    actions[i] = 'l';\n                                else if (best_wall_x == humans[i].first && best_wall_y == humans[i].second + 1)\n                                    actions[i] = 'r';\n                                else\n                                    actions[i] = '.';\n\n                                if (actions[i] != '.') {\n                                    auto it = find(hs.non_gate_walls.begin(), hs.non_gate_walls.end(),\n                                                   make_pair(best_wall_x, best_wall_y));\n                                    if (it != hs.non_gate_walls.end())\n                                        hs.non_gate_walls.erase(it);\n                                }\n                            } else {\n                                actions[i] = '.';\n                            }\n                        } else {\n                            // move towards best_adj\n                            pair<int, int> next = {best_adj_x, best_adj_y};\n                            while (parent[next.first][next.second] != make_pair(humans[i].first, humans[i].second)) {\n                                next = parent[next.first][next.second];\n                            }\n                            if (next.first == humans[i].first - 1 && next.second == humans[i].second)\n                                actions[i] = 'U';\n                            else if (next.first == humans[i].first + 1 && next.second == humans[i].second)\n                                actions[i] = 'D';\n                            else if (next.first == humans[i].first && next.second == humans[i].second - 1)\n                                actions[i] = 'L';\n                            else if (next.first == humans[i].first && next.second == humans[i].second + 1)\n                                actions[i] = 'R';\n                            else\n                                actions[i] = '.';\n                        }\n                    }\n                    handled = true;\n                }\n            }\n\n            if (!handled && hs.state == 1) {\n                // state 1: waiting for pets to leave\n                // compute connected component and count pets\n                vector<vector<bool>> visited(MAXN, vector<bool>(MAXN, false));\n                queue<pair<int, int>> q;\n                q.push({humans[i].first, humans[i].second});\n                visited[humans[i].first][humans[i].second] = true;\n                int pet_count = 0;\n                while (!q.empty()) {\n                    auto [x, y] = q.front(); q.pop();\n                    for (const auto& p : pets) {\n                        if (p.first == x && p.second == y) {\n                            pet_count++;\n                            break;\n                        }\n                    }\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 >= MAXN || ny < 0 || ny >= MAXN) continue;\n                        if (wall[nx][ny]) continue;\n                        if (visited[nx][ny]) continue;\n                        visited[nx][ny] = true;\n                        q.push({nx, ny});\n                    }\n                }\n\n                if (pet_count == 0) {\n                    // no pets in component\n                    if (humans[i].first == hs.gate_x && humans[i].second == hs.gate_y) {\n                        // on gate, try to build\n                        bool safe = true;\n                        for (const auto& p : pets) {\n                            if (p.first == hs.gate_x && p.second == hs.gate_y) {\n                                safe = false;\n                                break;\n                            }\n                        }\n                        if (safe) {\n                            for (int d = 0; d < 4; ++d) {\n                                int nx = hs.gate_x + dirs[d][0], ny = hs.gate_y + dirs[d][1];\n                                if (nx < 0 || nx >= MAXN || ny < 0 || ny >= MAXN) continue;\n                                for (const auto& p : pets) {\n                                    if (p.first == nx && p.second == ny) {\n                                        safe = false;\n                                        break;\n                                    }\n                                }\n                                if (!safe) break;\n                            }\n                        }\n                        if (safe) {\n                            if (hs.gate_x == humans[i].first - 1 && hs.gate_y == humans[i].second)\n                                actions[i] = 'u';\n                            else if (hs.gate_x == humans[i].first + 1 && hs.gate_y == humans[i].second)\n                                actions[i] = 'd';\n                            else if (hs.gate_x == humans[i].first && hs.gate_y == humans[i].second - 1)\n                                actions[i] = 'l';\n                            else if (hs.gate_x == humans[i].first && hs.gate_y == humans[i].second + 1)\n                                actions[i] = 'r';\n                            else\n                                actions[i] = '.';\n\n                            if (actions[i] != '.') {\n                                hs.state = 2;\n                                wall[hs.gate_x][hs.gate_y] = true;\n                                to_build[hs.gate_x][hs.gate_y] = false;\n                            }\n                        } else {\n                            actions[i] = '.';\n                        }\n                    } else {\n                        // move towards gate\n                        auto [dist, parent] = bfs(humans[i].first, humans[i].second, i);\n                        if (dist[hs.gate_x][hs.gate_y] == -1) {\n                            actions[i] = '.';\n                        } else {\n                            pair<int, int> cur = {hs.gate_x, hs.gate_y};\n                            while (parent[cur.first][cur.second] != make_pair(humans[i].first, humans[i].second)) {\n                                cur = parent[cur.first][cur.second];\n                            }\n                            if (cur.first == humans[i].first - 1 && cur.second == humans[i].second)\n                                actions[i] = 'U';\n                            else if (cur.first == humans[i].first + 1 && cur.second == humans[i].second)\n                                actions[i] = 'D';\n                            else if (cur.first == humans[i].first && cur.second == humans[i].second - 1)\n                                actions[i] = 'L';\n                            else if (cur.first == humans[i].first && cur.second == humans[i].second + 1)\n                                actions[i] = 'R';\n                            else\n                                actions[i] = '.';\n                        }\n                    }\n                } else {\n                    // pets present, move to outside cell\n                    if (wall[hs.out_x][hs.out_y]) {\n                        // outside cell is a wall, cannot move there\n                        actions[i] = '.';\n                    } else if (humans[i].first == hs.out_x && humans[i].second == hs.out_y) {\n                        actions[i] = '.';\n                    } else {\n                        auto [dist, parent] = bfs(humans[i].first, humans[i].second, i, true);\n                        if (dist[hs.out_x][hs.out_y] == -1) {\n                            actions[i] = '.';\n                        } else {\n                            pair<int, int> cur = {hs.out_x, hs.out_y};\n                            while (parent[cur.first][cur.second] != make_pair(humans[i].first, humans[i].second)) {\n                                cur = parent[cur.first][cur.second];\n                            }\n                            if (cur.first == humans[i].first - 1 && cur.second == humans[i].second)\n                                actions[i] = 'U';\n                            else if (cur.first == humans[i].first + 1 && cur.second == humans[i].second)\n                                actions[i] = 'D';\n                            else if (cur.first == humans[i].first && cur.second == humans[i].second - 1)\n                                actions[i] = 'L';\n                            else if (cur.first == humans[i].first && cur.second == humans[i].second + 1)\n                                actions[i] = 'R';\n                            else\n                                actions[i] = '.';\n                        }\n                    }\n                }\n            }\n        }\n\n        // output actions\n        cout << actions << endl;\n        cout.flush();\n\n        // apply human actions\n        for (int i = 0; i < M; ++i) {\n            char act = actions[i];\n            int x = humans[i].first, y = humans[i].second;\n            if (act == 'u' || act == 'd' || act == 'l' || act == 'r') {\n                int wx = x, wy = y;\n                if (act == 'u') wx = x - 1;\n                else if (act == 'd') wx = x + 1;\n                else if (act == 'l') wy = y - 1;\n                else if (act == 'r') wy = y + 1;\n                wall[wx][wy] = true;\n                to_build[wx][wy] = false;\n            } else if (act == 'U' || act == 'D' || act == 'L' || act == 'R') {\n                if (act == 'U') humans[i].first = x - 1;\n                else if (act == 'D') humans[i].first = x + 1;\n                else if (act == 'L') humans[i].second = y - 1;\n                else if (act == 'R') humans[i].second = y + 1;\n            }\n        }\n\n        // read pet movements\n        vector<string> pet_moves(N);\n        for (int i = 0; i < N; ++i) {\n            cin >> pet_moves[i];\n        }\n\n        // update pet positions\n        for (int i = 0; i < N; ++i) {\n            int x = pets[i].first, y = pets[i].second;\n            for (char c : pet_moves[i]) {\n                if (c == 'U') --x;\n                else if (c == 'D') ++x;\n                else if (c == 'L') --y;\n                else if (c == 'R') ++y;\n            }\n            pets[i] = {x, y};\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cstring>\n#include <algorithm>\n#include <cmath>\nusing namespace std;\n\nconst int N = 20;\nconst int L = 200;\nconst int STATES = N * N;\nconst int BEAM_WIDTH = 10;\n\nint neighbor[STATES][4];\ndouble stay_prob[STATES][4];\ndouble move_prob[STATES][4];\ndouble V[STATES][L + 1];\n\nstruct Candidate {\n    vector<double> bel;\n    double accum;\n    string seq;\n    double estimate;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj, ti, tj;\n    double p;\n    cin >> si >> sj >> ti >> tj >> p;\n\n    vector<string> h(N);\n    for (int i = 0; i < N; ++i) cin >> h[i];\n    vector<string> v(N - 1);\n    for (int i = 0; i < N - 1; ++i) cin >> v[i];\n\n    // Build neighbour table and transition probabilities\n    memset(neighbor, -1, sizeof(neighbor));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int id = i * N + j;\n            // up\n            if (i > 0 && v[i - 1][j] == '0')\n                neighbor[id][0] = (i - 1) * N + j;\n            // down\n            if (i < N - 1 && v[i][j] == '0')\n                neighbor[id][1] = (i + 1) * N + j;\n            // left\n            if (j > 0 && h[i][j - 1] == '0')\n                neighbor[id][2] = i * N + (j - 1);\n            // right\n            if (j < N - 1 && h[i][j] == '0')\n                neighbor[id][3] = i * N + (j + 1);\n        }\n    }\n\n    // Precompute stay_prob and move_prob for each state and action\n    for (int s = 0; s < STATES; ++s) {\n        for (int a = 0; a < 4; ++a) {\n            if (neighbor[s][a] == -1) {\n                stay_prob[s][a] = 1.0;\n                move_prob[s][a] = 0.0;\n            } else {\n                stay_prob[s][a] = p;\n                move_prob[s][a] = 1.0 - p;\n            }\n        }\n    }\n\n    int start_id = si * N + sj;\n    int goal_id = ti * N + tj;\n\n    // DP for optimal closed\u2011loop value V[state][rem]\n    for (int s = 0; s < STATES; ++s)\n        for (int r = 0; r <= L; ++r)\n            V[s][r] = 0.0;\n\n    for (int rem = 1; rem <= L; ++rem) {\n        double reward_reach = 200.0 + rem;   // 401 - (200 - rem + 1)\n        for (int s = 0; s < STATES; ++s) {\n            if (s == goal_id) {\n                V[s][rem] = 0.0;\n                continue;\n            }\n            double best = 0.0;\n            for (int a = 0; a < 4; ++a) {\n                int nb = neighbor[s][a];\n                double sp = stay_prob[s][a];\n                double mp = move_prob[s][a];\n                double expected = sp * V[s][rem - 1];\n                if (mp > 0.0) {\n                    if (nb == goal_id) {\n                        expected += mp * reward_reach;\n                    } else {\n                        expected += mp * V[nb][rem - 1];\n                    }\n                }\n                if (expected > best) best = expected;\n            }\n            V[s][rem] = best;\n        }\n    }\n\n    // Beam search for the memorized string\n    vector<Candidate> beam;\n    vector<double> start_bel(STATES, 0.0);\n    start_bel[start_id] = 1.0;\n    beam.push_back({start_bel, 0.0, \"\", 0.0});\n\n    const char dir_chars[] = \"UDLR\";\n\n    for (int step = 1; step <= L; ++step) {\n        int rem = L - step;   // steps remaining after this one\n        vector<Candidate> next_beam;\n        next_beam.reserve(beam.size() * 4);\n\n        for (const auto& cand : beam) {\n            for (int a = 0; a < 4; ++a) {\n                vector<double> new_bel(STATES, 0.0);\n                double immediate_reward = 0.0;\n\n                for (int s = 0; s < STATES; ++s) {\n                    double prob = cand.bel[s];\n                    if (prob == 0.0) continue;\n                    int nb = neighbor[s][a];\n                    double sp = stay_prob[s][a];\n                    double mp = move_prob[s][a];\n                    new_bel[s] += prob * sp;\n                    if (mp > 0.0) {\n                        if (nb == goal_id) {\n                            immediate_reward += prob * mp * (401 - step);\n                        } else {\n                            new_bel[nb] += prob * mp;\n                        }\n                    }\n                }\n\n                double new_accum = cand.accum + immediate_reward;\n                double heuristic = 0.0;\n                for (int s = 0; s < STATES; ++s)\n                    heuristic += new_bel[s] * V[s][rem];\n                double estimate = new_accum + heuristic;\n\n                Candidate new_cand;\n                new_cand.bel = move(new_bel);\n                new_cand.accum = new_accum;\n                new_cand.seq = cand.seq + dir_chars[a];\n                new_cand.estimate = estimate;\n                next_beam.push_back(move(new_cand));\n            }\n        }\n\n        // Keep only the top BEAM_WIDTH candidates by estimate\n        sort(next_beam.begin(), next_beam.end(),\n             [](const Candidate& x, const Candidate& y) {\n                 return x.estimate > y.estimate;\n             });\n        if (next_beam.size() > BEAM_WIDTH)\n            next_beam.resize(BEAM_WIDTH);\n        beam = move(next_beam);\n    }\n\n    // Select the candidate with the highest actual accumulated score\n    Candidate best = *max_element(beam.begin(), beam.end(),\n                                  [](const Candidate& x, const Candidate& y) {\n                                      return x.accum < y.accum;\n                                  });\n    cout << best.seq << endl;\n\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30;\nconst int D = 4; // 0: left, 1: up, 2: right, 3: down\nconst int di[D] = {0, -1, 0, 1};\nconst int dj[D] = {-1, 0, 1, 0};\nconst int MAX_STATES = N * N * D;\n\n// to[t][d] = exit direction when entering from d, or -1 if impossible\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\nint type[N][N];\nint rot[N][N];\nint best_rot[N][N];\nint best_score = 0;\n\ninline int get_exit(int t, int r, int d) {\n    int d_in = ((d - r) + 4) & 3;\n    int e = to[t][d_in];\n    if (e == -1) return -1;\n    return (e + r) & 3;\n}\n\ninline int state_id(int i, int j, int d) {\n    return (i * N + j) * D + d;\n}\n\ninline void state_coord(int id, int& i, int& j, int& d) {\n    d = id % D;\n    int ij = id / D;\n    j = ij % N;\n    i = ij / N;\n}\n\nint compute_score(const int rot[N][N]) {\n    static int status[MAX_STATES]; // 0: unvisited, 1: visiting, 2: processed\n    memset(status, 0, sizeof(status));\n    \n    vector<int> cycles;\n    int path[MAX_STATES];\n    \n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            for (int d = 0; d < D; ++d) {\n                int sid = state_id(i, j, d);\n                if (status[sid]) continue;\n                \n                int t = type[i][j];\n                int r = rot[i][j];\n                if (get_exit(t, r, d) == -1) {\n                    status[sid] = 2;\n                    continue;\n                }\n                \n                int path_len = 0;\n                int ci = i, cj = j, cd = d;\n                int cur_sid = sid;\n                \n                while (true) {\n                    if (status[cur_sid] == 2) {\n                        // Mark all states in path as processed\n                        for (int k = 0; k < path_len; ++k) {\n                            status[path[k]] = 2;\n                        }\n                        break;\n                    }\n                    if (status[cur_sid] == 1) {\n                        // Found a cycle\n                        int cycle_start = -1;\n                        for (int k = 0; k < path_len; ++k) {\n                            if (path[k] == cur_sid) {\n                                cycle_start = k;\n                                break;\n                            }\n                        }\n                        int cycle_len = path_len - cycle_start;\n                        cycles.push_back(cycle_len);\n                        // Mark all states in path as processed\n                        for (int k = 0; k < path_len; ++k) {\n                            status[path[k]] = 2;\n                        }\n                        break;\n                    }\n                    \n                    status[cur_sid] = 1;\n                    path[path_len++] = cur_sid;\n                    \n                    // Compute next state\n                    int t2 = type[ci][cj];\n                    int r2 = rot[ci][cj];\n                    int d2 = get_exit(t2, r2, cd);\n                    if (d2 == -1) {\n                        for (int k = 0; k < path_len; ++k) {\n                            status[path[k]] = 2;\n                        }\n                        break;\n                    }\n                    \n                    int ni = ci + di[d2];\n                    int nj = cj + dj[d2];\n                    if (ni < 0 || ni >= N || nj < 0 || nj >= N) {\n                        for (int k = 0; k < path_len; ++k) {\n                            status[path[k]] = 2;\n                        }\n                        break;\n                    }\n                    \n                    int nd = (d2 + 2) & 3;\n                    if (get_exit(type[ni][nj], rot[ni][nj], nd) == -1) {\n                        for (int k = 0; k < path_len; ++k) {\n                            status[path[k]] = 2;\n                        }\n                        break;\n                    }\n                    \n                    ci = ni;\n                    cj = nj;\n                    cd = nd;\n                    cur_sid = state_id(ci, cj, cd);\n                }\n            }\n        }\n    }\n    \n    sort(cycles.rbegin(), cycles.rend());\n    if (cycles.size() < 2) return 0;\n    return cycles[0] * cycles[1];\n}\n\nvoid greedy_init() {\n    for (int iter = 0; iter < 5; ++iter) {\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                int best_r = rot[i][j];\n                int best_match = -1;\n                for (int r = 0; r < 4; ++r) {\n                    rot[i][j] = r;\n                    int match = 0;\n                    for (int d = 0; d < 4; ++d) {\n                        int t = type[i][j];\n                        if (get_exit(t, r, d) != -1) {\n                            int ni = i + di[d];\n                            int nj = j + dj[d];\n                            if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                                int nd = (d+2)%4;\n                                if (get_exit(type[ni][nj], rot[ni][nj], nd) != -1) {\n                                    match++;\n                                }\n                            }\n                        }\n                    }\n                    if (match > best_match) {\n                        best_match = match;\n                        best_r = r;\n                    }\n                }\n                rot[i][j] = best_r;\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // read input\n    for (int i = 0; i < N; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; ++j) {\n            type[i][j] = s[j] - '0';\n        }\n    }\n\n    // random number generator\n    random_device rd;\n    mt19937 rng(rd());\n    uniform_real_distribution<double> uni(0.0, 1.0);\n    uniform_int_distribution<int> rand_tile(0, N-1);\n    uniform_int_distribution<int> rand_rot(0, 3);\n\n    // initialize with greedy method\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            rot[i][j] = rand_rot(rng);\n    \n    greedy_init();\n    \n    int current_score = compute_score(rot);\n    best_score = current_score;\n    memcpy(best_rot, rot, sizeof(rot));\n\n    // simulated annealing parameters\n    const int max_iter = 20000;\n    const double T0 = 1000.0;\n    double T = T0;\n\n    for (int iter = 0; iter < max_iter; ++iter) {\n        // pick a random tile\n        int i = rand_tile(rng);\n        int j = rand_tile(rng);\n        int old_r = rot[i][j];\n        int new_r = (old_r + 1 + rand_rot(rng)) % 4;\n        rot[i][j] = new_r;\n\n        int new_score = compute_score(rot);\n        double delta = new_score - current_score;\n        if (delta > 0 || uni(rng) < exp(delta / T)) {\n            current_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            rot[i][j] = old_r;\n        }\n\n        // cool down\n        T = T0 * (1.0 - iter / (double)max_iter);\n    }\n\n    // output best rotations\n    string ans;\n    ans.reserve(N * N);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            ans += char('0' + best_rot[i][j]);\n    cout << ans << endl;\n\n    return 0;\n}","ahc011":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <cstring>\n#include <stack>\n\nusing namespace std;\n\nint N, T;\nint board[10][10];\nint empty_r, empty_c;\nint total_tiles; // N*N-1\n\n// precomputed bits for patterns 0..15\nbool has_up[16], has_down[16], has_left[16], has_right[16];\n\nvoid precompute_bits() {\n    for (int p = 0; p < 16; ++p) {\n        has_left[p]  = p & 1;\n        has_up[p]    = p & 2;\n        has_right[p] = p & 4;\n        has_down[p]  = p & 8;\n    }\n}\n\n// convert hex char to integer\nint hex_to_int(char c) {\n    if ('0' <= c && c <= '9') return c - '0';\n    return 10 + c - 'a';\n}\n\n// compute size of largest tree in the current board\nint compute_tree_size(int b[10][10]) {\n    bool vis[10][10] = {false};\n    int max_size = 0;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (b[i][j] == 0 || vis[i][j]) continue;\n\n            // DFS stack (encoded as i*N + j)\n            int stack[100];\n            int top = 0;\n            stack[top++] = i * N + j;\n            vis[i][j] = true;\n\n            int vertices = 0, edges = 0;\n            while (top) {\n                int pos = stack[--top];\n                int x = pos / N, y = pos % N;\n                ++vertices;\n                int p = b[x][y];\n\n                // up\n                if (has_up[p] && x > 0 && b[x-1][y] && has_down[b[x-1][y]]) {\n                    if (!vis[x-1][y]) {\n                        ++edges;\n                        vis[x-1][y] = true;\n                        stack[top++] = (x-1)*N + y;\n                    }\n                }\n                // down\n                if (has_down[p] && x+1 < N && b[x+1][y] && has_up[b[x+1][y]]) {\n                    if (!vis[x+1][y]) {\n                        ++edges;\n                        vis[x+1][y] = true;\n                        stack[top++] = (x+1)*N + y;\n                    }\n                }\n                // left\n                if (has_left[p] && y > 0 && b[x][y-1] && has_right[b[x][y-1]]) {\n                    if (!vis[x][y-1]) {\n                        ++edges;\n                        vis[x][y-1] = true;\n                        stack[top++] = x*N + (y-1);\n                    }\n                }\n                // right\n                if (has_right[p] && y+1 < N && b[x][y+1] && has_left[b[x][y+1]]) {\n                    if (!vis[x][y+1]) {\n                        ++edges;\n                        vis[x][y+1] = true;\n                        stack[top++] = x*N + (y+1);\n                    }\n                }\n            }\n\n            if (edges == vertices - 1) {\n                max_size = max(max_size, vertices);\n            }\n        }\n    }\n    return max_size;\n}\n\n// simulated annealing solver\nstring solve() {\n    precompute_bits();\n    total_tiles = N * N - 1;\n\n    // find initial empty position\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (board[i][j] == 0) {\n                empty_r = i;\n                empty_c = j;\n            }\n\n    // current state\n    int cur_board[10][10];\n    memcpy(cur_board, board, sizeof(board));\n    int cur_er = empty_r, cur_ec = empty_c;\n    int cur_S = compute_tree_size(cur_board);\n    string cur_moves = \"\";\n    int steps = 0;\n\n    // best state\n    int best_S = cur_S;\n    string best_moves = \"\";\n    int best_score;\n    if (cur_S == total_tiles)\n        best_score = (int)round(500000.0 * (2.0 - 0.0 / T));\n    else\n        best_score = (int)round(500000.0 * cur_S / total_tiles);\n\n    // SA parameters\n    double temp = 5.0;\n    const double cooling = 0.99995;\n    const double min_temp = 1e-3;\n\n    // random generators\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> dir_dist(0, 3);\n    uniform_real_distribution<double> prob_dist(0.0, 1.0);\n\n    // direction vectors and corresponding move characters\n    const int dr[4] = {-1, 1, 0, 0};\n    const int dc[4] = {0, 0, -1, 1};\n    const char move_char[4] = {'U', 'D', 'L', 'R'};\n\n    auto start_time = chrono::steady_clock::now();\n    const double time_limit = 2.9; // seconds\n    int iteration = 0;\n\n    while (steps < T) {\n        // time check every 20000 iterations\n        if ((iteration & 20000) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > time_limit) break;\n        }\n        ++iteration;\n\n        int dir = dir_dist(rng);\n        int nr = cur_er + dr[dir];\n        int nc = cur_ec + dc[dir];\n        if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n\n        // perform move\n        swap(cur_board[cur_er][cur_ec], cur_board[nr][nc]);\n        int new_S = compute_tree_size(cur_board);\n        double delta = new_S - cur_S;\n        bool accept = false;\n\n        if (delta > 0)\n            accept = true;\n        else if (temp > 1e-9) {\n            double prob = exp(delta / temp);\n            if (prob_dist(rng) < prob)\n                accept = true;\n        }\n\n        if (accept) {\n            cur_moves += move_char[dir];\n            ++steps;\n            cur_er = nr;\n            cur_ec = nc;\n            cur_S = new_S;\n\n            // if we reached a full tree, we are done (first full tree gives minimal K)\n            if (cur_S == total_tiles) {\n                best_moves = cur_moves;\n                break;\n            }\n\n            // otherwise update best score if improved\n            int K = steps;\n            int score;\n            if (cur_S == total_tiles)\n                score = (int)round(500000.0 * (2.0 - (double)K / T));\n            else\n                score = (int)round(500000.0 * cur_S / total_tiles);\n            if (score > best_score) {\n                best_score = score;\n                best_S = cur_S;\n                best_moves = cur_moves;\n            }\n        } else {\n            // revert move\n            swap(cur_board[cur_er][cur_ec], cur_board[nr][nc]);\n        }\n\n        // cool down\n        temp *= cooling;\n        if (temp < min_temp) temp = min_temp;\n    }\n\n    return best_moves;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> T;\n    for (int i = 0; i < N; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; ++j) {\n            board[i][j] = hex_to_int(s[j]);\n        }\n    }\n\n    string ans = solve();\n    cout << ans << endl;\n\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\nusing int64 = long long;\n\nstruct Line {\n    int64 px, py, qx, qy;\n    int64 dx, dy;\n};\n\nstruct ArrayHash {\n    size_t operator()(const array<uint64_t,2>& a) const {\n        return a[0] ^ (a[1] * 0x9e3779b97f4a7c15ULL);\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, K;\n    cin >> N >> K;\n    int a[11] = {0};\n    for (int d = 1; d <= 10; ++d) cin >> a[d];\n    vector<int64> xs(N), ys(N);\n    for (int i = 0; i < N; ++i) cin >> xs[i] >> ys[i];\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> coord_dist(-20000, 20000);\n    uniform_int_distribution<int> delta_dist(-5, 5);\n\n    // Helper to check that a line does not pass through any strawberry\n    auto is_valid_line = [&](const Line& line) -> bool {\n        if (line.px == line.qx && line.py == line.qy) return false;\n        for (int i = 0; i < N; ++i) {\n            int64 cross = line.dx * (ys[i] - line.py) - line.dy * (xs[i] - line.px);\n            if (cross == 0) return false;\n        }\n        return true;\n    };\n\n    // Helper to check that the line actually cuts the cake (distance < 10000)\n    auto line_cuts_circle = [&](const Line& line) -> bool {\n        int64 num = abs(line.qx * line.py - line.qy * line.px);\n        int64 len2 = line.dx * line.dx + line.dy * line.dy;\n        return num * num < 10000LL * 10000LL * len2;\n    };\n\n    // Generate initial K lines\n    vector<Line> lines(K);\n    for (int i = 0; i < K; ++i) {\n        while (true) {\n            Line line;\n            line.px = coord_dist(rng);\n            line.py = coord_dist(rng);\n            line.qx = coord_dist(rng);\n            line.qy = coord_dist(rng);\n            line.dx = line.qx - line.px;\n            line.dy = line.qy - line.py;\n            if (!is_valid_line(line)) continue;\n            if (!line_cuts_circle(line)) continue;\n            lines[i] = line;\n            break;\n        }\n    }\n\n    // Compute initial patterns and group counts\n    vector<array<uint64_t,2>> point_pat(N);\n    unordered_map<array<uint64_t,2>, int, ArrayHash> pat_cnt;\n    for (int i = 0; i < N; ++i) {\n        array<uint64_t,2> pat = {0, 0};\n        for (int l = 0; l < K; ++l) {\n            int side = (lines[l].dx * (ys[i] - lines[l].py) -\n                        lines[l].dy * (xs[i] - lines[l].px)) > 0 ? 1 : 0;\n            if (l < 64)\n                pat[0] |= (uint64_t(side) << l);\n            else\n                pat[1] |= (uint64_t(side) << (l - 64));\n        }\n        point_pat[i] = pat;\n        pat_cnt[pat]++;\n    }\n\n    int b[11] = {0};\n    for (auto& [pat, cnt] : pat_cnt) {\n        if (cnt >= 1 && cnt <= 10) b[cnt]++;\n    }\n\n    int current_score = 0;\n    for (int d = 1; d <= 10; ++d) current_score += min(a[d], b[d]);\n\n    // Simulated annealing parameters\n    double T = 50.0;\n    const double cooling = 0.9995;\n    const double large_prob = 0.01;\n    auto start_time = chrono::steady_clock::now();\n    const double time_limit = 2.8;  // seconds\n\n    for (int iter = 0; ; ++iter) {\n        // Time check every 1000 iterations\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 > time_limit) break;\n        }\n\n        int l = rng() % K;\n        bool large = (rng() % 100) < 1;\n\n        Line new_line;\n        bool valid = false;\n\n        if (!large) { // small perturbation\n            new_line = lines[l];\n            int which = rng() % 2;\n            if (which == 0) {\n                new_line.px += delta_dist(rng);\n                new_line.py += delta_dist(rng);\n            } else {\n                new_line.qx += delta_dist(rng);\n                new_line.qy += delta_dist(rng);\n            }\n            if (new_line.px == new_line.qx && new_line.py == new_line.qy) continue;\n            new_line.dx = new_line.qx - new_line.px;\n            new_line.dy = new_line.qy - new_line.py;\n            valid = true;\n            for (int i = 0; i < N; ++i) {\n                int64 cross = new_line.dx * (ys[i] - new_line.py) -\n                              new_line.dy * (xs[i] - new_line.px);\n                if (cross == 0) { valid = false; break; }\n            }\n        } else { // large change: completely new line\n            while (true) {\n                new_line.px = coord_dist(rng);\n                new_line.py = coord_dist(rng);\n                new_line.qx = coord_dist(rng);\n                new_line.qy = coord_dist(rng);\n                new_line.dx = new_line.qx - new_line.px;\n                new_line.dy = new_line.qy - new_line.py;\n                if (is_valid_line(new_line)) {\n                    valid = true;\n                    break;\n                }\n            }\n        }\n        if (!valid) continue;\n\n        // Apply changes incrementally\n        vector<pair<int, array<uint64_t,2>>> changed; // point index, old pattern\n\n        for (int i = 0; i < N; ++i) {\n            int64 cross = new_line.dx * (ys[i] - new_line.py) -\n                          new_line.dy * (xs[i] - new_line.px);\n            int new_side = cross > 0 ? 1 : 0;\n\n            // current side from pattern\n            uint64_t& low = point_pat[i][0];\n            uint64_t& high = point_pat[i][1];\n            int old_side;\n            if (l < 64) old_side = (low >> l) & 1;\n            else old_side = (high >> (l - 64)) & 1;\n\n            if (old_side == new_side) continue;\n\n            array<uint64_t,2> old_pat = {low, high};\n\n            // toggle the bit for line l\n            if (l < 64) low ^= (1ULL << l);\n            else high ^= (1ULL << (l - 64));\n            array<uint64_t,2> new_pat = {low, high};\n\n            // update map and b for old_pat -> new_pat\n            // decrement old_pat\n            auto it = pat_cnt.find(old_pat);\n            int c_old = it->second;\n            if (c_old >= 1 && c_old <= 10) b[c_old]--;\n            if (--c_old == 0) pat_cnt.erase(it);\n            else it->second = c_old;\n\n            // increment new_pat\n            auto it2 = pat_cnt.find(new_pat);\n            if (it2 != pat_cnt.end()) {\n                int c_new = it2->second;\n                if (c_new >= 1 && c_new <= 10) b[c_new]--;\n                it2->second = c_new + 1;\n                c_new++;\n                if (c_new >= 1 && c_new <= 10) b[c_new]++;\n            } else {\n                pat_cnt[new_pat] = 1;\n                if (1 <= 10) b[1]++;\n            }\n\n            changed.emplace_back(i, old_pat);\n        }\n\n        // Compute new score\n        int new_score = 0;\n        for (int d = 1; d <= 10; ++d) new_score += min(a[d], b[d]);\n\n        // Acceptance test\n        bool accept = false;\n        if (new_score >= current_score) {\n            accept = true;\n        } else {\n            double delta = new_score - current_score;\n            double prob = exp(delta / T);\n            uniform_real_distribution<double> real_dist(0.0, 1.0);\n            if (real_dist(rng) < prob) accept = true;\n        }\n\n        if (accept) {\n            lines[l] = new_line;\n            current_score = new_score;\n        } else {\n            // Revert all changes\n            for (auto& p : changed) {\n                int i = p.first;\n                array<uint64_t,2> old_pat = p.second;\n                array<uint64_t,2> new_pat = point_pat[i]; // current\n\n                // decrement new_pat\n                auto it = pat_cnt.find(new_pat);\n                int c_new = it->second;\n                if (c_new >= 1 && c_new <= 10) b[c_new]--;\n                if (--c_new == 0) pat_cnt.erase(it);\n                else it->second = c_new;\n\n                // increment old_pat\n                auto it2 = pat_cnt.find(old_pat);\n                if (it2 != pat_cnt.end()) {\n                    int c_old = it2->second;\n                    if (c_old >= 1 && c_old <= 10) b[c_old]--;\n                    it2->second = c_old + 1;\n                    c_old++;\n                    if (c_old >= 1 && c_old <= 10) b[c_old]++;\n                } else {\n                    pat_cnt[old_pat] = 1;\n                    if (1 <= 10) b[1]++;\n                }\n\n                point_pat[i] = old_pat;\n            }\n        }\n\n        T *= cooling;\n    }\n\n    // Output the final lines\n    cout << K << \"\\n\";\n    for (int i = 0; i < K; ++i) {\n        cout << lines[i].px << \" \" << lines[i].py << \" \"\n             << lines[i].qx << \" \" << lines[i].qy << \"\\n\";\n    }\n\n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <array>\n#include <random>\n#include <chrono>\n#include <algorithm>\n\nusing namespace std;\n\nstruct MoveCandidate {\n    array<int, 8> pts;\n    double score;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::steady_clock::now();\n    const double TIME_LIMIT = 4.5;  // seconds\n    \n    int N, M;\n    cin >> N >> M;\n\n    const int c = (N - 1) / 2;\n    vector<vector<int>> w(N, vector<int>(N));\n    long long totalS = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int dx = i - c, dy = j - c;\n            w[i][j] = dx * dx + dy * dy + 1;\n            totalS += w[i][j];\n        }\n    }\n\n    vector<pair<int, int>> init(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> init[i].first >> init[i].second;\n    }\n\n    vector<array<int, 8>> best_ops;\n    long long best_score = -1;\n    int trial = 0;\n    \n    while (true) {\n        auto current_time = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(current_time - start_time).count();\n        if (elapsed > TIME_LIMIT) break;\n        trial++;\n        \n        // Initialize state\n        vector<vector<char>> dot(N, vector<char>(N, 0));\n        for (auto& p : init) dot[p.first][p.second] = 1;\n\n        vector<vector<char>> h_edge(N, vector<char>(N, 0));\n        vector<vector<char>> v_edge(N, vector<char>(N, 0));\n        vector<vector<char>> d1_edge(N, vector<char>(N, 0));\n        vector<vector<char>> d2_edge(N, vector<char>(N, 0));\n\n        vector<array<int, 8>> ops;\n        mt19937 rng(chrono::steady_clock::now().time_since_epoch().count() + trial);\n        uniform_real_distribution<double> noise(0.0, 0.1);\n\n        while (true) {\n            vector<MoveCandidate> candidates;\n            double max_score = -1.0;\n\n            for (int x = 0; x < N; ++x) {\n                for (int y = 0; y < N; ++y) {\n                    if (dot[x][y]) continue;\n                    int pw = w[x][y];\n\n                    // Unit squares (4 orientations)\n                    // lower-left\n                    if (x + 1 < N && y + 1 < N) {\n                        if (dot[x+1][y] && dot[x][y+1] && dot[x+1][y+1]) {\n                            if (!h_edge[x][y] && !h_edge[x][y+1] && !v_edge[x][y] && !v_edge[x+1][y]) {\n                                array<int,8> pts = {x, y, x+1, y, x+1, y+1, x, y+1};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                    // lower-right\n                    if (x - 1 >= 0 && y + 1 < N) {\n                        if (dot[x-1][y] && dot[x-1][y+1] && dot[x][y+1]) {\n                            if (!h_edge[x-1][y] && !h_edge[x-1][y+1] && !v_edge[x-1][y] && !v_edge[x][y]) {\n                                array<int,8> pts = {x, y, x, y+1, x-1, y+1, x-1, y};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                    // upper-left\n                    if (x + 1 < N && y - 1 >= 0) {\n                        if (dot[x][y-1] && dot[x+1][y-1] && dot[x+1][y]) {\n                            if (!h_edge[x][y-1] && !h_edge[x][y] && !v_edge[x][y-1] && !v_edge[x+1][y-1]) {\n                                array<int,8> pts = {x, y, x+1, y, x+1, y-1, x, y-1};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                    // upper-right\n                    if (x - 1 >= 0 && y - 1 >= 0) {\n                        if (dot[x-1][y-1] && dot[x][y-1] && dot[x-1][y]) {\n                            if (!h_edge[x-1][y-1] && !h_edge[x-1][y] && !v_edge[x-1][y-1] && !v_edge[x][y-1]) {\n                                array<int,8> pts = {x, y, x-1, y, x-1, y-1, x, y-1};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n\n                    // Unit diamonds (4 orientations)\n                    // case A\n                    if (x <= N-3 && y >= 1 && y <= N-2) {\n                        int lx = x, ly = y;\n                        if (dot[lx+1][ly+1] && dot[lx+2][ly] && dot[lx+1][ly-1]) {\n                            if (!d1_edge[lx][ly] && !d2_edge[lx+1][ly+1] && !d1_edge[lx+1][ly-1] && !d2_edge[lx][ly]) {\n                                array<int,8> pts = {lx, ly, lx+1, ly+1, lx+2, ly, lx+1, ly-1};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                    // case B\n                    if (x >= 1 && x <= N-2 && y >= 2 && y <= N-1) {\n                        int lx = x-1, ly = y-1;\n                        if (dot[lx][ly] && dot[lx+2][ly] && dot[lx+1][ly-1]) {\n                            if (!d1_edge[lx][ly] && !d2_edge[lx+1][ly+1] && !d1_edge[lx+1][ly-1] && !d2_edge[lx][ly]) {\n                                array<int,8> pts = {lx+1, ly+1, lx+2, ly, lx+1, ly-1, lx, ly};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                    // case C\n                    if (x >= 2 && y >= 1 && y <= N-2) {\n                        int lx = x-2, ly = y;\n                        if (dot[lx][ly] && dot[lx+1][ly+1] && dot[lx+1][ly-1]) {\n                            if (!d1_edge[lx][ly] && !d2_edge[lx+1][ly+1] && !d1_edge[lx+1][ly-1] && !d2_edge[lx][ly]) {\n                                array<int,8> pts = {lx+2, ly, lx+1, ly-1, lx, ly, lx+1, ly+1};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                    // case D\n                    if (x >= 1 && x <= N-2 && y >= 0 && y <= N-3) {\n                        int lx = x-1, ly = y+1;\n                        if (dot[lx][ly] && dot[lx+1][ly+1] && dot[lx+2][ly]) {\n                            if (!d1_edge[lx][ly] && !d2_edge[lx+1][ly+1] && !d1_edge[lx+1][ly-1] && !d2_edge[lx][ly]) {\n                                array<int,8> pts = {lx+1, ly-1, lx, ly, lx+1, ly+1, lx+2, ly};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (candidates.empty()) break;\n\n            // Select candidate with highest score\n            vector<int> best_idx;\n            for (size_t i = 0; i < candidates.size(); ++i) {\n                if (candidates[i].score == max_score) {\n                    best_idx.push_back(i);\n                }\n            }\n            int chosen = best_idx[uniform_int_distribution<int>(0, best_idx.size()-1)(rng)];\n            MoveCandidate& mv = candidates[chosen];\n\n            // Apply move\n            int x1 = mv.pts[0], y1 = mv.pts[1];\n            dot[x1][y1] = 1;\n\n            // Determine shape and mark edges\n            int minx = mv.pts[0], maxx = mv.pts[0], miny = mv.pts[1], maxy = mv.pts[1];\n            for (int i = 0; i < 4; ++i) {\n                int px = mv.pts[2*i], py = mv.pts[2*i+1];\n                if (px < minx) minx = px;\n                if (px > maxx) maxx = px;\n                if (py < miny) miny = py;\n                if (py > maxy) maxy = py;\n            }\n            \n            if (maxx - minx == 1 && maxy - miny == 1) {  // unit square\n                h_edge[minx][miny] = 1;\n                h_edge[minx][maxy] = 1;\n                v_edge[minx][miny] = 1;\n                v_edge[maxx][miny] = 1;\n            } else {  // unit diamond\n                int lx = minx, ly = -1;\n                for (int i = 0; i < 4; ++i) {\n                    if (mv.pts[2*i] == lx) {\n                        ly = mv.pts[2*i+1];\n                        break;\n                    }\n                }\n                d1_edge[lx][ly] = 1;\n                d2_edge[lx+1][ly+1] = 1;\n                d1_edge[lx+1][ly-1] = 1;\n                d2_edge[lx][ly] = 1;\n            }\n\n            ops.push_back(mv.pts);\n        }\n\n        // Calculate score for this trial\n        long long sum_w = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (dot[i][j]) sum_w += w[i][j];\n            }\n        }\n        double factor = (double)(N * N) / M;\n        double ratio = (double)sum_w / totalS;\n        long long score = llround(1e6 * factor * ratio);\n\n        if (score > best_score) {\n            best_score = score;\n            best_ops = ops;\n        }\n    }\n\n    // Output\n    cout << best_ops.size() << \"\\n\";\n    for (auto& op : best_ops) {\n        for (int i = 0; i < 8; ++i) {\n            if (i) cout << \" \";\n            cout << op[i];\n        }\n        cout << \"\\n\";\n    }\n\n    return 0;\n}","ahc015":"#include <iostream>\n#include <vector>\n#include <array>\n#include <queue>\n#include <utility>\n#include <algorithm>\n#include <cmath>\n#include <iomanip>\n#include <unordered_map>\n#include <string>\n#include <random>\n\nusing namespace std;\n\n// global flavors (1-indexed)\nvector<int> flavors(101);\n\n// 10x10 grid: 0 = empty, 1..3 = flavor\nusing Grid = array<array<int, 10>, 10>;\n\n// random generator with fixed seed\nmt19937 rng(12345);\n\n// ------------------------------------------------------------\n// tilt simulation\nGrid tilt(const Grid& g, char dir) {\n    Grid ng = {}; // zero-initialized\n    if (dir == 'F') {\n        for (int c = 0; c < 10; ++c) {\n            int idx = 0;\n            for (int r = 0; r < 10; ++r) {\n                if (g[r][c] != 0) {\n                    ng[idx++][c] = g[r][c];\n                }\n            }\n        }\n    } else if (dir == 'B') {\n        for (int c = 0; c < 10; ++c) {\n            int idx = 9;\n            for (int r = 9; r >= 0; --r) {\n                if (g[r][c] != 0) {\n                    ng[idx--][c] = g[r][c];\n                }\n            }\n        }\n    } else if (dir == 'L') {\n        for (int r = 0; r < 10; ++r) {\n            int idx = 0;\n            for (int c = 0; c < 10; ++c) {\n                if (g[r][c] != 0) {\n                    ng[r][idx++] = g[r][c];\n                }\n            }\n        }\n    } else if (dir == 'R') {\n        for (int r = 0; r < 10; ++r) {\n            int idx = 9;\n            for (int c = 9; c >= 0; --c) {\n                if (g[r][c] != 0) {\n                    ng[r][idx--] = g[r][c];\n                }\n            }\n        }\n    }\n    return ng;\n}\n\n// ------------------------------------------------------------\n// compute sum of squares of connected components\nint compute_sum_squares(const Grid& g) {\n    bool visited[10][10] = {};\n    int sum = 0;\n    for (int r = 0; r < 10; ++r) {\n        for (int c = 0; c < 10; ++c) {\n            if (g[r][c] != 0 && !visited[r][c]) {\n                int flavor = g[r][c];\n                int size = 0;\n                queue<pair<int, int>> q;\n                q.push({r, c});\n                visited[r][c] = true;\n                while (!q.empty()) {\n                    auto [x, y] = q.front(); q.pop();\n                    ++size;\n                    // four neighbors\n                    if (x > 0 && !visited[x-1][y] && g[x-1][y] == flavor) {\n                        visited[x-1][y] = true;\n                        q.push({x-1, y});\n                    }\n                    if (x < 9 && !visited[x+1][y] && g[x+1][y] == flavor) {\n                        visited[x+1][y] = true;\n                        q.push({x+1, y});\n                    }\n                    if (y > 0 && !visited[x][y-1] && g[x][y-1] == flavor) {\n                        visited[x][y-1] = true;\n                        q.push({x, y-1});\n                    }\n                    if (y < 9 && !visited[x][y+1] && g[x][y+1] == flavor) {\n                        visited[x][y+1] = true;\n                        q.push({x, y+1});\n                    }\n                }\n                sum += size * size;\n            }\n        }\n    }\n    return sum;\n}\n\n// ------------------------------------------------------------\n// compute total spread (sum of squared distances to centroid)\ndouble compute_spread(const Grid& g) {\n    vector<int> cnt(4, 0);\n    vector<double> sum_r(4, 0.0), sum_c(4, 0.0);\n    vector<double> sum_r2(4, 0.0), sum_c2(4, 0.0);\n    for (int r = 0; r < 10; ++r) {\n        for (int c = 0; c < 10; ++c) {\n            int f = g[r][c];\n            if (f != 0) {\n                cnt[f]++;\n                sum_r[f] += r;\n                sum_c[f] += c;\n                sum_r2[f] += r * r;\n                sum_c2[f] += c * c;\n            }\n        }\n    }\n    double total = 0.0;\n    for (int f = 1; f <= 3; ++f) {\n        if (cnt[f] > 0) {\n            double mean_r = sum_r[f] / cnt[f];\n            double mean_c = sum_c[f] / cnt[f];\n            total += (sum_r2[f] + sum_c2[f]) -\n                     (sum_r[f] * sum_r[f] + sum_c[f] * sum_c[f]) / cnt[f];\n        }\n    }\n    return total;\n}\n\n// ------------------------------------------------------------\n// helper to convert grid to string for memoization\nstring grid_to_string(const Grid& g) {\n    string s;\n    s.reserve(100);\n    for (int r = 0; r < 10; ++r) {\n        for (int c = 0; c < 10; ++c) {\n            s.push_back('0' + g[r][c]);\n        }\n    }\n    return s;\n}\n\n// ------------------------------------------------------------\n// recursive expectimax for remaining \u2264 4 candies, with memoization\ndouble expected_score(const Grid& grid, int next_idx,\n                      unordered_map<string, double>& memo) {\n    if (next_idx > 100) {\n        return compute_sum_squares(grid);\n    }\n\n    string key = grid_to_string(grid) + \":\" + to_string(next_idx);\n    auto it = memo.find(key);\n    if (it != memo.end()) {\n        return it->second;\n    }\n\n    // collect empty cells\n    vector<pair<int, int>> empties;\n    for (int r = 0; r < 10; ++r)\n        for (int c = 0; c < 10; ++c)\n            if (grid[r][c] == 0)\n                empties.emplace_back(r, c);\n\n    int E = empties.size();\n    double total = 0.0;\n\n    for (auto [r, c] : empties) {\n        // place the next candy\n        Grid g2 = grid;\n        g2[r][c] = flavors[next_idx];\n\n        // choose the best direction for this placement\n        double best = -1.0;\n        for (char dir : {'F', 'B', 'L', 'R'}) {\n            Grid g3 = tilt(g2, dir);\n            double val = expected_score(g3, next_idx + 1, memo);\n            if (val > best) best = val;\n        }\n        total += best;\n    }\n\n    double result = total / E;\n    memo[key] = result;\n    return result;\n}\n\n// ------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // read all flavors\n    for (int i = 1; i <= 100; ++i) {\n        cin >> flavors[i];\n    }\n\n    Grid grid = {};  // initially empty\n    const int SAMPLES = 5; // for Monte Carlo lookahead\n\n    for (int t = 1; t <= 100; ++t) {\n        int p;\n        cin >> p;\n\n        // place the t\u2011th candy in the p\u2011th empty cell (row\u2011major order)\n        int cnt = 0;\n        int r_place = -1, c_place = -1;\n        for (int r = 0; r < 10; ++r) {\n            for (int c = 0; c < 10; ++c) {\n                if (grid[r][c] == 0) {\n                    ++cnt;\n                    if (cnt == p) {\n                        r_place = r;\n                        c_place = c;\n                        break;\n                    }\n                }\n            }\n            if (cnt == p) break;\n        }\n        grid[r_place][c_place] = flavors[t];\n\n        // last tilt does nothing \u2013 output any direction and finish\n        if (t == 100) {\n            cout << 'F' << endl;\n            return 0;\n        }\n\n        int remaining = 100 - t;  // candies still to be placed after this step\n        char best_dir;\n        Grid best_grid;\n\n        if (remaining <= 4) {\n            // deep evaluation using expectimax with memoization\n            double best_val = -1.0;\n            for (char dir : {'F', 'B', 'L', 'R'}) {\n                Grid after_tilt = tilt(grid, dir);\n                unordered_map<string, double> memo;\n                double val = expected_score(after_tilt, t + 1, memo);\n                if (val > best_val) {\n                    best_val = val;\n                    best_dir = dir;\n                    best_grid = after_tilt;\n                }\n            }\n        } else {\n            // Monte Carlo lookahead with SAMPLES random placements per direction\n            double best_expected = -1.0;\n            for (char dir : {'F', 'B', 'L', 'R'}) {\n                Grid after_tilt = tilt(grid, dir);\n\n                // collect empty cells\n                vector<pair<int, int>> empties;\n                for (int r = 0; r < 10; ++r)\n                    for (int c = 0; c < 10; ++c)\n                        if (after_tilt[r][c] == 0)\n                            empties.emplace_back(r, c);\n\n                if (empties.empty()) {\n                    continue; // should not happen when remaining > 0\n                }\n\n                double total = 0.0;\n                for (int s = 0; s < SAMPLES; ++s) {\n                    // choose a random empty cell\n                    uniform_int_distribution<int> dist(0, empties.size() - 1);\n                    int idx = dist(rng);\n                    auto [r, c] = empties[idx];\n\n                    Grid g2 = after_tilt;\n                    g2[r][c] = flavors[t + 1]; // next candy\n\n                    // evaluate the best next tilt\n                    int best_val = -1;\n                    for (char dir2 : {'F', 'B', 'L', 'R'}) {\n                        Grid g3 = tilt(g2, dir2);\n                        int val = compute_sum_squares(g3);\n                        if (val > best_val) best_val = val;\n                    }\n                    total += best_val;\n                }\n\n                double expected = total / SAMPLES;\n                if (expected > best_expected) {\n                    best_expected = expected;\n                    best_dir = dir;\n                    best_grid = after_tilt;\n                }\n            }\n\n            // Fallback: if no direction was chosen (shouldn't happen), use greedy\n            if (best_expected < 0) {\n                int best_sum_sq = -1;\n                double best_spread = 1e9;\n                for (char dir : {'F', 'B', 'L', 'R'}) {\n                    Grid after_tilt = tilt(grid, dir);\n                    int sum_sq = compute_sum_squares(after_tilt);\n                    double spread = compute_spread(after_tilt);\n                    if (sum_sq > best_sum_sq ||\n                        (sum_sq == best_sum_sq && spread < best_spread)) {\n                        best_sum_sq = sum_sq;\n                        best_spread = spread;\n                        best_dir = dir;\n                        best_grid = after_tilt;\n                    }\n                }\n            }\n        }\n\n        cout << best_dir << endl;\n        grid = best_grid;\n    }\n\n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <string>\n#include <cmath>\n#include <cassert>\n\nusing namespace std;\n\nint main() {\n    // Problem parameters\n    int M;\n    double epsilon;\n    cin >> M >> epsilon;\n\n    // Fixed design choices\n    const int N = 30;                     // number of vertices\n    const int T = N * (N - 1) / 2;        // number of possible edges\n    const int TRIALS = 100;               // number of noise trials for precomputation\n\n    // ------------------------------------------------------------\n    // 1. Precompute all vertex pairs in lexicographic order\n    // ------------------------------------------------------------\n    vector<pair<int, int>> pairs;\n    pairs.reserve(T);\n    for (int i = 0; i < N; ++i)\n        for (int j = i + 1; j < N; ++j)\n            pairs.emplace_back(i, j);\n    assert(pairs.size() == T);\n\n    // ------------------------------------------------------------\n    // 2. Generate the M graphs G_0 ... G_{M-1}\n    // ------------------------------------------------------------\n    // Random generator for graph construction (deterministic seed)\n    mt19937 rng_graph(12345);\n    uniform_real_distribution<double> dist_graph(0.0, 1.0);\n\n    // Storage: adjacency matrices and the output strings\n    vector<vector<vector<bool>>> adj(M, vector<vector<bool>>(N, vector<bool>(N, false)));\n    vector<string> graph_strings(M);\n\n    for (int idx = 0; idx < M; ++idx) {\n        double p = (M > 1) ? double(idx) / (M - 1) : 0.0;   // edge probability for this graph\n        string s(T, '0');\n        for (int e = 0; e < T; ++e) {\n            auto [u, v] = pairs[e];\n            if (dist_graph(rng_graph) < p) {\n                adj[idx][u][v] = true;\n                s[e] = '1';\n            }\n        }\n        graph_strings[idx] = s;\n    }\n\n    // ------------------------------------------------------------\n    // 3. Output the chosen N and the M graphs\n    // ------------------------------------------------------------\n    cout << N << endl;\n    for (int i = 0; i < M; ++i)\n        cout << graph_strings[i] << endl;\n    cout.flush();\n\n    // ------------------------------------------------------------\n    // 4. Precompute mean and variance of sorted degree sequences\n    //    under the noise model (edge flips with probability epsilon)\n    // ------------------------------------------------------------\n    // Random generator for noise simulation (different seed)\n    mt19937 rng_noise(54321);\n    uniform_real_distribution<double> dist_noise(0.0, 1.0);\n\n    // Means and variances for each graph and each sorted position\n    vector<vector<double>> mean_deg(M, vector<double>(N, 0.0));\n    vector<vector<double>> var_deg(M, vector<double>(N, 0.0));\n\n    for (int g = 0; g < M; ++g) {\n        vector<double> sum(N, 0.0), sum_sq(N, 0.0);\n        for (int trial = 0; trial < TRIALS; ++trial) {\n            vector<int> deg(N, 0);\n            for (int e = 0; e < T; ++e) {\n                auto [u, v] = pairs[e];\n                bool present = adj[g][u][v];\n                // flip with probability epsilon\n                if (dist_noise(rng_noise) < epsilon)\n                    present = !present;\n                if (present) {\n                    deg[u]++;\n                    deg[v]++;\n                }\n            }\n            sort(deg.begin(), deg.end());\n            for (int j = 0; j < N; ++j) {\n                sum[j] += deg[j];\n                sum_sq[j] += deg[j] * deg[j];\n            }\n        }\n        for (int j = 0; j < N; ++j) {\n            mean_deg[g][j] = sum[j] / TRIALS;\n            double variance = sum_sq[j] / TRIALS - mean_deg[g][j] * mean_deg[g][j];\n            // avoid zero variance (can happen for empty/complete graphs with very low noise)\n            if (variance < 1e-9) variance = 1e-9;\n            var_deg[g][j] = variance;\n        }\n    }\n\n    // ------------------------------------------------------------\n    // 5. Process the 100 queries\n    // ------------------------------------------------------------\n    for (int q = 0; q < 100; ++q) {\n        string H_str;\n        cin >> H_str;\n        assert(H_str.size() == T);\n\n        // Compute degree sequence of H\n        vector<int> deg_H(N, 0);\n        for (int e = 0; e < T; ++e) {\n            if (H_str[e] == '1') {\n                auto [u, v] = pairs[e];\n                deg_H[u]++;\n                deg_H[v]++;\n            }\n        }\n        sort(deg_H.begin(), deg_H.end());\n\n        // Find the graph with smallest chi\u2011squared distance\n        int best_graph = 0;\n        double best_dist = 1e100;\n        for (int g = 0; g < M; ++g) {\n            double dist = 0.0;\n            for (int j = 0; j < N; ++j) {\n                double diff = deg_H[j] - mean_deg[g][j];\n                dist += (diff * diff) / var_deg[g][j];\n            }\n            if (dist < best_dist) {\n                best_dist = dist;\n                best_graph = g;\n            }\n        }\n\n        cout << best_graph << endl;\n        cout.flush();\n    }\n\n    return 0;\n}","ahc017":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cassert>\n#include <limits>\n\nusing namespace std;\n\nstruct Point {\n    double x, y;\n    double dist(const Point& other) const {\n        double dx = x - other.x;\n        double dy = y - other.y;\n        return sqrt(dx*dx + dy*dy);\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n\n    vector<pair<int, int>> edges(M);\n    vector<long long> weights(M);\n    for (int i = 0; i < M; ++i) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        --u; --v;\n        edges[i] = {u, v};\n        weights[i] = w;\n    }\n\n    // Read coordinates\n    vector<Point> pts(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> pts[i].x >> pts[i].y;\n    }\n\n    // Compute edge midpoints\n    vector<Point> mid(M);\n    for (int i = 0; i < M; ++i) {\n        auto [u, v] = edges[i];\n        mid[i].x = (pts[u].x + pts[v].x) * 0.5;\n        mid[i].y = (pts[u].y + pts[v].y) * 0.5;\n    }\n\n    // Greedy assignment: farthest-first to maximize spatial dispersion per day\n    vector<int> day_of(M, -1);\n    vector<int> cnt(D, 0);\n    vector<vector<Point>> day_points(D);  // store midpoints of edges assigned to each day\n\n    // Process edges in random order for diversity\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    shuffle(order.begin(), order.end(), rng);\n\n    const double INF_DIST = 1e9;\n\n    for (int idx : order) {\n        int best_day = -1;\n        double best_min_dist = -1.0;\n        for (int d = 0; d < D; ++d) {\n            if (cnt[d] >= K) continue;\n            double min_dist = INF_DIST;\n            if (day_points[d].empty()) {\n                min_dist = INF_DIST;  // large value to prioritize empty days\n            } else {\n                // Compute minimum distance from current edge's midpoint to any edge already in day d\n                for (const Point& p : day_points[d]) {\n                    double dist = mid[idx].dist(p);\n                    if (dist < min_dist) min_dist = dist;\n                }\n            }\n            if (min_dist > best_min_dist) {\n                best_min_dist = min_dist;\n                best_day = d;\n            }\n        }\n        assert(best_day != -1);\n        day_of[idx] = best_day;\n        cnt[best_day]++;\n        day_points[best_day].push_back(mid[idx]);\n    }\n\n    // Output assignments (1-indexed days)\n    for (int i = 0; i < M; ++i) {\n        cout << day_of[i] + 1 << (i == M-1 ? \"\\n\" : \" \");\n    }\n\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAXD = 14;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    int D;\n    cin >> D;\n    vector<string> f1(D), r1(D), f2(D), r2(D);\n    for (int i = 0; i < D; ++i) cin >> f1[i];\n    for (int i = 0; i < D; ++i) cin >> r1[i];\n    for (int i = 0; i < D; ++i) cin >> f2[i];\n    for (int i = 0; i < D; ++i) cin >> r2[i];\n    \n    // Convert to boolean arrays for quick access\n    bool f1b[D][D] = {}, r1b[D][D] = {};\n    bool f2b[D][D] = {}, r2b[D][D] = {};\n    for (int z = 0; z < D; ++z) {\n        for (int x = 0; x < D; ++x) {\n            f1b[z][x] = (f1[z][x] == '1');\n            f2b[z][x] = (f2[z][x] == '1');\n        }\n        for (int y = 0; y < D; ++y) {\n            r1b[z][y] = (r1[z][y] == '1');\n            r2b[z][y] = (r2[z][y] == '1');\n        }\n    }\n    \n    // Allowed regions for each object\n    bool allowed1[D][D][D] = {};\n    bool allowed2[D][D][D] = {};\n    // Intersection I\n    bool I[D][D][D] = {};\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                allowed1[x][y][z] = f1b[z][x] && r1b[z][y];\n                allowed2[x][y][z] = f2b[z][x] && r2b[z][y];\n                I[x][y][z] = allowed1[x][y][z] && allowed2[x][y][z];\n            }\n        }\n    }\n    \n    // Connected components of I\n    int compI[D][D][D];\n    memset(compI, -1, sizeof(compI));\n    int num_components_I = 0;\n    const int dx[6] = {1,-1,0,0,0,0};\n    const int dy[6] = {0,0,1,-1,0,0};\n    const int dz[6] = {0,0,0,0,1,-1};\n    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 (I[x][y][z] && compI[x][y][z] == -1) {\n                    queue<tuple<int,int,int>> q;\n                    q.push({x, y, z});\n                    compI[x][y][z] = num_components_I;\n                    while (!q.empty()) {\n                        auto [cx, cy, cz] = q.front(); q.pop();\n                        for (int d = 0; d < 6; ++d) {\n                            int nx = cx + dx[d];\n                            int ny = cy + dy[d];\n                            int nz = cz + dz[d];\n                            if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D &&\n                                I[nx][ny][nz] && compI[nx][ny][nz] == -1) {\n                                compI[nx][ny][nz] = num_components_I;\n                                q.push({nx, ny, nz});\n                            }\n                        }\n                    }\n                    ++num_components_I;\n                }\n            }\n        }\n    }\n    \n    // Initialize objects with all cells from I (shared)\n    bool obj1[D][D][D] = {};\n    bool obj2[D][D][D] = {};\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 (I[x][y][z]) {\n                    obj1[x][y][z] = true;\n                    obj2[x][y][z] = true;\n                }\n    \n    // For each object, add minimal extra cells to satisfy silhouettes\n    for (int obj_id = 0; obj_id < 2; ++obj_id) {\n        bool (*obj)[D][D] = (obj_id == 0) ? obj1 : obj2;\n        bool (*fb)[D] = (obj_id == 0) ? f1b : f2b;\n        bool (*rb)[D] = (obj_id == 0) ? r1b : r2b;\n        for (int z = 0; z < D; ++z) {\n            // Lists of required x and y\n            vector<int> X, Y;\n            for (int x = 0; x < D; ++x) if (fb[z][x]) X.push_back(x);\n            for (int y = 0; y < D; ++y) if (rb[z][y]) Y.push_back(y);\n            \n            // Determine which x and y are already covered by I\n            vector<bool> x_covered(D, false), y_covered(D, false);\n            for (int x : X) {\n                for (int y = 0; y < D; ++y) {\n                    if (I[x][y][z]) {\n                        x_covered[x] = true;\n                        break;\n                    }\n                }\n            }\n            for (int y : Y) {\n                for (int x = 0; x < D; ++x) {\n                    if (I[x][y][z]) {\n                        y_covered[y] = true;\n                        break;\n                    }\n                }\n            }\n            \n            vector<int> X_rem, Y_rem;\n            for (int x : X) if (!x_covered[x]) X_rem.push_back(x);\n            for (int y : Y) if (!y_covered[y]) Y_rem.push_back(y);\n            \n            int a = X_rem.size(), b = Y_rem.size();\n            int M = max(a, b);\n            // Add cells to cover remaining requirements\n            if (a >= b) {\n                for (int i = 0; i < b; ++i) {\n                    int x = X_rem[i], y = Y_rem[i];\n                    obj[x][y][z] = true;\n                }\n                for (int i = b; i < a; ++i) {\n                    int x = X_rem[i];\n                    int y = Y.empty() ? 0 : Y[0]; // Y non\u2011empty because silhouette guarantees at least one y\n                    obj[x][y][z] = true;\n                }\n            } else {\n                for (int i = 0; i < a; ++i) {\n                    int x = X_rem[i], y = Y_rem[i];\n                    obj[x][y][z] = true;\n                }\n                for (int i = a; i < b; ++i) {\n                    int y = Y_rem[i];\n                    int x = X.empty() ? 0 : X[0];\n                    obj[x][y][z] = true;\n                }\n            }\n        }\n    }\n    \n    // Shared blocks are exactly the connected components of I\n    // Assign IDs to shared components\n    vector<int> comp_id(num_components_I);\n    int cur_id = 1;\n    for (int i = 0; i < num_components_I; ++i) comp_id[i] = cur_id++;\n    \n    // Prepare output arrays\n    vector<vector<vector<int>>> b1(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    vector<vector<vector<int>>> b2(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    \n    // Fill shared blocks in both objects\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 (I[x][y][z]) {\n                    int id = comp_id[compI[x][y][z]];\n                    b1[x][y][z] = id;\n                    b2[x][y][z] = id;\n                }\n    \n    // Unit blocks for non\u2011shared cells in obj1\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 (obj1[x][y][z] && !I[x][y][z])\n                    b1[x][y][z] = cur_id++;\n    \n    // Unit blocks for non\u2011shared cells in obj2\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 (obj2[x][y][z] && !I[x][y][z])\n                    b2[x][y][z] = cur_id++;\n    \n    // Output\n    int total_blocks = cur_id - 1;\n    cout << total_blocks << \"\\n\";\n    // b1\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                cout << b1[x][y][z];\n                if (x == D-1 && y == D-1 && z == D-1) cout << \"\\n\";\n                else cout << \" \";\n            }\n    // b2\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                cout << b2[x][y][z];\n                if (x == D-1 && y == D-1 && z == D-1) cout << \"\\n\";\n                else cout << \" \";\n            }\n    \n    return 0;\n}","ahc020":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <climits>\n#include <numeric>\n\nusing namespace std;\ntypedef long long ll;\n\nstruct Candidate {\n    int type;      // 0: active vertex, 1: inactive vertex\n    int idx;       // vertex index\n    int new_P;     // new output strength\n    ll cost;       // total cost of the action\n    int count;     // number of newly covered residents\n    int first_idx; // first index in sorted_res[idx] to cover\n    int last_idx;  // last index (exclusive) in sorted_res[idx] to cover\n};\n\n// integer ceil(sqrt(x))\nint ceil_sqrt(ll x) {\n    int r = sqrt(x);\n    while ((ll)r * r < x) ++r;\n    return r;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\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\n    vector<int> u(M), v(M), w(M);\n    vector<vector<pair<int, int>>> adj(N); // (neighbor, edge index)\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]].emplace_back(v[j], j);\n        adj[v[j]].emplace_back(u[j], j);\n    }\n\n    vector<int> a(K), b(K);\n    for (int k = 0; k < K; ++k) cin >> a[k] >> b[k];\n\n    // squared distances from vertices to residents\n    vector<vector<ll>> dist2(N, vector<ll>(K));\n    for (int i = 0; i < N; ++i) {\n        for (int k = 0; k < K; ++k) {\n            ll dx = x[i] - a[k];\n            ll dy = y[i] - b[k];\n            dist2[i][k] = dx * dx + dy * dy;\n        }\n    }\n\n    // for each vertex, residents sorted by distance\n    vector<vector<int>> sorted_res(N);\n    for (int i = 0; i < N; ++i) {\n        sorted_res[i].resize(K);\n        iota(sorted_res[i].begin(), sorted_res[i].end(), 0);\n        sort(sorted_res[i].begin(), sorted_res[i].end(),\n             [&](int k1, int k2) { return dist2[i][k1] < dist2[i][k2]; });\n    }\n\n    // state\n    vector<bool> covered(K, false);\n    int covered_cnt = 0;\n    vector<int> P(N, 0);\n    vector<int> next_uncovered(N, 0); // for active vertices\n    vector<bool> is_vertex_active(N, false);\n    is_vertex_active[0] = true; // station 1 (index 0)\n    vector<bool> is_edge_on(M, false);\n\n    // main loop\n    while (covered_cnt < K) {\n        // Dijkstra to compute additional connection costs\n        vector<ll> dist_conn(N, LLONG_MAX);\n        vector<int> prev_vertex(N, -1), prev_edge(N, -1);\n        priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<>> pq;\n        for (int i = 0; i < N; ++i) {\n            if (is_vertex_active[i]) {\n                dist_conn[i] = 0;\n                pq.emplace(0, i);\n            }\n        }\n        while (!pq.empty()) {\n            auto [d, u_idx] = pq.top(); pq.pop();\n            if (d != dist_conn[u_idx]) continue;\n            for (auto [v_idx, e_idx] : adj[u_idx]) {\n                ll cost = is_edge_on[e_idx] ? 0 : w[e_idx];\n                if (dist_conn[u_idx] + cost < dist_conn[v_idx]) {\n                    dist_conn[v_idx] = dist_conn[u_idx] + cost;\n                    prev_vertex[v_idx] = u_idx;\n                    prev_edge[v_idx] = e_idx;\n                    pq.emplace(dist_conn[v_idx], v_idx);\n                }\n            }\n        }\n\n        // evaluate all possible actions\n        Candidate best;\n        bool found = false;\n\n        // actions on active vertices\n        for (int i = 0; i < N; ++i) {\n            if (!is_vertex_active[i]) continue;\n            // move to first uncovered resident\n            while (next_uncovered[i] < K && covered[sorted_res[i][next_uncovered[i]]])\n                ++next_uncovered[i];\n            if (next_uncovered[i] == K) continue;\n\n            int first = next_uncovered[i];\n            int k = sorted_res[i][first];\n            ll d2 = dist2[i][k];\n            int new_P = ceil_sqrt(d2);\n            if (new_P > 5000) continue;\n            ll new_P2 = (ll)new_P * new_P;\n            ll old_P2 = (ll)P[i] * P[i];\n\n            // count newly covered residents\n            int cnt = 0;\n            int last = first;\n            for (int j = first; j < K; ++j) {\n                int res = sorted_res[i][j];\n                if (dist2[i][res] > new_P2) break;\n                if (!covered[res]) ++cnt;\n                last = j + 1;\n            }\n            if (cnt == 0) continue;\n\n            ll cost_inc = new_P2 - old_P2;\n            if (!found || (ll)cost_inc * best.count < (ll)best.cost * cnt) {\n                best = {0, i, new_P, cost_inc, cnt, first, last};\n                found = true;\n            }\n        }\n\n        // actions on inactive vertices\n        for (int i = 0; i < N; ++i) {\n            if (is_vertex_active[i]) continue;\n            if (dist_conn[i] == LLONG_MAX) continue; // should not happen\n\n            // first uncovered resident\n            int first = 0;\n            while (first < K && covered[sorted_res[i][first]]) ++first;\n            if (first == K) continue;\n\n            int k = sorted_res[i][first];\n            ll d2 = dist2[i][k];\n            int new_P = ceil_sqrt(d2);\n            if (new_P > 5000) continue;\n            ll new_P2 = (ll)new_P * new_P;\n\n            int cnt = 0;\n            int last = first;\n            for (int j = first; j < K; ++j) {\n                int res = sorted_res[i][j];\n                if (dist2[i][res] > new_P2) break;\n                if (!covered[res]) ++cnt;\n                last = j + 1;\n            }\n            if (cnt == 0) continue;\n\n            ll total_cost = dist_conn[i] + new_P2;\n            if (!found || (ll)total_cost * best.count < (ll)best.cost * cnt) {\n                best = {1, i, new_P, total_cost, cnt, first, last};\n                found = true;\n            }\n        }\n\n        if (!found) break; // should not happen\n\n        // apply the best action\n        if (best.type == 0) { // active vertex\n            int i = best.idx;\n            P[i] = best.new_P;\n            for (int j = best.first_idx; j < best.last_idx; ++j) {\n                int res = sorted_res[i][j];\n                if (!covered[res]) {\n                    covered[res] = true;\n                    ++covered_cnt;\n                }\n            }\n            next_uncovered[i] = best.last_idx;\n        } else { // inactive vertex\n            int j = best.idx;\n            // turn on edges along the shortest path\n            int cur = j;\n            while (!is_vertex_active[cur]) {\n                int e = prev_edge[cur];\n                if (!is_edge_on[e]) is_edge_on[e] = true;\n                int prev = prev_vertex[cur];\n                is_vertex_active[cur] = true;\n                next_uncovered[cur] = 0; // newly activated, P=0 initially\n                P[cur] = 0;\n                cur = prev;\n            }\n            P[j] = best.new_P;\n            for (int idx = best.first_idx; idx < best.last_idx; ++idx) {\n                int res = sorted_res[j][idx];\n                if (!covered[res]) {\n                    covered[res] = true;\n                    ++covered_cnt;\n                }\n            }\n            next_uncovered[j] = best.last_idx;\n        }\n    }\n\n    // output\n    for (int i = 0; i < N; ++i) {\n        cout << P[i] << (i + 1 == N ? \"\\n\" : \" \");\n    }\n    for (int j = 0; j < M; ++j) {\n        cout << (is_edge_on[j] ? 1 : 0) << (j + 1 == M ? \"\\n\" : \" \");\n    }\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30; // fixed pyramid size\n\nint main() {\n    // read input\n    vector<vector<int>> a(N);\n    for (int x = 0; x < N; ++x) {\n        a[x].resize(x + 1);\n        for (int y = 0; y <= x; ++y) {\n            cin >> a[x][y];\n        }\n    }\n\n    vector<array<int, 4>> ops; // stores swaps (x1,y1,x2,y2)\n\n    // swap two adjacent balls and record the operation\n    auto do_swap = [&](int x1, int y1, int x2, int y2) {\n        swap(a[x1][y1], a[x2][y2]);\n        ops.push_back({x1, y1, x2, y2});\n    };\n\n    // sift down a value starting from (x,y) until heap property holds\n    auto sift = [&](int x, int y) {\n        while (x < N - 1) { // while not a leaf\n            int x_left = x + 1, y_left = y;      // left child\n            int x_right = x + 1, y_right = y + 1; // right child\n            // choose the child with the smaller value\n            int nx, ny;\n            if (a[x_left][y_left] <= a[x_right][y_right]) {\n                nx = x_left; ny = y_left;\n            } else {\n                nx = x_right; ny = y_right;\n            }\n            if (a[x][y] > a[nx][ny]) {\n                do_swap(x, y, nx, ny);\n                x = nx; y = ny; // continue sifting with the moved value\n            } else {\n                break;\n            }\n        }\n    };\n\n    // process rows from bottom to top\n    for (int x = N - 2; x >= 0; --x) {\n        // collect nodes in this row and sort by value descending\n        vector<pair<int, int>> nodes;\n        for (int y = 0; y <= x; ++y) {\n            nodes.emplace_back(a[x][y], y);\n        }\n        sort(nodes.begin(), nodes.end(), greater<pair<int, int>>());\n        // sift each node in that order\n        for (auto& p : nodes) {\n            sift(x, p.second);\n        }\n    }\n\n    // output\n    cout << ops.size() << '\\n';\n    for (auto& sw : ops) {\n        cout << sw[0] << ' ' << sw[1] << ' ' << sw[2] << ' ' << sw[3] << '\\n';\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int D = 9;  // Grid size is fixed at 9\nint entrance_r = 0, entrance_c = (D - 1) / 2;  // (0,4)\n\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\n\nbool obstacle[D][D] = {false};\nbool occupied[D][D] = {false};\nint container_num[D][D];       // -1 if no container\n\nint dist[D][D];                // BFS distance from entrance\nint cell_rank[D][D];           // index in the sorted order (0..M-1)\nvector<pair<int, int>> order;  // free squares sorted by (dist, row, col)\nint M;                         // number of containers\n\n// ---------- preprocessing ----------\nvoid compute_bfs_distances() {\n    for (int i = 0; i < D; ++i)\n        for (int j = 0; j < D; ++j)\n            dist[i][j] = -1;\n\n    queue<pair<int, int>> q;\n    dist[entrance_r][entrance_c] = 0;\n    q.push({entrance_r, entrance_c});\n\n    while (!q.empty()) {\n        auto [r, c] = q.front(); q.pop();\n        for (int d = 0; d < 4; ++d) {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n            if (obstacle[nr][nc]) continue;\n            if (dist[nr][nc] == -1) {\n                dist[nr][nc] = dist[r][c] + 1;\n                q.push({nr, nc});\n            }\n        }\n    }\n}\n\nvoid build_order() {\n    order.clear();\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            if (i == entrance_r && j == entrance_c) continue;\n            if (obstacle[i][j]) continue;\n            order.push_back({i, j});\n        }\n    }\n    sort(order.begin(), order.end(),\n         [](const auto& a, const auto& b) {\n             int da = dist[a.first][a.second];\n             int db = dist[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    M = order.size();\n    for (int i = 0; i < D; ++i)\n        for (int j = 0; j < D; ++j)\n            cell_rank[i][j] = -1;\n    for (int i = 0; i < M; ++i) {\n        auto [r, c] = order[i];\n        cell_rank[r][c] = i;\n    }\n}\n\n// ---------- helper for articulation test ----------\n// temporarily block (br,bc) and count reachable empty squares from entrance\nint count_reachable_without(int br, int bc, bool is_empty[D][D]) {\n    bool original = is_empty[br][bc];\n    is_empty[br][bc] = false;          // block the square\n\n    bool visited[D][D] = {false};\n    int cnt = 0;\n    queue<pair<int, int>> q;\n    q.push({entrance_r, entrance_c});\n    visited[entrance_r][entrance_c] = true;\n    ++cnt;\n\n    while (!q.empty()) {\n        auto [r, c] = q.front(); q.pop();\n        for (int d = 0; d < 4; ++d) {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n            if (!is_empty[nr][nc]) continue;\n            if (!visited[nr][nc]) {\n                visited[nr][nc] = true;\n                q.push({nr, nc});\n                ++cnt;\n            }\n        }\n    }\n\n    is_empty[br][bc] = original;       // restore\n    return cnt;\n}\n\n// ---------- main ----------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    int input_D;  // We'll read D but ignore it since it's always 9\n    cin >> input_D >> N;\n\n    // read obstacles\n    for (int i = 0; i < N; ++i) {\n        int r, c;\n        cin >> r >> c;\n        obstacle[r][c] = true;\n    }\n\n    // preprocessing\n    compute_bfs_distances();\n    build_order();\n\n    // initialise container numbers\n    for (int i = 0; i < D; ++i)\n        for (int j = 0; j < D; ++j)\n            container_num[i][j] = -1;\n\n    // ---------- placement phase ----------\n    for (int step = 0; step < M; ++step) {\n        int t;\n        cin >> t;\n\n        // build current empty mask (entrance + all non\u2011occupied, non\u2011obstacle)\n        bool is_empty[D][D] = {false};\n        for (int i = 0; i < D; ++i)\n            for (int j = 0; j < D; ++j) {\n                if (obstacle[i][j]) is_empty[i][j] = false;\n                else if (occupied[i][j]) is_empty[i][j] = false;\n                else is_empty[i][j] = true;      // includes entrance\n            }\n\n        // collect all reachable empty squares (except entrance)\n        vector<pair<int, int>> reachable;\n        bool visited[D][D] = {false};\n        queue<pair<int, int>> q;\n        q.push({entrance_r, entrance_c});\n        visited[entrance_r][entrance_c] = true;\n\n        while (!q.empty()) {\n            auto [r, c] = q.front(); q.pop();\n            if (!(r == entrance_r && c == entrance_c))\n                reachable.push_back({r, c});\n            for (int d = 0; d < 4; ++d) {\n                int nr = r + dr[d], nc = c + dc[d];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (!is_empty[nr][nc]) continue;\n                if (!visited[nr][nc]) {\n                    visited[nr][nc] = true;\n                    q.push({nr, nc});\n                }\n            }\n        }\n\n        // among reachable squares, keep only those that are not articulation points\n        vector<pair<int, int>> safe;\n        int total_empty = reachable.size() + 1;   // +1 for entrance\n        for (auto& s : reachable) {\n            int r = s.first, c = s.second;\n            int cnt = count_reachable_without(r, c, is_empty);\n            if (cnt == total_empty - 1)          // graph stays connected\n                safe.push_back(s);\n        }\n\n        // choose a square\n        pair<int, int> chosen;\n        if (!safe.empty()) {\n            // pick the safe square whose rank is closest to t\n            int best_diff = 1e9, best_dist = 1e9;\n            for (auto& s : safe) {\n                int r = s.first, c = s.second;\n                int rnk = cell_rank[r][c];\n                int diff = abs(rnk - t);\n                int d = dist[r][c];\n                if (diff < best_diff || (diff == best_diff && d < best_dist)) {\n                    best_diff = diff;\n                    best_dist = d;\n                    chosen = s;\n                }\n            }\n        } else {\n            // fallback \u2013 should never happen, but choose the closest reachable square\n            int best_dist = 1e9;\n            for (auto& s : reachable) {\n                int d = dist[s.first][s.second];\n                if (d < best_dist) {\n                    best_dist = d;\n                    chosen = s;\n                }\n            }\n        }\n\n        // output placement\n        cout << chosen.first << \" \" << chosen.second << endl;\n\n        // update state\n        occupied[chosen.first][chosen.second] = true;\n        container_num[chosen.first][chosen.second] = t;\n    }\n\n    // ---------- retrieval phase ----------\n    int remaining = M;\n    while (remaining > 0) {\n        // rebuild empty mask\n        bool is_empty[D][D] = {false};\n        for (int i = 0; i < D; ++i)\n            for (int j = 0; j < D; ++j) {\n                if (obstacle[i][j]) is_empty[i][j] = false;\n                else if (occupied[i][j]) is_empty[i][j] = false;\n                else is_empty[i][j] = true;\n            }\n\n        // find all containers adjacent to an empty square\n        vector<pair<int, int>> accessible;\n        for (int i = 0; i < D; ++i) {\n            for (int j = 0; j < D; ++j) {\n                if (!occupied[i][j]) continue;\n                bool adj = false;\n                for (int d = 0; d < 4; ++d) {\n                    int ni = i + dr[d], nj = j + dc[d];\n                    if (ni < 0 || ni >= D || nj < 0 || nj >= D) continue;\n                    if (is_empty[ni][nj]) {\n                        adj = true;\n                        break;\n                    }\n                }\n                if (adj) accessible.push_back({i, j});\n            }\n        }\n\n        // choose the one with the smallest number\n        auto best = accessible[0];\n        int best_num = container_num[best.first][best.second];\n        for (auto& p : accessible) {\n            int num = container_num[p.first][p.second];\n            if (num < best_num) {\n                best_num = num;\n                best = p;\n            }\n        }\n\n        // output retrieval\n        cout << best.first << \" \" << best.second << endl;\n\n        // remove it\n        occupied[best.first][best.second] = false;\n        container_num[best.first][best.second] = -1;\n        --remaining;\n    }\n\n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <utility>\n#include <algorithm>\nusing namespace std;\n\nconst int MAXN = 50;\nconst int MAXM = 100;\n\nint n, m;\nint cur[MAXN][MAXN];\nint colorCount[MAXM+1] = {0};          // 0..100\nint edgeCount[MAXM+1][MAXM+1] = {0};   // only upper triangular used\nbool required[MAXM+1][MAXM+1] = {false};\nbool allowed[MAXM+1] = {false};        // colors that may touch 0\n\nconst int dx[4] = {1, -1, 0, 0};\nconst int dy[4] = {0, 0, 1, -1};\n\n// Check if we can safely recolor (i,j) to 0\nbool isRemovable(int i, int j) {\n    int c = cur[i][j];\n    if (c == 0) return false;\n    if (!allowed[c]) return false;\n    if (colorCount[c] <= 1) return false;\n\n    int cnt[MAXM+1] = {0};   // count of neighbor colors (0..m)\n    bool adj_to_0 = false;\n    int same_color_neighbors = 0;\n\n    // examine four neighbours (outside counts as color 0)\n    for (int d = 0; d < 4; ++d) {\n        int ni = i + dx[d], nj = j + dy[d];\n        int col;\n        if (ni >= 0 && ni < n && nj >= 0 && nj < n)\n            col = cur[ni][nj];\n        else\n            col = 0;   // outside\n        cnt[col]++;\n        if (col == 0) adj_to_0 = true;\n        else if (!allowed[col]) return false;   // would create forbidden 0\u2013col adjacency\n        if (col == c) same_color_neighbors++;\n    }\n    if (!adj_to_0) return false;\n\n    // Edge count constraints\n    for (int d = 0; d <= m; ++d) {\n        if (cnt[d] == 0 || d == c) continue;\n        if (d == 0) {\n            // need at least one edge between c and 0 after removal\n            if (edgeCount[0][c] - cnt[0] < 1) return false;\n        } else {\n            int a = min(c, d), b = max(c, d);\n            if (required[a][b] && edgeCount[a][b] - cnt[d] < 1) return false;\n        }\n    }\n\n    // Connectivity of color c after removal\n    if (same_color_neighbors == 0) return false;   // should not happen\n    if (same_color_neighbors == 1) return true;    // leaf \u2013 safe\n\n    // BFS on color c, excluding (i,j)\n    int start_i = -1, start_j = -1;\n    for (int d = 0; d < 4; ++d) {\n        int ni = i + dx[d], nj = j + dy[d];\n        if (ni >= 0 && ni < n && nj >= 0 && nj < n && cur[ni][nj] == c) {\n            start_i = ni; start_j = nj; break;\n        }\n    }\n    if (start_i == -1) return false;   // no neighbour of same colour \u2013 impossible\n\n    bool visited[MAXN][MAXN] = {false};\n    queue<pair<int,int>> q;\n    visited[start_i][start_j] = true;\n    q.push({start_i, start_j});\n    int count = 0;\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        count++;\n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (nx >= 0 && nx < n && ny >= 0 && ny < n && !visited[nx][ny] &&\n                cur[nx][ny] == c && !(nx == i && ny == j)) {\n                visited[nx][ny] = true;\n                q.push({nx, ny});\n            }\n        }\n    }\n    return (count == colorCount[c] - 1);\n}\n\n// Actually recolor (i,j) from its colour c to 0\nvoid removeCell(int i, int j) {\n    int c = cur[i][j];\n    // Update edge counts for all incident edges\n    for (int d = 0; d < 4; ++d) {\n        int ni = i + dx[d], nj = j + dy[d];\n        int col;\n        if (ni >= 0 && ni < n && nj >= 0 && nj < n)\n            col = cur[ni][nj];\n        else\n            col = 0;   // outside\n        if (col == c) continue;   // no edge between same colours\n        // Remove edge c\u2013col\n        if (col == 0) {\n            edgeCount[0][c]--;\n        } else {\n            int a = min(c, col), b = max(c, col);\n            edgeCount[a][b]--;\n        }\n        // After recoloring, add edge 0\u2013col (if col != 0)\n        if (col != 0) {\n            edgeCount[0][col]++;\n        }\n    }\n    // Perform the recolor\n    cur[i][j] = 0;\n    colorCount[c]--;\n    colorCount[0]++;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n >> m;\n    for (int i = 0; i < n; ++i)\n        for (int j = 0; j < n; ++j) {\n            cin >> cur[i][j];\n            colorCount[cur[i][j]]++;\n        }\n\n    // Determine which colours are allowed to touch 0 (i.e. appear on the boundary)\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (i == 0 || i == n-1 || j == 0 || j == n-1)\n                allowed[cur[i][j]] = true;\n        }\n    }\n\n    // Build required adjacency matrix\n    // First, adjacency to outside (0)\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (i == 0 || i == n-1 || j == 0 || j == n-1) {\n                int c = cur[i][j];\n                required[0][c] = true;   // 0 < c, so store as [0][c]\n            }\n        }\n    }\n    // Then, adjacencies between colours >0\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c = cur[i][j];\n            if (i+1 < n) {\n                int d = cur[i+1][j];\n                if (c != d) {\n                    int a = min(c,d), b = max(c,d);\n                    required[a][b] = true;\n                }\n            }\n            if (j+1 < n) {\n                int d = cur[i][j+1];\n                if (c != d) {\n                    int a = min(c,d), b = max(c,d);\n                    required[a][b] = true;\n                }\n            }\n        }\n    }\n\n    // Compute initial edge counts\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c = cur[i][j];\n            // down\n            if (i+1 < n) {\n                int d = cur[i+1][j];\n                if (c != d) {\n                    int a = min(c,d), b = max(c,d);\n                    edgeCount[a][b]++;\n                }\n            }\n            // right\n            if (j+1 < n) {\n                int d = cur[i][j+1];\n                if (c != d) {\n                    int a = min(c,d), b = max(c,d);\n                    edgeCount[a][b]++;\n                }\n            }\n            // outside sides\n            if (i == 0) edgeCount[0][c]++;\n            if (i == n-1) edgeCount[0][c]++;\n            if (j == 0) edgeCount[0][c]++;\n            if (j == n-1) edgeCount[0][c]++;\n        }\n    }\n\n    // Erosion: repeatedly turn removable cells into 0\n    bool changed;\n    do {\n        changed = false;\n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                if (cur[i][j] == 0) continue;\n                if (isRemovable(i, j)) {\n                    removeCell(i, j);\n                    changed = true;\n                }\n            }\n        }\n    } while (changed);\n\n    // Output the final map\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (j) cout << ' ';\n            cout << cur[i][j];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, D, Q;\nvector<vector<int>> cmp;   // -2 unknown, -1: <, 0: =, 1: >\nint queries_used = 0;\n\n// Compare items i and j\nint compare_items(int i, int j) {\n    if (i == j) return 0;\n    if (cmp[i][j] != -2) return cmp[i][j];\n    cout << \"1 1 \" << i << \" \" << j << endl;\n    cout.flush();\n    string res;\n    cin >> res;\n    ++queries_used;\n    int ans;\n    if (res == \"<\") ans = -1;\n    else if (res == \">\") ans = 1;\n    else ans = 0;\n    cmp[i][j] = ans;\n    cmp[j][i] = -ans;\n    return ans;\n}\n\n// Compare two groups by total weight\nint compare_groups(const vector<int>& A, const vector<int>& B) {\n    if (A.empty() || B.empty()) return 0;\n    if (queries_used >= Q) return 0; // Fallback if no queries left\n    cout << A.size() << \" \" << B.size();\n    for (int x : A) cout << \" \" << x;\n    for (int x : B) cout << \" \" << x;\n    cout << endl;\n    cout.flush();\n    string res;\n    cin >> res;\n    ++queries_used;\n    if (res == \"<\") return -1;\n    else if (res == \">\") return 1;\n    else return 0;\n}\n\n// Merge sort for items\nvoid merge_sort(vector<int>& arr, int left, int right) {\n    if (left >= right || queries_used >= Q) return;\n    int mid = (left + right) / 2;\n    merge_sort(arr, left, mid);\n    merge_sort(arr, mid+1, right);\n    \n    vector<int> temp;\n    int i = left, j = mid+1;\n    while (i <= mid && j <= right && queries_used < Q) {\n        int res = compare_items(arr[i], arr[j]);\n        if (res <= 0) {\n            temp.push_back(arr[i++]);\n        } else {\n            temp.push_back(arr[j++]);\n        }\n    }\n    while (i <= mid) temp.push_back(arr[i++]);\n    while (j <= right) temp.push_back(arr[j++]);\n    \n    for (int k = 0; k < (int)temp.size(); ++k) {\n        arr[left + k] = temp[k];\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cout.tie(nullptr);\n\n    cin >> N >> D >> Q;\n    cmp.assign(N, vector<int>(N, -2));\n\n    // Estimate assignment cost: N * log2(D) comparisons\n    int logD = 0;\n    for (int t = D; t > 1; t >>= 1) ++logD;\n    logD = max(1, logD); // Ensure at least 1\n    int assign_budget = N * (logD + 1); // Conservative estimate\n    \n    int sort_budget = Q;\n    bool use_group_comparisons = (Q >= assign_budget);\n    if (use_group_comparisons) {\n        sort_budget = max(0, Q - assign_budget);\n    }\n\n    // Create item indices and sort using merge sort\n    vector<int> items(N);\n    iota(items.begin(), items.end(), 0);\n    \n    // Shuffle for better average-case performance\n    mt19937 rng(123456);\n    shuffle(items.begin(), items.end(), rng);\n    \n    // Perform merge sort with budget\n    merge_sort(items, 0, N-1);\n    \n    // If we didn't finish sorting due to budget, do insertion sort on remaining\n    if (queries_used < sort_budget) {\n        // Partial insertion sort to improve order\n        for (int i = 1; i < N && queries_used < sort_budget; ++i) {\n            int key = items[i];\n            int j = i - 1;\n            while (j >= 0 && queries_used < sort_budget) {\n                int res = compare_items(key, items[j]);\n                if (res < 0) {\n                    items[j+1] = items[j];\n                    --j;\n                } else break;\n            }\n            items[j+1] = key;\n        }\n    }\n\n    // Now items are sorted in ascending order (lightest to heaviest)\n    // We'll assign from heaviest to lightest\n    \n    vector<vector<int>> groups(D);\n    \n    // Seed groups with D heaviest items\n    for (int i = 0; i < D && i < N; ++i) {\n        int item = items[N-1-i]; // heaviest first\n        groups[i].push_back(item);\n    }\n\n    // Prepare items to assign (remaining heaviest to lightest)\n    vector<int> to_assign;\n    for (int i = D; i < N; ++i) {\n        to_assign.push_back(items[N-1-i]);\n    }\n\n    int assigned_idx = 0;\n    if (use_group_comparisons && queries_used < Q) {\n        // Use heap for efficient group selection\n        auto cmp_groups = [&](int i, int j) {\n            return compare_groups(groups[i], groups[j]) > 0; // Min-heap by weight\n        };\n        priority_queue<int, vector<int>, decltype(cmp_groups)> pq(cmp_groups);\n        \n        for (int i = 0; i < D; ++i) pq.push(i);\n        \n        while (assigned_idx < (int)to_assign.size() && queries_used < Q) {\n            // Estimate cost: 2*logD comparisons for pop+push\n            if (queries_used + 2*logD > Q) break;\n            \n            int g = pq.top(); pq.pop();\n            groups[g].push_back(to_assign[assigned_idx++]);\n            pq.push(g);\n        }\n    }\n\n    // Assign any remaining items without comparisons (round-robin)\n    for (; assigned_idx < (int)to_assign.size(); ++assigned_idx) {\n        int g = assigned_idx % D;\n        groups[g].push_back(to_assign[assigned_idx]);\n    }\n\n    // Output assignment\n    vector<int> ans(N);\n    for (int g = 0; g < D; ++g) {\n        for (int item : groups[g]) {\n            ans[item] = g;\n        }\n    }\n\n    // Dummy queries if needed\n    while (queries_used < Q) {\n        cout << \"1 1 0 1\" << endl;\n        cout.flush();\n        string dummy;\n        cin >> dummy;\n        ++queries_used;\n    }\n\n    // Output final division\n    for (int i = 0; i < N; ++i) {\n        cout << ans[i];\n        if (i < N-1) cout << \" \";\n    }\n    cout << endl;\n    cout.flush();\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int n, m;\n    cin >> n >> m;\n    int k = n / m;\n    vector<vector<int>> stacks(m);\n    for (int i = 0; i < m; ++i) {\n        stacks[i].resize(k);\n        for (int j = 0; j < k; ++j) {\n            cin >> stacks[i][j];\n        }\n    }\n\n    vector<pair<int, int>> ops;\n\n    // Function to get target stack for a number (0-indexed)\n    auto target_stack = [&](int v) {\n        return (v - 1) / k;\n    };\n\n    for (int v = 1; v <= n; ++v) {\n        // locate box v\n        int cur = -1, pos = -1;\n        for (int i = 0; i < m; ++i) {\n            for (int j = 0; j < (int)stacks[i].size(); ++j) {\n                if (stacks[i][j] == v) {\n                    cur = i;\n                    pos = j;\n                    break;\n                }\n            }\n            if (cur != -1) break;\n        }\n\n        // v is on top -> extract directly\n        if (pos == (int)stacks[cur].size() - 1) {\n            ops.emplace_back(v, 0);\n            stacks[cur].pop_back();\n        } else {\n            // move the block above v\n            int w = stacks[cur][pos + 1];   // box directly above v\n            \n            // Find maximum value in the block and count target stacks\n            int max_in_block = -1;\n            vector<int> target_counts(m, 0);\n            for (int j = pos + 1; j < (int)stacks[cur].size(); ++j) {\n                int box = stacks[cur][j];\n                max_in_block = max(max_in_block, box);\n                target_counts[target_stack(box)]++;\n            }\n            \n            // Find the target stack with the most boxes in the block\n            int best_target = -1;\n            int max_count = 0;\n            for (int i = 0; i < m; ++i) {\n                if (target_counts[i] > max_count) {\n                    max_count = target_counts[i];\n                    best_target = i;\n                } else if (target_counts[i] == max_count && best_target != -1) {\n                    // Tie-break: choose the one with larger top\n                    int top_best = stacks[best_target].empty() ? -1 : stacks[best_target].back();\n                    int top_i = stacks[i].empty() ? -1 : stacks[i].back();\n                    if (top_i > top_best) {\n                        best_target = i;\n                    }\n                }\n            }\n            \n            // Choose destination stack with improved strategy\n            int dest = -1;\n            // First, prefer an empty stack\n            for (int i = 0; i < m; ++i) {\n                if (i != cur && stacks[i].empty()) {\n                    dest = i;\n                    break;\n                }\n            }\n            \n            if (dest == -1 && best_target != -1 && best_target != cur) {\n                // Consider moving to the best target stack if conditions are good\n                int top_target = stacks[best_target].empty() ? -1 : stacks[best_target].back();\n                if (top_target > max_in_block) {\n                    dest = best_target;\n                }\n            }\n            \n            if (dest == -1) {\n                // Look for stacks where top > max_in_block\n                // Among these, choose the one with smallest top\n                int best_top = INT_MAX;\n                for (int i = 0; i < m; ++i) {\n                    if (i == cur || stacks[i].empty()) continue;\n                    int top_val = stacks[i].back();\n                    if (top_val > max_in_block && top_val < best_top) {\n                        best_top = top_val;\n                        dest = i;\n                    }\n                }\n                \n                // If no such stack, choose stack with largest top\n                if (dest == -1) {\n                    int max_top = -1;\n                    for (int i = 0; i < m; ++i) {\n                        if (i == cur) continue;\n                        if (!stacks[i].empty()) {\n                            int top_val = stacks[i].back();\n                            if (top_val > max_top) {\n                                max_top = top_val;\n                                dest = i;\n                            }\n                        }\n                    }\n                }\n            }\n            \n            // If still no destination (shouldn't happen), use current stack's first empty or something\n            if (dest == -1) {\n                for (int i = 0; i < m; ++i) {\n                    if (i != cur) {\n                        dest = i;\n                        break;\n                    }\n                }\n            }\n\n            // perform the move\n            ops.emplace_back(w, dest + 1);\n            // extract the block from cur\n            vector<int> moved(stacks[cur].begin() + pos + 1, stacks[cur].end());\n            stacks[cur].erase(stacks[cur].begin() + pos + 1, stacks[cur].end());\n            // append to destination\n            stacks[dest].insert(stacks[dest].end(), moved.begin(), moved.end());\n\n            // now v is on top -> extract it\n            ops.emplace_back(v, 0);\n            stacks[cur].pop_back();\n        }\n    }\n\n    // output the operation sequence\n    for (auto& p : ops) {\n        cout << p.first << \" \" << p.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAX_MOVES = 100000;\n\n// directions: up, down, left, right\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\nconst char move_char[] = {'U', 'D', 'L', 'R'};\nconst char opposite_char[] = {'D', 'U', 'R', 'L'};\n\nint N;\nvector<string> h, v;\nvector<vector<int>> d;\n\n// adjacency list: for each cell (i,j) list of (ni,nj,move_char)\nvector<vector<vector<tuple<int,int,char>>>> adj;\n\n// for coverage\nvector<vector<bool>> visited;\n\n// distances to (0,0)\nvector<vector<int>> dist0;\n\nchar get_opposite(char c) {\n    for (int k = 0; k < 4; ++k)\n        if (move_char[k] == c) return opposite_char[k];\n    return '?';\n}\n\nvoid build_graph() {\n    adj.assign(N, vector<vector<tuple<int,int,char>>>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            // down\n            if (i+1 < N && h[i][j] == '0')\n                adj[i][j].emplace_back(i+1, j, 'D');\n            // up\n            if (i-1 >= 0 && h[i-1][j] == '0')\n                adj[i][j].emplace_back(i-1, j, 'U');\n            // right\n            if (j+1 < N && v[i][j] == '0')\n                adj[i][j].emplace_back(i, j+1, 'R');\n            // left\n            if (j-1 >= 0 && v[i][j-1] == '0')\n                adj[i][j].emplace_back(i, j-1, 'L');\n        }\n    }\n}\n\nvoid compute_dist0() {\n    dist0.assign(N, vector<int>(N, -1));\n    queue<pair<int,int>> q;\n    q.emplace(0, 0);\n    dist0[0][0] = 0;\n    while (!q.empty()) {\n        auto [i,j] = q.front(); q.pop();\n        for (auto [ni, nj, move] : adj[i][j]) {\n            if (dist0[ni][nj] == -1) {\n                dist0[ni][nj] = dist0[i][j] + 1;\n                q.emplace(ni, nj);\n            }\n        }\n    }\n}\n\n// returns the base route (greedy DFS) and updates last_visit, current position, and time\nstring generate_base_route(vector<vector<int>>& last_visit, int& t, pair<int,int>& cur) {\n    visited.assign(N, vector<bool>(N, false));\n    string route;\n    stack<pair<int,int>> st;\n    stack<char> move_stack;\n    st.emplace(0, 0);\n    visited[0][0] = true;\n    last_visit[0][0] = 0;\n    t = 0;\n    cur = {0,0};\n\n    while (!st.empty()) {\n        auto [i,j] = st.top();\n        // find the unvisited neighbor with highest d\n        int best_d = -1;\n        char best_move = '?';\n        int best_ni = -1, best_nj = -1;\n        for (auto [ni, nj, move] : adj[i][j]) {\n            if (!visited[ni][nj]) {\n                if (d[ni][nj] > best_d) {\n                    best_d = d[ni][nj];\n                    best_move = move;\n                    best_ni = ni;\n                    best_nj = nj;\n                }\n            }\n        }\n        if (best_move != '?') {\n            // move to the best neighbor\n            visited[best_ni][best_nj] = true;\n            route += best_move;\n            ++t;\n            last_visit[best_ni][best_nj] = t;\n            cur = {best_ni, best_nj};\n            move_stack.push(best_move);\n            st.emplace(best_ni, best_nj);\n        } else {\n            // backtrack\n            st.pop();\n            if (!move_stack.empty()) {\n                char move_back = get_opposite(move_stack.top());\n                move_stack.pop();\n                route += move_back;\n                ++t;\n                auto [pi, pj] = st.top();\n                last_visit[pi][pj] = t;\n                cur = {pi, pj};\n            }\n        }\n    }\n    return route;\n}\n\n// greedy phase: returns the additional moves\nstring greedy_phase(pair<int,int> cur, int t, vector<vector<int>>& last_visit) {\n    string extra;\n    while (t < MAX_MOVES) {\n        int remaining = MAX_MOVES - t;\n        int ci = cur.first, cj = cur.second;\n        // if we must go directly to (0,0)\n        if (dist0[ci][cj] == remaining) {\n            // find neighbor with dist0 = remaining-1\n            for (auto [ni, nj, move] : adj[ci][cj]) {\n                if (dist0[ni][nj] == remaining - 1) {\n                    extra += move;\n                    ++t;\n                    last_visit[ni][nj] = t;\n                    cur = {ni, nj};\n                    break;\n                }\n            }\n        } else {\n            // choose neighbor with highest dirtiness among those with dist0 <= remaining-1\n            int best_dirt = -1;\n            int best_dist0 = INT_MAX;\n            char best_move = '?';\n            int best_ni = -1, best_nj = -1;\n            for (auto [ni, nj, move] : adj[ci][cj]) {\n                if (dist0[ni][nj] <= remaining - 1) {\n                    int dirt = (t - last_visit[ni][nj]) * d[ni][nj];\n                    if (dirt > best_dirt || (dirt == best_dirt && dist0[ni][nj] < best_dist0)) {\n                        best_dirt = dirt;\n                        best_dist0 = dist0[ni][nj];\n                        best_move = move;\n                        best_ni = ni;\n                        best_nj = nj;\n                    }\n                }\n            }\n            if (best_move != '?') {\n                extra += best_move;\n                ++t;\n                last_visit[best_ni][best_nj] = t;\n                cur = {best_ni, best_nj};\n            } else {\n                // fallback: move to any neighbor that reduces dist0\n                for (auto [ni, nj, move] : adj[ci][cj]) {\n                    if (dist0[ni][nj] < dist0[ci][cj]) {\n                        extra += move;\n                        ++t;\n                        last_visit[ni][nj] = t;\n                        cur = {ni, nj};\n                        break;\n                    }\n                }\n            }\n        }\n    }\n    return extra;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    h.resize(N-1);\n    for (int i = 0; i < N-1; ++i) cin >> h[i];\n    v.resize(N);\n    for (int i = 0; i < N; ++i) cin >> v[i];\n    d.assign(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> d[i][j];\n\n    build_graph();\n    compute_dist0();\n\n    vector<vector<int>> last_visit(N, vector<int>(N, 0));\n    int t = 0;\n    pair<int,int> cur = {0,0};\n    string base_route = generate_base_route(last_visit, t, cur);\n\n    string extra_route = greedy_phase(cur, t, last_visit);\n\n    cout << base_route << extra_route << endl;\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int INF = 1e9;\n\nstruct Solver {\n    int N, M, start_idx;\n    vector<int> xs, ys;\n    vector<vector<int>> cells;\n    vector<string> patterns;\n    vector<vector<char>> ov;\n\n    Solver(int N, int M, int start_idx, const vector<string>& grid, const vector<string>& patterns)\n        : N(N), M(M), start_idx(start_idx), patterns(patterns) {\n        int total = N * N;\n        xs.resize(total);\n        ys.resize(total);\n        cells.resize(26);\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                int idx = i * N + j;\n                xs[idx] = i;\n                ys[idx] = j;\n                int ch = grid[i][j] - 'A';\n                cells[ch].push_back(idx);\n            }\n        }\n\n        ov.assign(M, vector<char>(M, 0));\n        for (int i = 0; i < M; ++i) {\n            for (int j = 0; j < M; ++j) {\n                if (i == j) continue;\n                const string &a = patterns[i], &b = patterns[j];\n                for (int k = 4; k >= 1; --k) {\n                    if (a.compare(5 - k, k, b, 0, k) == 0) {\n                        ov[i][j] = k;\n                        break;\n                    }\n                }\n            }\n        }\n    }\n\n    vector<int> greedy_order_from(int start) const {\n        vector<bool> used(M, false);\n        vector<int> order;\n        order.push_back(start);\n        used[start] = true;\n        for (int step = 1; step < M; ++step) {\n            int last = order.back();\n            int best_ov = -1, best_next = -1;\n            for (int j = 0; j < M; ++j) {\n                if (!used[j]) {\n                    int o = ov[last][j];\n                    if (o > best_ov) {\n                        best_ov = o;\n                        best_next = j;\n                    }\n                }\n            }\n            order.push_back(best_next);\n            used[best_next] = true;\n        }\n        return order;\n    }\n\n    vector<int> random_greedy_order_from(int start, mt19937& rng) const {\n        vector<bool> used(M, false);\n        vector<int> order;\n        order.push_back(start);\n        used[start] = true;\n        for (int step = 1; step < M; ++step) {\n            int last = order.back();\n            int best_ov = -1;\n            vector<int> candidates;\n            for (int j = 0; j < M; ++j) {\n                if (!used[j]) {\n                    int o = ov[last][j];\n                    if (o > best_ov) {\n                        best_ov = o;\n                        candidates.clear();\n                        candidates.push_back(j);\n                    } else if (o == best_ov) {\n                        candidates.push_back(j);\n                    }\n                }\n            }\n            uniform_int_distribution<int> dist(0, candidates.size() - 1);\n            int chosen = candidates[dist(rng)];\n            order.push_back(chosen);\n            used[chosen] = true;\n        }\n        return order;\n    }\n\n    pair<int, vector<int>> solve_order(const vector<int>& order) const {\n        string S;\n        S.reserve(5 * M);\n        S += patterns[order[0]];\n        for (size_t i = 1; i < order.size(); ++i) {\n            int prev = order[i - 1];\n            int cur = order[i];\n            int k = ov[prev][cur];\n            S += patterns[cur].substr(k);\n        }\n        int L = S.size();\n        int total_cells = N * N;\n\n        vector<int> dp_prev(total_cells, INF);\n        vector<int> dp_curr(total_cells, INF);\n        vector<short> prev_cell(L * total_cells, -1);\n\n        int first_ch = S[0] - 'A';\n        for (int v : cells[first_ch]) {\n            int d = abs(xs[start_idx] - xs[v]) + abs(ys[start_idx] - ys[v]);\n            dp_prev[v] = d + 1;\n            prev_cell[0 * total_cells + v] = -1;\n        }\n\n        for (int pos = 1; pos < L; ++pos) {\n            int cur_ch = S[pos] - 'A';\n            int prev_ch = S[pos - 1] - 'A';\n            const auto& prev_cells = cells[prev_ch];\n            const auto& cur_cells = cells[cur_ch];\n\n            fill(dp_curr.begin(), dp_curr.end(), INF);\n            for (int v : cur_cells) {\n                int best = INF;\n                short best_u = -1;\n                for (int u : prev_cells) {\n                    if (dp_prev[u] == INF) continue;\n                    int d = abs(xs[u] - xs[v]) + abs(ys[u] - ys[v]);\n                    int cand = dp_prev[u] + d;\n                    if (cand < best) {\n                        best = cand;\n                        best_u = u;\n                    }\n                }\n                dp_curr[v] = best + 1;\n                prev_cell[pos * total_cells + v] = best_u;\n            }\n            swap(dp_prev, dp_curr);\n        }\n\n        int last_ch = S[L - 1] - 'A';\n        int best_cost = INF, best_end = -1;\n        for (int v : cells[last_ch]) {\n            if (dp_prev[v] < best_cost) {\n                best_cost = dp_prev[v];\n                best_end = v;\n            }\n        }\n\n        vector<int> path(L);\n        int cur_cell = best_end;\n        for (int pos = L - 1; pos >= 0; --pos) {\n            path[pos] = cur_cell;\n            cur_cell = prev_cell[pos * total_cells + cur_cell];\n        }\n\n        return {best_cost, path};\n    }\n\n    vector<int> two_opt_improve(vector<int> order, int iterations, mt19937& rng) const {\n        int cur_cost = solve_order(order).first;\n        int n = order.size();\n        for (int iter = 0; iter < iterations; ++iter) {\n            int i = rng() % n;\n            int j = rng() % n;\n            if (i == j) continue;\n            if (i > j) swap(i, j);\n            // reverse segment [i, j]\n            reverse(order.begin() + i, order.begin() + j + 1);\n            int new_cost = solve_order(order).first;\n            if (new_cost < cur_cost) {\n                cur_cost = new_cost;\n            } else {\n                // revert\n                reverse(order.begin() + i, order.begin() + j + 1);\n            }\n        }\n        return order;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n    int si, sj;\n    cin >> si >> sj;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n    vector<string> patterns(M);\n    for (int k = 0; k < M; ++k) cin >> patterns[k];\n\n    Solver solver(N, M, si * N + sj, grid, patterns);\n\n    mt19937 rng(123456);\n    const int K = 10;  // Increased from 5 to 10\n\n    int best_cost = INF;\n    vector<int> best_order;\n\n    for (int start = 0; start < M; ++start) {\n        // Deterministic greedy\n        vector<int> order = solver.greedy_order_from(start);\n        auto [cost, path] = solver.solve_order(order);\n        if (cost < best_cost) {\n            best_cost = cost;\n            best_order = order;\n        }\n        reverse(order.begin(), order.end());\n        auto [cost_rev, path_rev] = solver.solve_order(order);\n        if (cost_rev < best_cost) {\n            best_cost = cost_rev;\n            best_order = order;\n        }\n\n        // Random greedy orders\n        for (int iter = 0; iter < K; ++iter) {\n            vector<int> rand_order = solver.random_greedy_order_from(start, rng);\n            auto [cost_rand, path_rand] = solver.solve_order(rand_order);\n            if (cost_rand < best_cost) {\n                best_cost = cost_rand;\n                best_order = rand_order;\n            }\n            reverse(rand_order.begin(), rand_order.end());\n            auto [cost_rand_rev, path_rand_rev] = solver.solve_order(rand_order);\n            if (cost_rand_rev < best_cost) {\n                best_cost = cost_rand_rev;\n                best_order = rand_order;\n            }\n        }\n    }\n\n    // Apply 2-opt local search to further improve the best order\n    mt19937 rng2(654321);  // Different seed for local search\n    best_order = solver.two_opt_improve(best_order, 2000, rng2);\n\n    auto [final_cost, final_path] = solver.solve_order(best_order);\n    for (int idx : final_path) {\n        int i = idx / N;\n        int j = idx % N;\n        cout << i << ' ' << j << '\\n';\n    }\n\n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <cmath>\n#include <numeric>\n#include <cstdint>\n#include <tuple>\n\nusing namespace std;\n\nstruct Placement {\n    vector<short> cells;          // indices of covered cells (0..N*N-1)\n    vector<uint8_t> contrib;      // contribution to each measurement\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cout.tie(nullptr);\n\n    int N, M;\n    double eps;\n    cin >> N >> M >> eps;\n    double alpha = 1.0 - 2.0 * eps;\n    double beta = eps;\n\n    // read shapes\n    vector<vector<pair<int, int>>> shape_cells(M);\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        shape_cells[k].resize(d);\n        for (int t = 0; t < d; ++t) {\n            cin >> shape_cells[k][t].first >> shape_cells[k][t].second;\n        }\n    }\n\n    // number of divine queries: enough for recovery but leave room for fallback drilling\n    int L = min(150, N * N - 10);\n    // random generator for subsets\n    mt19937 rng(123456);\n    uniform_real_distribution<double> prob(0.0, 1.0);\n\n    // generate random subsets and record which measurements contain each cell\n    vector<vector<int>> subsets(L);\n    vector<vector<int>> meas_including(N * N);\n    for (int l = 0; l < L; ++l) {\n        vector<int>& sub = subsets[l];\n        for (int idx = 0; idx < N * N; ++idx) {\n            if (prob(rng) < 0.5) {\n                sub.push_back(idx);\n                meas_including[idx].push_back(l);\n            }\n        }\n    }\n\n    // precompute all possible placements and their contributions\n    vector<vector<Placement>> placements(M);\n    for (int k = 0; k < M; ++k) {\n        const auto& cells = shape_cells[k];\n        int max_i = 0, max_j = 0;\n        for (auto& p : cells) {\n            max_i = max(max_i, p.first);\n            max_j = max(max_j, p.second);\n        }\n        int h = max_i + 1, w = max_j + 1;\n        for (int dx = 0; dx <= N - h; ++dx) {\n            for (int dy = 0; dy <= N - w; ++dy) {\n                Placement pl;\n                // compute cell indices\n                for (auto& p : cells) {\n                    int i = dx + p.first;\n                    int j = dy + p.second;\n                    pl.cells.push_back(i * N + j);\n                }\n                // compute contribution vector\n                pl.contrib.assign(L, 0);\n                for (int idx : pl.cells) {\n                    for (int l : meas_including[idx]) {\n                        pl.contrib[l]++;\n                    }\n                }\n                placements[k].push_back(move(pl));\n            }\n        }\n    }\n\n    // perform divine queries\n    vector<double> z_vals(L);\n    for (int l = 0; l < L; ++l) {\n        int k = subsets[l].size();\n        cout << \"q \" << k;\n        for (int idx : subsets[l]) {\n            int i = idx / N, j = idx % N;\n            cout << ' ' << i << ' ' << j;\n        }\n        cout << endl;\n        int y;\n        cin >> y;\n        z_vals[l] = (y - beta * k) / alpha;\n    }\n\n    // ----- Greedy OMP to obtain an initial assignment -----\n    vector<int> assignment(M, -1);\n    vector<double> residual = z_vals;\n    for (int iter = 0; iter < M; ++iter) {\n        double best_score = -1e100;\n        int best_shape = -1, best_place = -1;\n        for (int k = 0; k < M; ++k) {\n            if (assignment[k] != -1) continue;\n            const auto& plist = placements[k];\n            for (size_t p_idx = 0; p_idx < plist.size(); ++p_idx) {\n                const auto& p = plist[p_idx];\n                double dot = 0.0, norm2 = 0.0;\n                for (int l = 0; l < L; ++l) {\n                    double c = p.contrib[l];\n                    dot += residual[l] * c;\n                    norm2 += c * c;\n                }\n                if (norm2 == 0) continue;\n                double score = dot / sqrt(norm2);\n                if (score > best_score) {\n                    best_score = score;\n                    best_shape = k;\n                    best_place = p_idx;\n                }\n            }\n        }\n        // assign the best found\n        assignment[best_shape] = best_place;\n        const auto& p = placements[best_shape][best_place];\n        for (int l = 0; l < L; ++l) {\n            residual[l] -= p.contrib[l];\n        }\n    }\n\n    // ----- Simulated Annealing to refine the assignment -----\n    // current sums and error\n    vector<double> cur_sum(L, 0.0);\n    for (int k = 0; k < M; ++k) {\n        const auto& p = placements[k][assignment[k]];\n        for (int l = 0; l < L; ++l) cur_sum[l] += p.contrib[l];\n    }\n    double cur_err = 0.0;\n    for (int l = 0; l < L; ++l) {\n        double diff = z_vals[l] - cur_sum[l];\n        cur_err += diff * diff;\n    }\n\n    vector<int> best_assignment = assignment;\n    double best_err = cur_err;\n\n    const int SA_ITER = 50000;\n    const double INITIAL_TEMP = 1000.0;\n    const double COOLING = 0.9995;\n    double temp = INITIAL_TEMP;\n\n    mt19937 rng_sa(987654);\n    uniform_int_distribution<int> shape_dist(0, M - 1);\n    vector<uniform_int_distribution<int>> place_dist;\n    for (int k = 0; k < M; ++k) {\n        place_dist.emplace_back(0, placements[k].size() - 1);\n    }\n\n    for (int it = 0; it < SA_ITER; ++it) {\n        int k = shape_dist(rng_sa);\n        int old_idx = assignment[k];\n        int new_idx = place_dist[k](rng_sa);\n        if (new_idx == old_idx) continue;\n\n        const auto& p_old = placements[k][old_idx];\n        const auto& p_new = placements[k][new_idx];\n\n        double delta_err = 0.0;\n        for (int l = 0; l < L; ++l) {\n            double delta = (double)p_new.contrib[l] - (double)p_old.contrib[l];\n            double e_l = z_vals[l] - cur_sum[l];\n            delta_err += -2.0 * e_l * delta + delta * delta;\n        }\n\n        if (delta_err < 0 || uniform_real_distribution<double>(0, 1)(rng_sa) < exp(-delta_err / temp)) {\n            cur_err += delta_err;\n            for (int l = 0; l < L; ++l) {\n                cur_sum[l] += (p_new.contrib[l] - p_old.contrib[l]);\n            }\n            assignment[k] = new_idx;\n            if (cur_err < best_err) {\n                best_err = cur_err;\n                best_assignment = assignment;\n            }\n        }\n        temp *= COOLING;\n    }\n\n    // use the best assignment found\n    assignment = best_assignment;\n    // recompute current sums and error for this assignment\n    fill(cur_sum.begin(), cur_sum.end(), 0.0);\n    for (int k = 0; k < M; ++k) {\n        const auto& p = placements[k][assignment[k]];\n        for (int l = 0; l < L; ++l) cur_sum[l] += p.contrib[l];\n    }\n    cur_err = 0.0;\n    for (int l = 0; l < L; ++l) {\n        double diff = z_vals[l] - cur_sum[l];\n        cur_err += diff * diff;\n    }\n\n    // ----- Local hill climbing -----\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng_sa);\n        for (int k : order) {\n            int old_idx = assignment[k];\n            const auto& p_old = placements[k][old_idx];\n            for (size_t new_idx = 0; new_idx < placements[k].size(); ++new_idx) {\n                if (new_idx == static_cast<size_t>(old_idx)) continue;\n                const auto& p_new = placements[k][new_idx];\n                double delta_err = 0.0;\n                for (int l = 0; l < L; ++l) {\n                    double delta = (double)p_new.contrib[l] - (double)p_old.contrib[l];\n                    double e_l = z_vals[l] - cur_sum[l];\n                    delta_err += -2.0 * e_l * delta + delta * delta;\n                }\n                if (delta_err < -1e-9) {\n                    cur_err += delta_err;\n                    for (int l = 0; l < L; ++l) {\n                        double delta = (double)p_new.contrib[l] - (double)p_old.contrib[l];\n                        cur_sum[l] += delta;\n                    }\n                    assignment[k] = new_idx;\n                    improved = true;\n                    break; // go to next shape\n                }\n            }\n        }\n    }\n\n    // ----- Reconstruct the island from the assignment -----\n    vector<vector<int>> grid(N, vector<int>(N, 0));\n    for (int k = 0; k < M; ++k) {\n        const auto& p = placements[k][assignment[k]];\n        for (int idx : p.cells) {\n            int i = idx / N, j = idx % N;\n            grid[i][j]++;\n        }\n    }\n\n    // collect cells with positive oil reserves\n    vector<pair<int, int>> positive;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] > 0) {\n                positive.emplace_back(i, j);\n            }\n        }\n    }\n\n    // ----- First guess -----\n    cout << \"a \" << positive.size();\n    for (auto& p : positive) {\n        cout << ' ' << p.first << ' ' << p.second;\n    }\n    cout << endl;\n\n    int resp;\n    cin >> resp;\n    if (resp == 1) {\n        return 0;\n    }\n\n    // ----- Fallback: drill every cell -----\n    vector<bool> has_oil(N * N, false);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << \"q 1 \" << i << ' ' << j << endl;\n            int val;\n            cin >> val;\n            if (val > 0) {\n                has_oil[i * N + j] = true;\n            }\n        }\n    }\n\n    positive.clear();\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (has_oil[i * N + j]) {\n                positive.emplace_back(i, j);\n            }\n        }\n    }\n\n    cout << \"a \" << positive.size();\n    for (auto& p : positive) {\n        cout << ' ' << p.first << ' ' << p.second;\n    }\n    cout << endl;\n\n    cin >> resp; // should be 1\n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cstdint>\n\nusing namespace std;\nusing ll = long long;\n\nint W, D, N;\n\nll compute_shortage(const vector<int>& sorted_areas, const vector<int>& widths) {\n    ll cost = 0;\n    for (size_t i = 0; i < sorted_areas.size(); ++i) {\n        ll area = (ll)widths[i] * W;\n        if (sorted_areas[i] > area) {\n            cost += 100LL * (sorted_areas[i] - area);\n        }\n    }\n    return cost;\n}\n\nvector<int> compute_optimal_widths(const vector<int>& sorted_areas) {\n    vector<int> widths(N, 1);\n    int total = N;\n    for (int i = 0; i < N; ++i) {\n        int needed = (sorted_areas[i] + W - 1) / W;\n        int add = min(W - total, max(0, needed - 1));\n        widths[i] += add;\n        total += add;\n    }\n    if (total < W) {\n        widths[0] += (W - total);\n    }\n    return widths;\n}\n\nint compute_transition_cost(const vector<int>& widths1, const vector<int>& widths2) {\n    vector<int> cum1(N), cum2(N);\n    int sum1 = 0, sum2 = 0;\n    for (int i = 0; i < N; ++i) {\n        sum1 += widths1[i];\n        cum1[i] = sum1;\n        sum2 += widths2[i];\n        cum2[i] = sum2;\n    }\n    int move_count = 0;\n    for (int i = 0; i < N-1; ++i) {\n        if (cum1[i] != cum2[i]) {\n            move_count++;\n        }\n    }\n    return 2000 * move_count;\n}\n\nvector<int> improve_widths(const vector<int>& widths, const vector<int>& sorted_areas) {\n    vector<int> w = widths;\n    for (int step = 0; step < 10; ++step) {\n        bool improved = false;\n        for (int i = 0; i < N; ++i) {\n            for (int j = i+1; j < N; ++j) {\n                if (w[i] > w[j] && (ll)w[i] * W > sorted_areas[i] && (ll)w[j] * W < sorted_areas[j]) {\n                    if (w[i] - 1 >= w[j] + 1) {\n                        w[i]--;\n                        w[j]++;\n                        improved = true;\n                        break;\n                    }\n                }\n            }\n            if (improved) break;\n        }\n        if (!improved) break;\n    }\n    return w;\n}\n\nvoid output_rectangles(const vector<int>& widths, const vector<int>& orig_idx) {\n    vector<pair<int, int>> strip_lr(N);\n    int left = 0;\n    for (int i = 0; i < N; ++i) {\n        int right = left + widths[i];\n        strip_lr[i] = {left, right};\n        left = right;\n    }\n    vector<int> assign(N);\n    for (int i = 0; i < N; ++i) {\n        assign[orig_idx[i]] = i;\n    }\n    for (int k = 0; k < N; ++k) {\n        int strip_idx = assign[k];\n        auto [l, r] = strip_lr[strip_idx];\n        cout << \"0 \" << l << \" \" << W << \" \" << r << \"\\n\";\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    cin >> W >> D >> N;\n    \n    vector<vector<int>> a(D, vector<int>(N));\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            cin >> a[d][k];\n        }\n    }\n    \n    // day 0\n    vector<pair<int, int>> order(N);\n    for (int k = 0; k < N; ++k) {\n        order[k] = {a[0][k], k};\n    }\n    sort(order.begin(), order.end(), greater<pair<int, int>>());\n    vector<int> sorted_areas(N);\n    vector<int> orig_idx(N);\n    for (int i = 0; i < N; ++i) {\n        sorted_areas[i] = order[i].first;\n        orig_idx[i] = order[i].second;\n    }\n    \n    vector<int> current_widths = compute_optimal_widths(sorted_areas);\n    output_rectangles(current_widths, orig_idx);\n    \n    // subsequent days\n    for (int d = 1; d < D; ++d) {\n        // sort current day's areas\n        order.resize(N);\n        for (int k = 0; k < N; ++k) {\n            order[k] = {a[d][k], k};\n        }\n        sort(order.begin(), order.end(), greater<pair<int, int>>());\n        sorted_areas.resize(N);\n        orig_idx.resize(N);\n        for (int i = 0; i < N; ++i) {\n            sorted_areas[i] = order[i].first;\n            orig_idx[i] = order[i].second;\n        }\n        \n        // compute candidates\n        vector<int> greedy_widths = compute_optimal_widths(sorted_areas);\n        vector<int> local_widths = improve_widths(current_widths, sorted_areas);\n        \n        vector<vector<int>> candidates = {current_widths, greedy_widths, local_widths};\n        ll best_cost = 1e18;\n        vector<int> best_widths;\n        \n        for (const auto& cand : candidates) {\n            ll shortage = compute_shortage(sorted_areas, cand);\n            int trans_cost = compute_transition_cost(current_widths, cand);\n            ll total = shortage + trans_cost;\n            if (total < best_cost) {\n                best_cost = total;\n                best_widths = cand;\n            }\n        }\n        \n        output_rectangles(best_widths, orig_idx);\n        current_widths = best_widths;\n    }\n    \n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <array>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <cstdint>\n\nusing namespace std;\n\nconst int MOD = 998244353;\nconst int N = 9, M = 20, K = 81;\n\nstruct Operation {\n    int stamp, p, q;\n    vector<pair<int, int>> cells;\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m, k;\n    cin >> n >> m >> k;\n\n    vector<int64_t> cur(81);\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cin >> cur[i * 9 + j];\n        }\n    }\n\n    vector<array<array<int, 3>, 3>> stamps(m);\n    for (int s = 0; s < m; ++s) {\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                cin >> stamps[s][i][j];\n            }\n        }\n    }\n\n    vector<Operation> ops;\n    for (int s = 0; s < m; ++s) {\n        for (int p = 0; p <= n - 3; ++p) {\n            for (int q = 0; q <= n - 3; ++q) {\n                Operation op;\n                op.stamp = s;\n                op.p = p;\n                op.q = q;\n                for (int i = 0; i < 3; ++i) {\n                    for (int j = 0; j < 3; ++j) {\n                        int cell = (p + i) * 9 + (q + j);\n                        int val = stamps[s][i][j];\n                        op.cells.emplace_back(cell, val);\n                    }\n                }\n                ops.push_back(move(op));\n            }\n        }\n    }\n    const int num_ops = ops.size();\n\n    int64_t score = 0;\n    for (int i = 0; i < 81; ++i) score += cur[i] % MOD;\n\n    auto delta_add = [&](int id) -> int64_t {\n        int64_t d = 0;\n        for (auto [idx, val] : ops[id].cells) {\n            int64_t old_rem = cur[idx] % MOD;\n            int64_t new_val = cur[idx] + val;\n            int64_t new_rem = new_val % MOD;\n            d += new_rem - old_rem;\n        }\n        return d;\n    };\n\n    auto apply_add = [&](int id) {\n        for (auto [idx, val] : ops[id].cells) {\n            cur[idx] += val;\n        }\n    };\n\n    auto delta_remove = [&](int id) -> int64_t {\n        int64_t d = 0;\n        for (auto [idx, val] : ops[id].cells) {\n            int64_t old_rem = cur[idx] % MOD;\n            int64_t new_val = cur[idx] - val;\n            int64_t new_rem = new_val % MOD;\n            d += new_rem - old_rem;\n        }\n        return d;\n    };\n\n    auto apply_remove = [&](int id) {\n        for (auto [idx, val] : ops[id].cells) {\n            cur[idx] -= val;\n        }\n    };\n\n    // Greedy initial solution\n    vector<int> cur_ops;\n    while (cur_ops.size() < K) {\n        int best_id = -1;\n        int64_t best_delta = 0;\n        for (int id = 0; id < num_ops; ++id) {\n            int64_t d = delta_add(id);\n            if (d > best_delta) {\n                best_delta = d;\n                best_id = id;\n            }\n        }\n        if (best_delta <= 0) break;\n        apply_add(best_id);\n        cur_ops.push_back(best_id);\n        score += best_delta;\n    }\n\n    // Simulated Annealing with increased iterations and adjusted probabilities\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> uni_real(0.0, 1.0);\n\n    const int max_iter = 3'000'000;  // Increased from 1M to 3M\n    const double T0 = 1e8;\n    double T = T0;\n\n    static int64_t contrib[81];\n    static vector<int> touched;\n\n    for (int iter = 0; iter < max_iter; ++iter) {\n        double r = uni_real(rng);\n        // Adjusted probabilities: 20% add, 20% remove, 60% replace\n        if (r < 0.2 && cur_ops.size() < K) {\n            // Add operation\n            int new_id = rng() % num_ops;\n            int64_t delta = delta_add(new_id);\n            if (delta > 0 || (delta <= 0 && exp(delta / T) > uni_real(rng))) {\n                apply_add(new_id);\n                cur_ops.push_back(new_id);\n                score += delta;\n            }\n        } else if (r < 0.4 && !cur_ops.empty()) {\n            // Remove operation\n            int idx = rng() % cur_ops.size();\n            int old_id = cur_ops[idx];\n            int64_t delta = delta_remove(old_id);\n            if (delta > 0 || (delta <= 0 && exp(delta / T) > uni_real(rng))) {\n                apply_remove(old_id);\n                cur_ops[idx] = cur_ops.back();\n                cur_ops.pop_back();\n                score += delta;\n            }\n        } else if (!cur_ops.empty()) {\n            // Replace operation (60% chance)\n            int idx = rng() % cur_ops.size();\n            int old_id = cur_ops[idx];\n            int new_id = rng() % num_ops;\n            if (new_id == old_id) continue;\n\n            // Compute net change using contrib array\n            touched.clear();\n            for (auto [i, v] : ops[old_id].cells) {\n                if (contrib[i] == 0) touched.push_back(i);\n                contrib[i] -= v;\n            }\n            for (auto [i, v] : ops[new_id].cells) {\n                if (contrib[i] == 0) touched.push_back(i);\n                contrib[i] += v;\n            }\n\n            int64_t delta = 0;\n            for (int i : touched) {\n                int64_t net = contrib[i];\n                int64_t old_rem = cur[i] % MOD;\n                int64_t new_val = cur[i] + net;\n                int64_t new_rem = new_val % MOD;\n                delta += new_rem - old_rem;\n            }\n\n            if (delta > 0 || (delta <= 0 && exp(delta / T) > uni_real(rng))) {\n                for (int i : touched) {\n                    cur[i] += contrib[i];\n                }\n                cur_ops[idx] = new_id;\n                score += delta;\n            }\n\n            for (int i : touched) {\n                contrib[i] = 0;\n            }\n        }\n\n        // Linear cooling\n        T = T0 * (1.0 - (double)iter / max_iter);\n    }\n\n    // Output\n    cout << cur_ops.size() << '\\n';\n    for (int id : cur_ops) {\n        cout << ops[id].stamp << ' ' << ops[id].p << ' ' << ops[id].q << '\\n';\n    }\n\n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <deque>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <climits>\n#include <cstdlib>\n#include <utility>\n\nusing namespace std;\n\nint main() {\n    const int N = 5;\n    int A[N][N];\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> A[i][j];\n\n    // queues of remaining containers for each receiving gate\n    deque<int> gate_rem[N];\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            gate_rem[i].push_back(A[i][j]);\n\n    int grid[N][N];\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            grid[i][j] = -1;          // -1 means empty\n\n    int hold = -1;                    // -1: not holding, otherwise container number\n    int posx = 0, posy = 0;           // position of the large crane\n\n    bool dispatched[25] = {false};\n    int next_exp[5];                  // next expected container for each row\n    for (int i = 0; i < N; ++i)\n        next_exp[i] = N * i;\n\n    pair<int, int> loc[25];           // location of container on the grid, (-1,-1) if not present\n    for (int i = 0; i < 25; ++i)\n        loc[i] = {-1, -1};\n\n    vector<string> ans(5);            // actions for the five cranes\n    int dispatched_cnt = 0;\n\n    const int INF = 1000000;\n\n    // helper lambdas\n    auto manhattan = [](int x1, int y1, int x2, int y2) {\n        return abs(x1 - x2) + abs(y1 - y2);\n    };\n\n    auto move_towards = [](int x, int y, int tx, int ty) -> char {\n        if (x < tx) return 'D';\n        if (x > tx) return 'U';\n        if (y < ty) return 'R';\n        if (y > ty) return 'L';\n        return '.';\n    };\n\n    auto find_buffer = [&](int x, int y, bool allow_active_gates) -> pair<int, int> {\n        int best_dist = INF;\n        pair<int, int> best = {-1, -1};\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N - 1; ++j) {   // columns 0..3 (col4 is dispatch)\n                if (grid[i][j] != -1) continue;\n                if (j == 0 && !allow_active_gates && !gate_rem[i].empty())\n                    continue;\n                int d = manhattan(x, y, i, j);\n                if (d < best_dist) {\n                    best_dist = d;\n                    best = {i, j};\n                }\n            }\n        }\n        return best;\n    };\n\n    auto estimated_store_distance = [&](int x, int y) -> int {\n        auto buf = find_buffer(x, y, false);\n        if (buf.first == -1) return INF;\n        return manhattan(x, y, buf.first, buf.second);\n    };\n\n    struct Candidate {\n        int cost;\n        int type;       // 0 = retrieve stored needed, 1 = pick up from gate\n        int b;          // container number\n        int px, py;     // pickup location\n        bool needed;    // for type 1: is it the next expected?\n    };\n\n    int turn = 0;\n    while (dispatched_cnt < N * N) {\n        ++turn;\n        if (turn > 10000) break;   // safety limit\n\n        // ---------- Step 1: place containers at receiving gates ----------\n        for (int i = 0; i < N; ++i) {\n            if (grid[i][0] == -1) {\n                // placement is blocked only if the large crane is at (i,0) and holding\n                if (!(posx == i && posy == 0 && hold != -1)) {\n                    if (!gate_rem[i].empty()) {\n                        int b = gate_rem[i].front();\n                        gate_rem[i].pop_front();\n                        grid[i][0] = b;\n                        loc[b] = {i, 0};\n                    }\n                }\n            }\n        }\n\n        // ---------- Step 2: decide action for the large crane ----------\n        char action;\n\n        if (hold != -1) {   // holding a container\n            int b = hold;\n            int r = b / N;\n            if (b == next_exp[r]) {   // should deliver\n                if (posx == r && posy == N - 1)\n                    action = 'Q';\n                else\n                    action = move_towards(posx, posy, r, N - 1);\n            } else {   // should store\n                // can we release here?\n                bool can_release_here = false;\n                if (posy != N - 1 && grid[posx][posy] == -1) {\n                    if (posy != 0 || gate_rem[posx].empty())\n                        can_release_here = true;\n                }\n                if (can_release_here) {\n                    action = 'Q';\n                } else {\n                    auto target = find_buffer(posx, posy, false);\n                    if (target.first == -1)   // no buffer -> fallback to deliver (causes inversion)\n                        target = {r, N - 1};\n                    action = move_towards(posx, posy, target.first, target.second);\n                }\n            }\n        } else {   // not holding\n            vector<Candidate> cand;\n\n            // retrieve stored needed containers\n            for (int r = 0; r < N; ++r) {\n                int b = next_exp[r];\n                if (b >= 0 && b < N * N && loc[b].first != -1) {\n                    int px = loc[b].first, py = loc[b].second;\n                    int d1 = manhattan(posx, posy, px, py);\n                    int d2 = manhattan(px, py, r, N - 1);\n                    int cost = d1 + d2 + 2;\n                    cand.push_back({cost, 0, b, px, py, true});\n                }\n            }\n\n            // pick up from gates\n            for (int i = 0; i < N; ++i) {\n                if (gate_rem[i].empty()) continue;\n                int head = gate_rem[i][0];\n                // only consider if the gate cell is empty or already contains the head\n                if (grid[i][0] != -1 && grid[i][0] != head) continue;\n                int px = i, py = 0;\n                int r = head / N;\n                bool needed = (head == next_exp[r]);\n                int d1 = manhattan(posx, posy, px, py);\n                int d2;\n                if (needed) {\n                    d2 = manhattan(px, py, r, N - 1);\n                } else {\n                    d2 = estimated_store_distance(px, py);\n                    if (d2 >= INF) d2 = 1000;   // large fallback\n                }\n                int cost = d1 + d2 + 2;\n                cand.push_back({cost, 1, head, px, py, needed});\n            }\n\n            if (cand.empty()) {\n                action = '.';\n            } else {\n                auto best = *min_element(cand.begin(), cand.end(),\n                    [](const Candidate& a, const Candidate& b) { return a.cost < b.cost; });\n                if (posx == best.px && posy == best.py)\n                    action = 'P';\n                else\n                    action = move_towards(posx, posy, best.px, best.py);\n            }\n        }\n\n        // execute the chosen action for crane 0\n        switch (action) {\n            case 'P':\n                hold = grid[posx][posy];\n                grid[posx][posy] = -1;\n                loc[hold] = {-1, -1};\n                break;\n            case 'Q':\n                grid[posx][posy] = hold;\n                loc[hold] = {posx, posy};\n                hold = -1;\n                break;\n            case 'U':\n                if (posx > 0) posx--;\n                break;\n            case 'D':\n                if (posx < N - 1) posx++;\n                break;\n            case 'L':\n                if (posy > 0) posy--;\n                break;\n            case 'R':\n                if (posy < N - 1) posy++;\n                break;\n            case '.':\n                break;\n            case 'B':\n                break;   // never used for crane 0\n        }\n\n        ans[0] += action;\n\n        // actions for the four small cranes (1..4)\n        for (int i = 1; i < N; ++i) {\n            if (turn == 1)\n                ans[i] += 'B';\n            else\n                ans[i] += '.';\n        }\n\n        // ---------- Step 3: dispatch containers at dispatch gates ----------\n        for (int i = 0; i < N; ++i) {\n            if (grid[i][N - 1] != -1) {\n                int b = grid[i][N - 1];\n                grid[i][N - 1] = -1;\n                dispatched[b] = true;\n                loc[b] = {-1, -1};\n                dispatched_cnt++;\n                // update next expected for this row\n                for (int c = N * i; c < N * (i + 1); ++c) {\n                    if (!dispatched[c]) {\n                        next_exp[i] = c;\n                        break;\n                    }\n                }\n            }\n        }\n\n        if (dispatched_cnt == N * N) break;\n    }\n\n    // output\n    for (int i = 0; i < N; ++i)\n        cout << ans[i] << endl;\n\n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <cassert>\n\nusing namespace std;\n\nstruct Square {\n    int x, y, h;\n};\n\ninline int manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\npair<long long, bool> evaluate(const vector<int>& perm, const vector<Square>& squares) {\n    long long total_steps = 0;\n    long long load_dist = 0;\n    int load = 0;\n    int cur_x = 0, cur_y = 0;\n    bool feasible = true;\n\n    for (int idx : perm) {\n        const Square& sq = squares[idx];\n        int d = manhattan(cur_x, cur_y, sq.x, sq.y);\n        total_steps += d;\n        load_dist += (long long)load * d;\n\n        load += sq.h;\n        if (load < 0) {\n            feasible = false;\n            break;\n        }\n\n        cur_x = sq.x;\n        cur_y = sq.y;\n    }\n\n    if (load != 0) feasible = false;\n\n    long long cost_without_base = 100 * total_steps + load_dist;\n    return {cost_without_base, feasible};\n}\n\nvector<int> greedy_permutation(const vector<Square>& squares, mt19937& rng) {\n    int M = squares.size();\n    vector<bool> used(M, false);\n    vector<int> perm;\n    int cur_x = 0, cur_y = 0;\n    int load = 0;\n    int remaining = M;\n\n    while (remaining > 0) {\n        vector<int> candidates;\n        int best_dist = 1e9;\n\n        for (int i = 0; i < M; ++i) {\n            if (used[i]) continue;\n            const Square& sq = squares[i];\n            bool feasible = false;\n            if (sq.h > 0) {\n                feasible = true;\n            } else {\n                if (load >= -sq.h) feasible = true;\n            }\n            if (!feasible) continue;\n            int d = manhattan(cur_x, cur_y, sq.x, sq.y);\n            if (d < best_dist) {\n                best_dist = d;\n                candidates.clear();\n                candidates.push_back(i);\n            } else if (d == best_dist) {\n                candidates.push_back(i);\n            }\n        }\n\n        assert(!candidates.empty());\n        uniform_int_distribution<int> dist(0, candidates.size()-1);\n        int best_idx = candidates[dist(rng)];\n\n        used[best_idx] = true;\n        perm.push_back(best_idx);\n        cur_x = squares[best_idx].x;\n        cur_y = squares[best_idx].y;\n        load += squares[best_idx].h;\n        --remaining;\n    }\n\n    return perm;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<vector<int>> h(N, vector<int>(N));\n    long long base = 0;\n    vector<Square> squares;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> h[i][j];\n            if (h[i][j] != 0) {\n                squares.push_back({i, j, h[i][j]});\n                base += abs(h[i][j]);\n            }\n        }\n    }\n\n    int M = squares.size();\n    if (M == 0) {\n        return 0;\n    }\n\n    random_device rd;\n    mt19937 rng(rd());\n    uniform_real_distribution<double> uni(0.0, 1.0);\n    uniform_int_distribution<int> rand_idx(0, M-1);\n\n    // SA parameters\n    const int MAX_ITER = 800000;\n    const int RESTART_INTERVAL = 100000;\n    double start_temp = 5000.0;\n    double end_temp = 1e-4;\n    double cooling = exp(log(end_temp / start_temp) / MAX_ITER);\n\n    vector<int> best_perm;\n    long long best_cost = 1e18;\n\n    // initial solution\n    vector<int> cur_perm = greedy_permutation(squares, rng);\n    auto [init_cost, feasible_init] = evaluate(cur_perm, squares);\n    assert(feasible_init);\n    best_perm = cur_perm;\n    best_cost = init_cost;\n    long long cur_cost = init_cost;\n\n    for (int iter = 0; iter < MAX_ITER; ++iter) {\n        // periodic restart\n        if (iter % RESTART_INTERVAL == 0 && iter > 0) {\n            cur_perm = greedy_permutation(squares, rng);\n            auto [cost, feasible] = evaluate(cur_perm, squares);\n            if (feasible) {\n                cur_cost = cost;\n                if (cur_cost < best_cost) {\n                    best_perm = cur_perm;\n                    best_cost = cur_cost;\n                }\n            }\n        }\n\n        double T = start_temp * pow(cooling, iter);\n        vector<int> new_perm = cur_perm;\n        double move_type = uni(rng);\n\n        if (move_type < 0.33) {\n            // swap two random positions\n            int i = rand_idx(rng);\n            int j = rand_idx(rng);\n            if (i != j) swap(new_perm[i], new_perm[j]);\n        } else if (move_type < 0.66) {\n            // reverse a random segment\n            int i = rand_idx(rng);\n            int j = rand_idx(rng);\n            if (i > j) swap(i, j);\n            reverse(new_perm.begin() + i, new_perm.begin() + j + 1);\n        } else {\n            // move a random element to another random position\n            int i = rand_idx(rng);\n            int j = rand_idx(rng);\n            if (i != j) {\n                int val = new_perm[i];\n                new_perm.erase(new_perm.begin() + i);\n                if (j > i) --j;\n                new_perm.insert(new_perm.begin() + j, val);\n            }\n        }\n\n        auto [new_cost, feasible] = evaluate(new_perm, squares);\n        if (!feasible) continue;\n\n        if (new_cost < cur_cost || uni(rng) < exp((cur_cost - new_cost) / T)) {\n            cur_perm = new_perm;\n            cur_cost = new_cost;\n            if (cur_cost < best_cost) {\n                best_perm = cur_perm;\n                best_cost = cur_cost;\n            }\n        }\n    }\n\n    // Output operations\n    int cur_x = 0, cur_y = 0, load = 0;\n    for (int idx : best_perm) {\n        const Square& sq = squares[idx];\n        while (cur_y < sq.y) { cout << \"R\\n\"; ++cur_y; }\n        while (cur_y > sq.y) { cout << \"L\\n\"; --cur_y; }\n        while (cur_x < sq.x) { cout << \"D\\n\"; ++cur_x; }\n        while (cur_x > sq.x) { cout << \"U\\n\"; --cur_x; }\n\n        if (sq.h > 0) {\n            cout << \"+\" << sq.h << \"\\n\";\n            load += sq.h;\n        } else {\n            cout << \"-\" << -sq.h << \"\\n\";\n            load += sq.h;\n        }\n    }\n\n    return 0;\n}","ahc035":"#include <cstdio>\n#include <vector>\n#include <array>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n#include <set>\n\nusing namespace std;\n\nconst int N = 6;\nconst int M = 15;\nconst int T = 10;\nconst int SEED_COUNT = 2 * N * (N - 1); // 60\n\nusing Seed = array<int, M>;\n\n// Complementarity score: sum of max values per attribute\nint complementarity(const Seed& a, const Seed& b) {\n    int res = 0;\n    for (int l = 0; l < M; ++l) {\n        res += max(a[l], b[l]);\n    }\n    return res;\n}\n\n// Select seeds with diversity and high potential\nvector<int> select_seeds(const vector<Seed>& seeds, const vector<int>& sums) {\n    vector<int> selected;\n    vector<bool> used(SEED_COUNT, false);\n    \n    // First, take top 10 by sum (high value seeds)\n    vector<int> by_sum(SEED_COUNT);\n    iota(by_sum.begin(), by_sum.end(), 0);\n    sort(by_sum.begin(), by_sum.end(), [&](int a, int b) { return sums[a] > sums[b]; });\n    \n    for (int i = 0; i < 10 && i < SEED_COUNT; ++i) {\n        selected.push_back(by_sum[i]);\n        used[by_sum[i]] = true;\n    }\n    \n    // Then add seeds that are complementary to existing ones\n    while (selected.size() < 36) {\n        int best_seed = -1;\n        int best_score = -1;\n        \n        for (int i = 0; i < SEED_COUNT; ++i) {\n            if (used[i]) continue;\n            \n            // Score: sum of complementarity with all selected seeds\n            int score = 0;\n            for (int s : selected) {\n                score += complementarity(seeds[i], seeds[s]);\n            }\n            score /= selected.size(); // Normalize by number of selected\n            \n            // Add a bonus for high individual sum\n            score += sums[i] / 10;\n            \n            if (score > best_score) {\n                best_score = score;\n                best_seed = i;\n            }\n        }\n        \n        if (best_seed != -1) {\n            selected.push_back(best_seed);\n            used[best_seed] = true;\n        } else {\n            break;\n        }\n    }\n    \n    // If we still need more, add by highest sum\n    if (selected.size() < 36) {\n        for (int i = 0; i < SEED_COUNT && selected.size() < 36; ++i) {\n            if (!used[i]) {\n                selected.push_back(i);\n                used[i] = true;\n            }\n        }\n    }\n    \n    return selected;\n}\n\n// Place seeds to maximize good pairings\nvoid place_seeds(const vector<Seed>& seeds, const vector<int>& sums, \n                 const vector<int>& selected, vector<vector<int>>& grid) {\n    // We'll use a greedy approach considering complementarity\n    vector<bool> used(SEED_COUNT, false);\n    for (int s : selected) used[s] = true;\n    \n    // Start with the highest sum seed in the center\n    vector<int> selected_copy = selected;\n    sort(selected_copy.begin(), selected_copy.end(), [&](int a, int b) { \n        return sums[a] > sums[b]; \n    });\n    \n    // Place highest sum seeds in interior cells first\n    vector<pair<int, int>> interior_cells;\n    vector<pair<int, int>> border_cells;\n    \n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            bool is_interior = (i > 0 && i < N-1 && j > 0 && j < N-1);\n            if (is_interior) {\n                interior_cells.push_back({i, j});\n            } else {\n                border_cells.push_back({i, j});\n            }\n        }\n    }\n    \n    // Place top seeds in interior\n    for (int i = 0; i < interior_cells.size() && i < selected_copy.size(); ++i) {\n        auto [r, c] = interior_cells[i];\n        grid[r][c] = selected_copy[i];\n    }\n    \n    // Fill remaining cells with remaining seeds\n    vector<int> remaining_seeds;\n    for (int s : selected_copy) {\n        bool placed = false;\n        for (int i = 0; i < N && !placed; ++i) {\n            for (int j = 0; j < N && !placed; ++j) {\n                if (grid[i][j] == s) {\n                    placed = true;\n                }\n            }\n        }\n        if (!placed) {\n            remaining_seeds.push_back(s);\n        }\n    }\n    \n    // Place border seeds\n    for (int i = 0; i < border_cells.size() && !remaining_seeds.empty(); ++i) {\n        auto [r, c] = border_cells[i];\n        grid[r][c] = remaining_seeds.back();\n        remaining_seeds.pop_back();\n    }\n    \n    // Fill any remaining empty cells\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] == -1 && !remaining_seeds.empty()) {\n                grid[i][j] = remaining_seeds.back();\n                remaining_seeds.pop_back();\n            }\n        }\n    }\n    \n    // Now optimize placement by swapping to increase complementarity\n    for (int iter = 0; iter < 100; ++iter) {\n        bool improved = false;\n        \n        for (int i1 = 0; i1 < N; ++i1) {\n            for (int j1 = 0; j1 < N; ++j1) {\n                for (int i2 = 0; i2 < N; ++i2) {\n                    for (int j2 = 0; j2 < N; ++j2) {\n                        if (i1 == i2 && j1 == j2) continue;\n                        \n                        // Calculate current complementarity for neighbors of both cells\n                        auto get_neighbors = [&](int i, int j) {\n                            vector<pair<int, int>> neighbors;\n                            if (i > 0) neighbors.push_back({i-1, j});\n                            if (i < N-1) neighbors.push_back({i+1, j});\n                            if (j > 0) neighbors.push_back({i, j-1});\n                            if (j < N-1) neighbors.push_back({i, j+1});\n                            return neighbors;\n                        };\n                        \n                        auto neighbors1 = get_neighbors(i1, j1);\n                        auto neighbors2 = get_neighbors(i2, j2);\n                        \n                        int current_score = 0;\n                        for (auto [ni, nj] : neighbors1) {\n                            current_score += complementarity(seeds[grid[i1][j1]], seeds[grid[ni][nj]]);\n                        }\n                        for (auto [ni, nj] : neighbors2) {\n                            current_score += complementarity(seeds[grid[i2][j2]], seeds[grid[ni][nj]]);\n                        }\n                        \n                        // Try swapping\n                        swap(grid[i1][j1], grid[i2][j2]);\n                        \n                        int new_score = 0;\n                        for (auto [ni, nj] : neighbors1) {\n                            new_score += complementarity(seeds[grid[i1][j1]], seeds[grid[ni][nj]]);\n                        }\n                        for (auto [ni, nj] : neighbors2) {\n                            new_score += complementarity(seeds[grid[i2][j2]], seeds[grid[ni][nj]]);\n                        }\n                        \n                        if (new_score > current_score) {\n                            improved = true;\n                        } else {\n                            swap(grid[i1][j1], grid[i2][j2]);\n                        }\n                    }\n                }\n            }\n        }\n        \n        if (!improved) break;\n    }\n}\n\nint main() {\n    vector<Seed> seeds(SEED_COUNT);\n    vector<int> sums(SEED_COUNT);\n    \n    // Read initial seeds\n    for (int i = 0; i < SEED_COUNT; ++i) {\n        for (int j = 0; j < M; ++j) {\n            scanf(\"%d\", &seeds[i][j]);\n        }\n        sums[i] = accumulate(seeds[i].begin(), seeds[i].end(), 0);\n    }\n    \n    for (int t = 0; t < T; ++t) {\n        // Select seeds\n        vector<int> selected = select_seeds(seeds, sums);\n        \n        // Place seeds\n        vector<vector<int>> grid(N, vector<int>(N, -1));\n        place_seeds(seeds, sums, selected, grid);\n        \n        // Output the grid\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                printf(\"%d\", grid[i][j]);\n                if (j < N - 1) printf(\" \");\n                else printf(\"\\n\");\n            }\n        }\n        fflush(stdout);\n        \n        // Read new seeds\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            for (int j = 0; j < M; ++j) {\n                scanf(\"%d\", &seeds[i][j]);\n            }\n            sums[i] = accumulate(seeds[i].begin(), seeds[i].end(), 0);\n        }\n    }\n    \n    return 0;\n}","ahc038":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <string>\n#include <cmath>\n#include <cassert>\n#include <climits>\n\nusing namespace std;\n\nstruct Point {\n    int x, y;\n    Point(int x = 0, int y = 0) : x(x), y(y) {}\n    bool operator==(const Point& other) const {\n        return x == other.x && y == other.y;\n    }\n};\n\nint manhattan(const Point& a, const Point& b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\nint N, M, V_arm; // V_arm = number of vertices in the arm (given V)\nvector<string> s_grid, t_grid;\nvector<Point> pickups;   // initial positions that need to be moved\nvector<Point> dropoffs;  // target positions that need to be filled\n\n// current state of the robotic arm\nPoint root;                     // current root position\nvector<int> cur_dir;            // current directions of edges (size = V_arm-1)\nvector<string> output_turns;    // sequence of operation strings\n\n// direction vectors: 0:right, 1:down, 2:left, 3:up\nconst int dx_dir[4] = {0, 1, 0, -1};\nconst int dy_dir[4] = {1, 0, -1, 0};\n\n// Helper: for a given cell, find the root position and offset (dx,dy) with Manhattan distance D\n// that minimizes distance from current root.\npair<Point, Point> find_best_root_offset(const Point& cell, const Point& cur_root, int D) {\n    int best_dist = INT_MAX;\n    Point best_root, best_offset;\n    for (int dx = -D; dx <= D; ++dx) {\n        int abs_dx = abs(dx);\n        int abs_dy = D - abs_dx;\n        for (int dy_sign : {1, -1}) {\n            int dy = dy_sign * abs_dy;\n            Point cand_root(cell.x - dx, cell.y - dy);\n            if (cand_root.x >= 0 && cand_root.x < N &&\n                cand_root.y >= 0 && cand_root.y < N) {\n                int dist = manhattan(cur_root, cand_root);\n                if (dist < best_dist) {\n                    best_dist = dist;\n                    best_root = cand_root;\n                    best_offset = Point(dx, dy);\n                }\n            }\n        }\n    }\n    return {best_root, best_offset};\n}\n\n// Move the root step by step to target_root, outputting moves.\nvoid move_to(const Point& target_root) {\n    while (root.x != target_root.x || root.y != target_root.y) {\n        char move_char = '.';\n        if (root.x < target_root.x) {\n            move_char = 'D';\n            root.x++;\n        } else if (root.x > target_root.x) {\n            move_char = 'U';\n            root.x--;\n        } else if (root.y < target_root.y) {\n            move_char = 'R';\n            root.y++;\n        } else if (root.y > target_root.y) {\n            move_char = 'L';\n            root.y--;\n        }\n        string turn(2 * V_arm, '.');\n        turn[0] = move_char;\n        output_turns.push_back(turn);\n    }\n}\n\n// Change the offset to (tx,ty) and perform action act ('P' for grab/release, '.' otherwise).\n// The function may output one or two turns.\nvoid change_offset_and_act(int tx, int ty, char act) {\n    int D = V_arm - 1; // number of edges\n    int H = abs(ty);   // number of horizontal edges needed\n    int V_edges = D - H; // = abs(tx)\n\n    int hor_sign = (ty > 0) ? 0 : 2; // 0:right, 2:left\n    int ver_sign = (tx > 0) ? 1 : 3; // 1:down, 3:up\n\n    // Compute target directions for each edge with min-cost assignment\n    vector<int> target_dir(D, 0);\n    vector<int> cost_hor(D), cost_ver(D);\n    for (int i = 0; i < D; ++i) {\n        int d = cur_dir[i];\n        cost_hor[i] = min(abs(d - hor_sign), 4 - abs(d - hor_sign));\n        cost_ver[i] = min(abs(d - ver_sign), 4 - abs(d - ver_sign));\n    }\n\n    vector<pair<int, int>> diff; // (cost_hor - cost_ver, index)\n    for (int i = 0; i < D; ++i) {\n        diff.emplace_back(cost_hor[i] - cost_ver[i], i);\n    }\n    sort(diff.begin(), diff.end());\n\n    vector<bool> is_hor(D, false);\n    for (int i = 0; i < H; ++i) {\n        is_hor[diff[i].second] = true;\n    }\n    for (int i = 0; i < D; ++i) {\n        if (is_hor[i])\n            target_dir[i] = hor_sign;\n        else\n            target_dir[i] = ver_sign;\n    }\n\n    // Compute required rotations (number of clockwise 90\u00b0 steps)\n    vector<int> need(D);\n    for (int i = 0; i < D; ++i) {\n        need[i] = (target_dir[i] - cur_dir[i] + 4) % 4;\n    }\n\n    bool has_180 = false;\n    for (int i = 0; i < D; ++i) {\n        if (need[i] == 2) {\n            has_180 = true;\n            break;\n        }\n    }\n\n    auto make_rotation_string = [&](bool final_turn) -> string {\n        string rot(D, '.');\n        for (int i = 0; i < D; ++i) {\n            if (need[i] == 0) rot[i] = '.';\n            else if (need[i] == 1) rot[i] = 'R';\n            else if (need[i] == 2) {\n                rot[i] = 'R'; // one rotation now, another later if needed\n            }\n            else if (need[i] == 3) rot[i] = 'L';\n        }\n        return rot;\n    };\n\n    if (!has_180) {\n        // One turn is enough\n        string rot_str = make_rotation_string(true);\n        // Update cur_dir\n        for (int i = 0; i < D; ++i) {\n            if (need[i] == 1) cur_dir[i] = (cur_dir[i] + 1) % 4;\n            else if (need[i] == 3) cur_dir[i] = (cur_dir[i] + 3) % 4;\n        }\n        // Build turn string\n        string turn(2 * V_arm, '.');\n        turn[0] = '.'; // no move\n        for (int i = 0; i < D; ++i) turn[1 + i] = rot_str[i];\n        if (act == 'P') turn[2 * V_arm - 1] = 'P'; // fingertip action at vertex V_arm-1\n        output_turns.push_back(turn);\n    } else {\n        // Need two turns\n        // First turn: rotate once where needed\n        string rot_str1 = make_rotation_string(false);\n        // Update cur_dir after first rotation\n        for (int i = 0; i < D; ++i) {\n            if (need[i] == 1 || need[i] == 2) cur_dir[i] = (cur_dir[i] + 1) % 4;\n            else if (need[i] == 3) cur_dir[i] = (cur_dir[i] + 3) % 4;\n        }\n        // Build first turn\n        string turn1(2 * V_arm, '.');\n        turn1[0] = '.';\n        for (int i = 0; i < D; ++i) turn1[1 + i] = rot_str1[i];\n        output_turns.push_back(turn1);\n\n        // Second turn: rotate the remaining 180\u00b0 edges\n        vector<int> need2(D, 0);\n        for (int i = 0; i < D; ++i) {\n            if (need[i] == 2) need2[i] = 1;\n        }\n        string rot_str2(D, '.');\n        for (int i = 0; i < D; ++i) {\n            if (need2[i] == 1) rot_str2[i] = 'R';\n        }\n        // Update cur_dir\n        for (int i = 0; i < D; ++i) {\n            if (need2[i] == 1) cur_dir[i] = (cur_dir[i] + 1) % 4;\n        }\n        string turn2(2 * V_arm, '.');\n        turn2[0] = '.';\n        for (int i = 0; i < D; ++i) turn2[1 + i] = rot_str2[i];\n        if (act == 'P') turn2[2 * V_arm - 1] = 'P';\n        output_turns.push_back(turn2);\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Read input\n    cin >> N >> M >> V_arm;\n    s_grid.resize(N);\n    t_grid.resize(N);\n    for (int i = 0; i < N; ++i) cin >> s_grid[i];\n    for (int i = 0; i < N; ++i) cin >> t_grid[i];\n\n    // Determine pickups and dropoffs\n    vector<vector<bool>> is_target(N, vector<bool>(N, false));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (t_grid[i][j] == '1') is_target[i][j] = true;\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (s_grid[i][j] == '1') {\n                if (is_target[i][j]) {\n                    // Already at a target, mark both as done\n                    is_target[i][j] = false;\n                } else {\n                    pickups.emplace_back(i, j);\n                }\n            }\n        }\n    }\n\n    // The remaining targets are dropoffs\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (is_target[i][j]) {\n                dropoffs.emplace_back(i, j);\n            }\n        }\n    }\n\n    // Design the arm: a chain of V_arm vertices, edges of length 1\n    cout << V_arm << '\\n';\n    for (int i = 1; i < V_arm; ++i) {\n        cout << i-1 << \" 1\\n\";\n    }\n\n    // Initial root position (0,0)\n    root = Point(0, 0);\n    cout << root.x << ' ' << root.y << '\\n';\n\n    // Initialize edge directions (all right)\n    cur_dir.assign(V_arm - 1, 0);\n\n    int D = V_arm - 1; // total length of the arm\n\n    // Process each takoyaki\n    while (!pickups.empty()) {\n        // Find the closest pickup\n        int best_pickup_idx = -1;\n        int best_pickup_dist = INT_MAX;\n        Point best_pickup_root, best_pickup_offset;\n        for (int idx = 0; idx < (int)pickups.size(); ++idx) {\n            auto [cand_root, cand_offset] = find_best_root_offset(pickups[idx], root, D);\n            int dist = manhattan(root, cand_root);\n            if (dist < best_pickup_dist) {\n                best_pickup_dist = dist;\n                best_pickup_idx = idx;\n                best_pickup_root = cand_root;\n                best_pickup_offset = cand_offset;\n            }\n        }\n\n        // Move to the pickup root position\n        move_to(best_pickup_root);\n        // Change offset and grab\n        change_offset_and_act(best_pickup_offset.x, best_pickup_offset.y, 'P');\n        // Remove the pickup from the list\n        pickups.erase(pickups.begin() + best_pickup_idx);\n\n        // Find the closest dropoff\n        int best_dropoff_idx = -1;\n        int best_dropoff_dist = INT_MAX;\n        Point best_dropoff_root, best_dropoff_offset;\n        for (int idx = 0; idx < (int)dropoffs.size(); ++idx) {\n            auto [cand_root, cand_offset] = find_best_root_offset(dropoffs[idx], root, D);\n            int dist = manhattan(root, cand_root);\n            if (dist < best_dropoff_dist) {\n                best_dropoff_dist = dist;\n                best_dropoff_idx = idx;\n                best_dropoff_root = cand_root;\n                best_dropoff_offset = cand_offset;\n            }\n        }\n\n        // Move to the dropoff root position\n        move_to(best_dropoff_root);\n        // Change offset and release\n        change_offset_and_act(best_dropoff_offset.x, best_dropoff_offset.y, 'P');\n        // Remove the dropoff from the list\n        dropoffs.erase(dropoffs.begin() + best_dropoff_idx);\n    }\n\n    // Output all turns\n    for (const string& turn : output_turns) {\n        cout << turn << '\\n';\n    }\n\n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <cmath>\n#include <queue>\n\nusing namespace std;\n\nstruct Point {\n    int x, y, w;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    cin >> N;\n    \n    vector<Point> mackerels(N), sardines(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> mackerels[i].x >> mackerels[i].y;\n        mackerels[i].w = 1;\n    }\n    for (int i = 0; i < N; ++i) {\n        cin >> sardines[i].x >> sardines[i].y;\n        sardines[i].w = -1;\n    }\n    \n    // Create a coarse grid (100x100 cells)\n    const int GRID_SIZE = 100;\n    const int CELL_SIZE = 1000; // 100000 / 100 = 1000\n    \n    vector<vector<int>> grid(GRID_SIZE, vector<int>(GRID_SIZE, 0));\n    \n    // Fill grid with net benefit (mackerels - sardines)\n    for (const auto& p : mackerels) {\n        int gx = min(p.x / CELL_SIZE, GRID_SIZE - 1);\n        int gy = min(p.y / CELL_SIZE, GRID_SIZE - 1);\n        grid[gx][gy]++;\n    }\n    for (const auto& p : sardines) {\n        int gx = min(p.x / CELL_SIZE, GRID_SIZE - 1);\n        int gy = min(p.y / CELL_SIZE, GRID_SIZE - 1);\n        grid[gx][gy]--;\n    }\n    \n    // Find the cell with highest net benefit as starting point\n    int best_gx = 0, best_gy = 0;\n    int best_cell_score = grid[0][0];\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            if (grid[i][j] > best_cell_score) {\n                best_cell_score = grid[i][j];\n                best_gx = i;\n                best_gy = j;\n            }\n        }\n    }\n    \n    // BFS to expand from the best cell\n    vector<vector<bool>> visited(GRID_SIZE, vector<bool>(GRID_SIZE, false));\n    queue<pair<int, int>> q;\n    q.push({best_gx, best_gy});\n    visited[best_gx][best_gy] = true;\n    \n    vector<pair<int, int>> region;\n    region.push_back({best_gx, best_gy});\n    \n    int total_score = best_cell_score;\n    const int dx[] = {1, -1, 0, 0};\n    const int dy[] = {0, 0, 1, -1};\n    \n    // Expand region while it improves the score\n    while (!q.empty()) {\n        auto [x, y] = q.front();\n        q.pop();\n        \n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            \n            if (nx >= 0 && nx < GRID_SIZE && ny >= 0 && ny < GRID_SIZE && !visited[nx][ny]) {\n                if (grid[nx][ny] > 0) {  // Only add if positive contribution\n                    visited[nx][ny] = true;\n                    q.push({nx, ny});\n                    region.push_back({nx, ny});\n                    total_score += grid[nx][ny];\n                }\n            }\n        }\n    }\n    \n    // Find bounding box of the region\n    int min_gx = GRID_SIZE, max_gx = -1, min_gy = GRID_SIZE, max_gy = -1;\n    for (const auto& [gx, gy] : region) {\n        min_gx = min(min_gx, gx);\n        max_gx = max(max_gx, gx);\n        min_gy = min(min_gy, gy);\n        max_gy = max(max_gy, gy);\n    }\n    \n    // Convert back to original coordinates\n    int left = min_gx * CELL_SIZE;\n    int right = (max_gx + 1) * CELL_SIZE;\n    int bottom = min_gy * CELL_SIZE;\n    int top = (max_gy + 1) * CELL_SIZE;\n    \n    // Ensure within bounds\n    left = max(0, left);\n    right = min(100000, right);\n    bottom = max(0, bottom);\n    top = min(100000, top);\n    \n    // Output rectangle\n    cout << \"4\\n\";\n    cout << left << \" \" << bottom << \"\\n\";\n    cout << right << \" \" << bottom << \"\\n\";\n    cout << right << \" \" << top << \"\\n\";\n    cout << left << \" \" << top << \"\\n\";\n    \n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <tuple>\n\nusing namespace std;\n\nconst double p_place = 0.9; // probability to attempt placing a rectangle\n\nstruct Rectangle {\n    int x, y, w, h;\n    int right() const { return x + w; }\n    int bottom() const { return y + h; }\n};\n\n// Compute y0 for U placement given left edge x0 and width\nint compute_y0(int x0, int width, const vector<int>& placed_indices, const Rectangle rect_of_index[]) {\n    int y0 = 0;\n    for (int idx : placed_indices) {\n        const Rectangle& R = rect_of_index[idx];\n        if (x0 < R.right() && x0 + width > R.x) {\n            y0 = max(y0, R.bottom());\n        }\n    }\n    return y0;\n}\n\n// Compute x0 for L placement given top edge y0 and height\nint compute_x0(int y0, int height, const vector<int>& placed_indices, const Rectangle rect_of_index[]) {\n    int x0 = 0;\n    for (int idx : placed_indices) {\n        const Rectangle& R = rect_of_index[idx];\n        if (y0 < R.bottom() && y0 + height > R.y) {\n            x0 = max(x0, R.right());\n        }\n    }\n    return x0;\n}\n\nvoid solve_turn(int turn, const vector<int>& w, const vector<int>& h, int N, mt19937& rng) {\n    vector<int> placed_indices;          // indices of placed rectangles\n    Rectangle rect_of_index[N];          // stores rectangle data when placed\n    bool is_placed[N] = {false};\n    int W = 0, H = 0;                    // current bounding box\n\n    vector<tuple<int, int, char, int>> ops; // (p, r, d, b)\n\n    uniform_real_distribution<double> dist_real(0.0, 1.0);\n    uniform_int_distribution<int> dist_binary(0, 1);\n\n    for (int i = 0; i < N; ++i) {\n        // Decide whether to attempt placement\n        if (dist_real(rng) >= p_place) continue;\n\n        // Choose random rotation and direction\n        int r = dist_binary(rng);\n        char d = (dist_binary(rng) == 0) ? 'U' : 'L';\n        int width = (r == 0) ? w[i] : h[i];\n        int height = (r == 0) ? h[i] : w[i];\n\n        // Find best reference b for the chosen d, r\n        int best_b = -1;\n        int best_newW = W, best_newH = H;\n        int best_score = -1;\n\n        // List of possible b: -1 and all placed indices\n        vector<int> b_candidates = {-1};\n        for (int idx : placed_indices) b_candidates.push_back(idx);\n\n        for (int b : b_candidates) {\n            int x0, y0;\n            if (d == 'U') {\n                x0 = (b == -1) ? 0 : rect_of_index[b].right();\n                y0 = compute_y0(x0, width, placed_indices, rect_of_index);\n            } else { // 'L'\n                y0 = (b == -1) ? 0 : rect_of_index[b].bottom();\n                x0 = compute_x0(y0, height, placed_indices, rect_of_index);\n            }\n            int newW = max(W, x0 + width);\n            int newH = max(H, y0 + height);\n            int score = newW + newH;\n            if (best_b == -1 || score < best_score) {\n                best_b = b;\n                best_score = score;\n                best_newW = newW;\n                best_newH = newH;\n            }\n        }\n\n        // Check if placing is beneficial (using measured dimensions)\n        if (best_score <= W + H + w[i] + h[i]) {\n            // Perform placement\n            int x0, y0;\n            if (d == 'U') {\n                x0 = (best_b == -1) ? 0 : rect_of_index[best_b].right();\n                y0 = compute_y0(x0, width, placed_indices, rect_of_index);\n            } else {\n                y0 = (best_b == -1) ? 0 : rect_of_index[best_b].bottom();\n                x0 = compute_x0(y0, height, placed_indices, rect_of_index);\n            }\n            // Update state\n            rect_of_index[i] = {x0, y0, width, height};\n            is_placed[i] = true;\n            placed_indices.push_back(i);\n            W = best_newW;\n            H = best_newH;\n            ops.emplace_back(i, r, d, best_b);\n        }\n    }\n\n    // Output operations\n    cout << ops.size() << '\\n';\n    for (auto [p, r, d, b] : ops) {\n        cout << p << ' ' << r << ' ' << d << ' ' << b << '\\n';\n    }\n    cout.flush();\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T, sigma;\n    cin >> N >> T >> sigma;\n    vector<int> w(N), h(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> w[i] >> h[i];\n    }\n\n    // Random number generator\n    random_device rd;\n    mt19937 rng(rd());\n\n    for (int t = 0; t < T; ++t) {\n        solve_turn(t, w, h, N, rng);\n        // Read measured box dimensions (not used in this simple strategy)\n        int Wp, Hp;\n        cin >> Wp >> Hp;\n    }\n\n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <random>\n#include <cmath>\n#include <numeric>\n#include <chrono>\nusing namespace std;\n\nint N, H;\nvector<vector<int>> adj;\nvector<int> A;\n\n// Check if changing vertex v to newd is feasible (without modifying state)\nbool can_change(int v, int newd, const vector<int>& depth) {\n    // check v itself if newd > 0\n    if (newd > 0) {\n        bool has = false;\n        for (int u : adj[v]) {\n            if (depth[u] == newd - 1) {\n                has = true;\n                break;\n            }\n        }\n        if (!has) return false;\n    }\n    // check all neighbours\n    for (int u : adj[v]) {\n        if (depth[u] == 0) continue; // root has no constraint\n        bool has = false;\n        for (int w : adj[u]) {\n            int d_w = (w == v) ? newd : depth[w];\n            if (d_w == depth[u] - 1) {\n                has = true;\n                break;\n            }\n        }\n        if (!has) return false;\n    }\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    cin >> N >> M >> H;\n    A.resize(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n    adj.resize(N);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n    // read coordinates (unused)\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // ---------- 1. Compute H-neighborhoods ----------\n    vector<vector<int>> cover(N);\n    for (int v = 0; v < N; ++v) {\n        vector<int> dist(N, -1);\n        queue<int> q;\n        dist[v] = 0;\n        q.push(v);\n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            if (dist[u] > H) continue;\n            cover[v].push_back(u);\n            if (dist[u] == H) continue;\n            for (int w : adj[u]) {\n                if (dist[w] == -1) {\n                    dist[w] = dist[u] + 1;\n                    q.push(w);\n                }\n            }\n        }\n    }\n\n    // ---------- 2. Greedy set cover to choose roots ----------\n    vector<bool> covered(N, false);\n    vector<int> roots;\n    int remaining = N;\n    while (remaining > 0) {\n        int best_v = -1, best_cnt = -1;\n        for (int v = 0; v < N; ++v) {\n            int cnt = 0;\n            for (int u : cover[v]) if (!covered[u]) cnt++;\n            if (cnt > best_cnt || (cnt == best_cnt && (best_v == -1 || A[v] < A[best_v]))) {\n                best_cnt = cnt;\n                best_v = v;\n            }\n        }\n        roots.push_back(best_v);\n        for (int u : cover[best_v]) if (!covered[u]) {\n            covered[u] = true;\n            --remaining;\n        }\n    }\n\n    // ---------- 3. Multi-source BFS to get initial depths ----------\n    vector<int> depth(N, -1);\n    queue<int> q;\n    for (int r : roots) {\n        depth[r] = 0;\n        q.push(r);\n    }\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (int v : adj[u]) {\n            if (depth[v] == -1) {\n                depth[v] = depth[u] + 1;\n                q.push(v);\n            }\n        }\n    }\n    long long cur_obj = 0;\n    for (int v = 0; v < N; ++v) cur_obj += depth[v] * A[v];\n\n    // ---------- 4. Simulated Annealing ----------\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> rand_v(0, N-1);\n    uniform_int_distribution<int> rand_d(0, H);\n    uniform_real_distribution<double> rand_float(0.0, 1.0);\n\n    const int ITER = 1500000;\n    double temp = 1000.0;\n    const double cooling = 0.999995;\n\n    for (int iter = 0; iter < ITER; ++iter) {\n        int v = rand_v(rng);\n        int oldd = depth[v];\n        int newd = rand_d(rng);\n        if (newd == oldd) continue;\n        int delta = (newd - oldd) * A[v];\n\n        // feasibility check\n        if (!can_change(v, newd, depth)) continue;\n\n        // SA acceptance\n        if (delta >= 0 || rand_float(rng) < exp(delta / temp)) {\n            depth[v] = newd;\n            cur_obj += delta;\n        }\n        temp *= cooling;\n    }\n\n    // ---------- 5. Greedy improvement (high beauty first) ----------\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    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int v : order) {\n            while (depth[v] < H) {\n                int newd = depth[v] + 1;\n                if (can_change(v, newd, depth)) {\n                    depth[v] = newd;\n                    cur_obj += A[v];\n                    improved = true;\n                } else {\n                    break;\n                }\n            }\n        }\n    }\n\n    // ---------- 6. Build parent pointers ----------\n    vector<int> parent(N, -1);\n    for (int v = 0; v < N; ++v) {\n        if (depth[v] == 0) continue;\n        for (int u : adj[v]) {\n            if (depth[u] == depth[v] - 1) {\n                parent[v] = u;\n                break;\n            }\n        }\n    }\n\n    // ---------- 7. Output ----------\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << parent[i];\n    }\n    cout << endl;\n\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 20;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    int n;\n    cin >> n;\n    vector<string> board(n);\n    for (int i = 0; i < n; ++i) {\n        cin >> board[i];\n    }\n    \n    vector<vector<char>> grid(n, vector<char>(n));\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            grid[i][j] = board[i][j];\n        }\n    }\n    \n    auto is_safe = [&](int i, int j, int dir) -> bool {\n        if (dir == 0) { // up\n            for (int r = 0; r < i; ++r) {\n                if (grid[r][j] == 'o') return false;\n            }\n            return true;\n        } else if (dir == 1) { // down\n            for (int r = i+1; r < n; ++r) {\n                if (grid[r][j] == 'o') return false;\n            }\n            return true;\n        } else if (dir == 2) { // left\n            for (int c = 0; c < j; ++c) {\n                if (grid[i][c] == 'o') return false;\n            }\n            return true;\n        } else { // right\n            for (int c = j+1; c < n; ++c) {\n                if (grid[i][c] == 'o') return false;\n            }\n            return true;\n        }\n    };\n    \n    int total_ops = 0;\n    while (true) {\n        // Find all Oni\n        vector<pair<int,int>> oni_list;\n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                if (grid[i][j] == 'x') {\n                    oni_list.emplace_back(i, j);\n                }\n            }\n        }\n        if (oni_list.empty()) break;\n        \n        // Enumerate all possible operations and choose the best ratio\n        double best_ratio = -1.0;\n        int best_i = -1, best_j = -1, best_dir = -1, best_cost = 0, best_count = 0;\n        for (auto [i, j] : oni_list) {\n            for (int dir = 0; dir < 4; ++dir) {\n                if (!is_safe(i, j, dir)) continue;\n                \n                int cost;\n                if (dir == 0) cost = i + 1;\n                else if (dir == 1) cost = n - i;\n                else if (dir == 2) cost = j + 1;\n                else cost = n - j;\n                \n                int count = 0;\n                if (dir == 0) { // up\n                    for (int r = 0; r <= i; ++r) {\n                        if (grid[r][j] == 'x') count++;\n                    }\n                } else if (dir == 1) { // down\n                    for (int r = i; r < n; ++r) {\n                        if (grid[r][j] == 'x') count++;\n                    }\n                } else if (dir == 2) { // left\n                    for (int c = 0; c <= j; ++c) {\n                        if (grid[i][c] == 'x') count++;\n                    }\n                } else { // right\n                    for (int c = j; c < n; ++c) {\n                        if (grid[i][c] == 'x') count++;\n                    }\n                }\n                \n                double ratio = static_cast<double>(count) / cost;\n                if (ratio > best_ratio || (ratio == best_ratio && count > best_count)) {\n                    best_ratio = ratio;\n                    best_i = i;\n                    best_j = j;\n                    best_dir = dir;\n                    best_cost = cost;\n                    best_count = count;\n                }\n            }\n        }\n        \n        // Perform the best operation\n        if (best_dir == 0) { // up\n            int k = best_i + 1;\n            for (int t = 0; t < k; ++t) cout << \"U \" << best_j << \"\\n\";\n            for (int t = 0; t < k; ++t) cout << \"D \" << best_j << \"\\n\";\n            for (int r = 0; r <= best_i; ++r) grid[r][best_j] = '.';\n        } else if (best_dir == 1) { // down\n            int k = n - best_i;\n            for (int t = 0; t < k; ++t) cout << \"D \" << best_j << \"\\n\";\n            for (int t = 0; t < k; ++t) cout << \"U \" << best_j << \"\\n\";\n            for (int r = best_i; r < n; ++r) grid[r][best_j] = '.';\n        } else if (best_dir == 2) { // left\n            int k = best_j + 1;\n            for (int t = 0; t < k; ++t) cout << \"L \" << best_i << \"\\n\";\n            for (int t = 0; t < k; ++t) cout << \"R \" << best_i << \"\\n\";\n            for (int c = 0; c <= best_j; ++c) grid[best_i][c] = '.';\n        } else { // right\n            int k = n - best_j;\n            for (int t = 0; t < k; ++t) cout << \"R \" << best_i << \"\\n\";\n            for (int t = 0; t < k; ++t) cout << \"L \" << best_i << \"\\n\";\n            for (int c = best_j; c < n; ++c) grid[best_i][c] = '.';\n        }\n        total_ops += 2 * best_cost;\n    }\n    \n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, L;\n    cin >> N >> L;\n    vector<int> T(N);\n    for (int i = 0; i < N; ++i) cin >> T[i];\n\n    // Random generator\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    // ---------- Greedy initialization ----------\n    vector<int> a(N), b(N);\n    vector<int> need(N);\n    need[0] = max(0, T[0] - 1);   // employee 0 gets one initial visit\n    for (int i = 1; i < N; ++i) need[i] = T[i];\n\n    // Supplies: each employee i provides two edges with weights ceil(T_i/2) and floor(T_i/2)\n    vector<tuple<int, int, int>> supplies; // weight, employee i, type (0 for a, 1 for b)\n    for (int i = 0; i < N; ++i) {\n        int odd = (T[i] + 1) / 2;  // ceil(T_i/2)\n        int even = T[i] / 2;       // floor(T_i/2)\n        supplies.emplace_back(odd, i, 0);\n        supplies.emplace_back(even, i, 1);\n    }\n    // Sort supplies by weight descending\n    sort(supplies.begin(), supplies.end(),\n         [](const auto& x, const auto& y) { return get<0>(x) > get<0>(y); });\n\n    // Priority queue for demands (remaining need, employee j)\n    priority_queue<pair<int, int>> pq;\n    for (int j = 0; j < N; ++j) {\n        if (need[j] > 0) pq.emplace(need[j], j);\n    }\n\n    // Assign each supply to the current highest demand\n    for (const auto& [weight, i, type] : supplies) {\n        if (pq.empty()) break;\n        auto [rem, j] = pq.top();\n        pq.pop();\n        if (type == 0) a[i] = j;\n        else b[i] = j;\n        rem -= weight;\n        if (rem > 0) pq.emplace(rem, j);\n    }\n    // If any demand remains, it will be ignored (edges already assigned to some j, possibly 0)\n\n    // ---------- Build transition table ----------\n    // nxt[i][0] = b_i, nxt[i][1] = a_i\n    array<array<int, 2>, 100> nxt;\n    for (int i = 0; i < N; ++i) {\n        nxt[i][0] = b[i];\n        nxt[i][1] = a[i];\n    }\n\n    // ---------- Simulation function ----------\n    auto simulate = [&]() {\n        int cnt[100];\n        memset(cnt, 0, sizeof(cnt));\n        cnt[0] = 1;\n        int cur = 0;\n        int steps = L - 1;\n        while (steps--) {\n            int parity = cnt[cur] & 1;\n            int next_emp = nxt[cur][parity];\n            ++cnt[next_emp];\n            cur = next_emp;\n        }\n        int error = 0;\n        for (int i = 0; i < N; ++i) {\n            error += abs(cnt[i] - T[i]);\n        }\n        return error;\n    };\n\n    int cur_error = simulate();\n    int best_error = cur_error;\n    vector<int> best_a = a, best_b = b;\n\n    // ---------- Simulated Annealing ----------\n    double temp = 1000.0;\n    const double cooling = 0.998;\n    auto start_time = chrono::steady_clock::now();\n    const double time_limit = 1.9; // seconds\n    uniform_real_distribution<double> dist(0.0, 1.0);\n\n    int iter = 0;\n    while (true) {\n        if ((iter & 63) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > time_limit) break;\n        }\n        ++iter;\n\n        // Choose random edge\n        int i = rng() % N;\n        int type = rng() % 2; // 0 -> a_i, 1 -> b_i\n        int old_val = (type == 0) ? a[i] : b[i];\n        int new_val = rng() % N;\n        if (new_val == old_val) continue;\n\n        // Apply change\n        if (type == 0) {\n            a[i] = new_val;\n            nxt[i][1] = new_val;\n        } else {\n            b[i] = new_val;\n            nxt[i][0] = new_val;\n        }\n\n        int new_error = simulate();\n        int delta = new_error - cur_error;\n\n        bool accept = false;\n        if (delta < 0) {\n            accept = true;\n        } else {\n            double prob = exp(-delta / temp);\n            if (dist(rng) < prob) accept = true;\n        }\n\n        if (accept) {\n            cur_error = new_error;\n            if (cur_error < best_error) {\n                best_error = cur_error;\n                best_a = a;\n                best_b = b;\n                if (best_error == 0) break; // optimal\n            }\n        } else {\n            // Revert\n            if (type == 0) {\n                a[i] = old_val;\n                nxt[i][1] = old_val;\n            } else {\n                b[i] = old_val;\n                nxt[i][0] = old_val;\n            }\n        }\n\n        // Cool down\n        temp *= cooling;\n    }\n\n    // ---------- Output ----------\n    for (int i = 0; i < N; ++i) {\n        cout << best_a[i] << \" \" << best_b[i] << \"\\n\";\n    }\n\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\n#include <boost/geometry.hpp>\n#include <boost/geometry/index/rtree.hpp>\n\nnamespace bg = boost::geometry;\nnamespace bgi = boost::geometry::index;\n\nusing point = bg::model::point<double, 2, bg::cs::cartesian>;\nusing box = bg::model::box<point>;\nusing value = std::pair<box, int>;\n\n// Hilbert value computation for ordering\ninline uint32_t hilbertOrder(int x, int y, int iterations = 10) {\n    uint32_t d = 0;\n    for (int s = 1 << (iterations - 1); s > 0; s >>= 1) {\n        bool rx = (x & s) > 0;\n        bool ry = (y & s) > 0;\n        d = (d << 2) | ((rx ? 1 : 0) * 3) ^ (ry ? 1 : 0);\n        if (!ry) {\n            if (rx) {\n                x = (1 << iterations) - 1 - x;\n                y = (1 << iterations) - 1 - y;\n            }\n            std::swap(x, y);\n        }\n    }\n    return d;\n}\n\nint main() {\n    std::ios::sync_with_stdio(false);\n    std::cin.tie(nullptr);\n\n    int N, M, Q, L, W;\n    std::cin >> N >> M >> Q >> L >> W;\n\n    std::vector<int> G(M);\n    for (int i = 0; i < M; ++i) {\n        std::cin >> G[i];\n    }\n\n    std::vector<int> lx(N), rx(N), ly(N), ry(N);\n    std::vector<double> cx(N), cy(N);\n    std::vector<box> boxes(N);\n    \n    for (int i = 0; i < N; ++i) {\n        std::cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n        cx[i] = (lx[i] + rx[i]) / 2.0;\n        cy[i] = (ly[i] + ry[i]) / 2.0;\n        boxes[i] = box(point(lx[i], ly[i]), point(rx[i], ry[i]));\n    }\n\n    // Create R-tree for spatial queries\n    bgi::rtree<value, bgi::quadratic<16>> rtree;\n    for (int i = 0; i < N; ++i) {\n        rtree.insert(std::make_pair(boxes[i], i));\n    }\n\n    // Order cities by Hilbert curve for better spatial locality\n    std::vector<int> order(N);\n    std::iota(order.begin(), order.end(), 0);\n    std::sort(order.begin(), order.end(), [&](int i, int j) {\n        // Scale coordinates to [0, 2^20) for Hilbert curve\n        int xi = static_cast<int>((cx[i] / 10000.0) * (1 << 20));\n        int yi = static_cast<int>((cy[i] / 10000.0) * (1 << 20));\n        int xj = static_cast<int>((cx[j] / 10000.0) * (1 << 20));\n        int yj = static_cast<int>((cy[j] / 10000.0) * (1 << 20));\n        return hilbertOrder(xi, yi) < hilbertOrder(xj, yj);\n    });\n\n    // Cluster cities into groups using a balanced approach\n    std::vector<std::vector<int>> groups(M);\n    std::vector<bool> used(N, false);\n    \n    for (int k = 0; k < M; ++k) {\n        if (groups[k].size() == G[k]) continue;\n        \n        // Find the city with smallest uncertainty that hasn't been assigned\n        int start = -1;\n        double min_area = 1e18;\n        for (int i : order) {\n            if (!used[i]) {\n                double area = (rx[i] - lx[i]) * (ry[i] - ly[i]);\n                if (area < min_area) {\n                    min_area = area;\n                    start = i;\n                }\n            }\n        }\n        \n        // If no unassigned city, break (shouldn't happen)\n        if (start == -1) break;\n        \n        // Use BFS to collect nearby cities for this group\n        std::queue<int> q;\n        q.push(start);\n        used[start] = true;\n        groups[k].push_back(start);\n        \n        while (!q.empty() && groups[k].size() < G[k]) {\n            int curr = q.front();\n            q.pop();\n            \n            // Query R-tree for nearest cities\n            std::vector<value> results;\n            point center(cx[curr], cy[curr]);\n            rtree.query(bgi::nearest(center, 10), std::back_inserter(results));\n            \n            for (const auto& [box, idx] : results) {\n                if (!used[idx] && groups[k].size() < G[k]) {\n                    used[idx] = true;\n                    groups[k].push_back(idx);\n                    q.push(idx);\n                }\n            }\n        }\n        \n        // If we still need more cities, add the closest available\n        while (groups[k].size() < G[k]) {\n            double min_dist = 1e18;\n            int best = -1;\n            for (int i = 0; i < N; ++i) {\n                if (!used[i]) {\n                    double dx = cx[groups[k][0]] - cx[i];\n                    double dy = cy[groups[k][0]] - cy[i];\n                    double dist = dx*dx + dy*dy;\n                    if (dist < min_dist) {\n                        min_dist = dist;\n                        best = i;\n                    }\n                }\n            }\n            if (best != -1) {\n                used[best] = true;\n                groups[k].push_back(best);\n            } else {\n                break; // Shouldn't happen if sum G_i = N\n            }\n        }\n    }\n\n    std::vector<std::vector<std::pair<int, int>>> group_edges(M);\n    int query_count = 0;\n\n    // First pass: Use basic sliding window queries\n    for (int k = 0; k < M; ++k) {\n        const auto& cities = groups[k];\n        int g = cities.size();\n        if (g == 1) continue;\n\n        if (g <= L) {\n            std::cout << \"? \" << g;\n            for (int city : cities) std::cout << \" \" << city;\n            std::cout << std::endl;\n            std::cout.flush();\n            \n            for (int i = 0; i < g - 1; ++i) {\n                int a, b;\n                std::cin >> a >> b;\n                group_edges[k].emplace_back(a, b);\n            }\n            query_count++;\n        } else {\n            int step = L - 1;\n            int windows = (g - 1 + step - 1) / step;\n            for (int w = 0; w < windows; ++w) {\n                int start = w * step;\n                int end = std::min(start + L, g);\n                int sz = end - start;\n                \n                std::cout << \"? \" << sz;\n                for (int i = start; i < end; ++i) {\n                    std::cout << \" \" << cities[i];\n                }\n                std::cout << std::endl;\n                std::cout.flush();\n                \n                for (int i = 0; i < sz - 1; ++i) {\n                    int a, b;\n                    std::cin >> a >> b;\n                    group_edges[k].emplace_back(a, b);\n                }\n                query_count++;\n            }\n        }\n    }\n\n    // Second pass: Use remaining queries to improve largest groups\n    int remaining_queries = Q - query_count;\n    if (remaining_queries > 0) {\n        // Sort groups by size descending\n        std::vector<int> group_indices(M);\n        std::iota(group_indices.begin(), group_indices.end(), 0);\n        std::sort(group_indices.begin(), group_indices.end(), \n                 [&](int a, int b) { return groups[a].size() > groups[b].size(); });\n        \n        for (int k : group_indices) {\n            if (remaining_queries <= 0) break;\n            \n            const auto& cities = groups[k];\n            int g = cities.size();\n            if (g <= L) continue; // Already optimal\n            \n            // Add extra overlapping windows for this group\n            int extra_windows = std::min(remaining_queries, (g - L) / 2 + 1);\n            for (int w = 0; w < extra_windows; ++w) {\n                int start = w * 2; // Step of 2 for more overlap\n                if (start + L > g) break;\n                \n                std::cout << \"? \" << L;\n                for (int i = start; i < start + L; ++i) {\n                    std::cout << \" \" << cities[i];\n                }\n                std::cout << std::endl;\n                std::cout.flush();\n                \n                for (int i = 0; i < L - 1; ++i) {\n                    int a, b;\n                    std::cin >> a >> b;\n                    group_edges[k].emplace_back(a, b);\n                }\n                remaining_queries--;\n            }\n            \n            // Run Kruskal on collected edges using lower-bound distances\n            if (group_edges[k].size() > g - 1) {\n                // Build adjacency list with lower-bound distances\n                std::vector<std::tuple<double, int, int>> edges_with_weights;\n                for (const auto& [a, b] : group_edges[k]) {\n                    // Compute lower-bound distance between rectangles\n                    double dx = std::max({0.0, \n                                        static_cast<double>(lx[a] - rx[b]),\n                                        static_cast<double>(lx[b] - rx[a])});\n                    double dy = std::max({0.0, \n                                        static_cast<double>(ly[a] - ry[b]),\n                                        static_cast<double>(ly[b] - ry[a])});\n                    double lb_dist = std::sqrt(dx*dx + dy*dy);\n                    edges_with_weights.emplace_back(lb_dist, a, b);\n                }\n                \n                // Kruskal's algorithm\n                std::sort(edges_with_weights.begin(), edges_with_weights.end());\n                std::vector<int> parent(N);\n                std::iota(parent.begin(), parent.end(), 0);\n                \n                auto find = [&](int x) {\n                    while (parent[x] != x) {\n                        parent[x] = parent[parent[x]];\n                        x = parent[x];\n                    }\n                    return x;\n                };\n                \n                group_edges[k].clear();\n                for (const auto& [w, a, b] : edges_with_weights) {\n                    int ra = find(a), rb = find(b);\n                    if (ra != rb) {\n                        parent[ra] = rb;\n                        group_edges[k].emplace_back(a, b);\n                        if (group_edges[k].size() == g - 1) break;\n                    }\n                }\n            }\n        }\n    }\n\n    // Output answer\n    std::cout << \"!\" << std::endl;\n    for (int k = 0; k < M; ++k) {\n        // Output cities in the group\n        for (size_t i = 0; i < groups[k].size(); ++i) {\n            if (i > 0) std::cout << \" \";\n            std::cout << groups[k][i];\n        }\n        std::cout << std::endl;\n        \n        // Output edges\n        for (const auto& [a, b] : group_edges[k]) {\n            std::cout << a << \" \" << b << std::endl;\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n    vector<pair<int, int>> pts(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> pts[i].first >> pts[i].second;\n    }\n\n    vector<string> actions;\n\n    for (int i = 0; i < M - 1; ++i) {\n        int r1 = pts[i].first, c1 = pts[i].second;\n        int r2 = pts[i + 1].first, c2 = pts[i + 1].second;\n\n        // ----- compute costs of the nine possible plans -----\n        int direct = abs(r1 - r2) + abs(c1 - c2);\n\n        int costU = (r1 > 0 ? 1 : 0) + abs(c1 - c2) + r2;\n        int costD = (r1 < N - 1 ? 1 : 0) + abs(c1 - c2) + (N - 1 - r2);\n        int costL = (c1 > 0 ? 1 : 0) + abs(r1 - r2) + c2;\n        int costR = (c1 < N - 1 ? 1 : 0) + abs(r1 - r2) + (N - 1 - c2);\n\n        // Corner plans\n        int costTL = (r1 > 0 ? 1 : 0) + (c1 > 0 ? 1 : 0) + r2 + c2;\n        int costTR = (r1 > 0 ? 1 : 0) + (c1 < N - 1 ? 1 : 0) + r2 + (N - 1 - c2);\n        int costBL = (r1 < N - 1 ? 1 : 0) + (c1 > 0 ? 1 : 0) + (N - 1 - r2) + c2;\n        int costBR = (r1 < N - 1 ? 1 : 0) + (c1 < N - 1 ? 1 : 0) + (N - 1 - r2) + (N - 1 - c2);\n\n        // ----- choose the cheapest plan -----\n        int best = direct;\n        int option = 0; // 0:direct, 1:up, 2:down, 3:left, 4:right, 5:TL, 6:TR, 7:BL, 8:BR\n        if (costU < best) { best = costU; option = 1; }\n        if (costD < best) { best = costD; option = 2; }\n        if (costL < best) { best = costL; option = 3; }\n        if (costR < best) { best = costR; option = 4; }\n        if (costTL < best) { best = costTL; option = 5; }\n        if (costTR < best) { best = costTR; option = 6; }\n        if (costBL < best) { best = costBL; option = 7; }\n        if (costBR < best) { best = costBR; option = 8; }\n\n        // ----- generate the actions for the chosen plan -----\n        switch (option) {\n            case 0: // direct moves\n                if (r2 > r1) {\n                    for (int k = 0; k < r2 - r1; ++k) actions.push_back(\"M D\");\n                } else if (r2 < r1) {\n                    for (int k = 0; k < r1 - r2; ++k) actions.push_back(\"M U\");\n                }\n                if (c2 > c1) {\n                    for (int k = 0; k < c2 - c1; ++k) actions.push_back(\"M R\");\n                } else if (c2 < c1) {\n                    for (int k = 0; k < c1 - c2; ++k) actions.push_back(\"M L\");\n                }\n                break;\n\n            case 1: // Up\n                if (r1 > 0) actions.push_back(\"S U\");\n                if (c2 > c1) {\n                    for (int k = 0; k < c2 - c1; ++k) actions.push_back(\"M R\");\n                } else if (c2 < c1) {\n                    for (int k = 0; k < c1 - c2; ++k) actions.push_back(\"M L\");\n                }\n                if (r2 > 0) {\n                    for (int k = 0; k < r2; ++k) actions.push_back(\"M D\");\n                }\n                break;\n\n            case 2: // Down\n                if (r1 < N - 1) actions.push_back(\"S D\");\n                if (c2 > c1) {\n                    for (int k = 0; k < c2 - c1; ++k) actions.push_back(\"M R\");\n                } else if (c2 < c1) {\n                    for (int k = 0; k < c1 - c2; ++k) actions.push_back(\"M L\");\n                }\n                if (r2 < N - 1) {\n                    int steps = N - 1 - r2;\n                    for (int k = 0; k < steps; ++k) actions.push_back(\"M U\");\n                }\n                break;\n\n            case 3: // Left\n                if (c1 > 0) actions.push_back(\"S L\");\n                if (r2 > r1) {\n                    for (int k = 0; k < r2 - r1; ++k) actions.push_back(\"M D\");\n                } else if (r2 < r1) {\n                    for (int k = 0; k < r1 - r2; ++k) actions.push_back(\"M U\");\n                }\n                if (c2 > 0) {\n                    for (int k = 0; k < c2; ++k) actions.push_back(\"M R\");\n                }\n                break;\n\n            case 4: // Right\n                if (c1 < N - 1) actions.push_back(\"S R\");\n                if (r2 > r1) {\n                    for (int k = 0; k < r2 - r1; ++k) actions.push_back(\"M D\");\n                } else if (r2 < r1) {\n                    for (int k = 0; k < r1 - r2; ++k) actions.push_back(\"M U\");\n                }\n                if (c2 < N - 1) {\n                    int steps = N - 1 - c2;\n                    for (int k = 0; k < steps; ++k) actions.push_back(\"M L\");\n                }\n                break;\n\n            case 5: // Top-left corner\n                if (r1 > 0) actions.push_back(\"S U\");\n                if (c1 > 0) actions.push_back(\"S L\");\n                // now at (0,0)\n                if (c2 > 0) {\n                    for (int k = 0; k < c2; ++k) actions.push_back(\"M R\");\n                }\n                if (r2 > 0) {\n                    for (int k = 0; k < r2; ++k) actions.push_back(\"M D\");\n                }\n                break;\n\n            case 6: // Top-right corner\n                if (r1 > 0) actions.push_back(\"S U\");\n                if (c1 < N - 1) actions.push_back(\"S R\");\n                // now at (0,N-1)\n                if (r2 > 0) {\n                    for (int k = 0; k < r2; ++k) actions.push_back(\"M D\");\n                }\n                if (c2 < N - 1) {\n                    int steps = N - 1 - c2;\n                    for (int k = 0; k < steps; ++k) actions.push_back(\"M L\");\n                }\n                break;\n\n            case 7: // Bottom-left corner\n                if (r1 < N - 1) actions.push_back(\"S D\");\n                if (c1 > 0) actions.push_back(\"S L\");\n                // now at (N-1,0)\n                if (r2 < N - 1) {\n                    int steps = N - 1 - r2;\n                    for (int k = 0; k < steps; ++k) actions.push_back(\"M U\");\n                }\n                if (c2 > 0) {\n                    for (int k = 0; k < c2; ++k) actions.push_back(\"M R\");\n                }\n                break;\n\n            case 8: // Bottom-right corner\n                if (r1 < N - 1) actions.push_back(\"S D\");\n                if (c1 < N - 1) actions.push_back(\"S R\");\n                // now at (N-1,N-1)\n                if (r2 < N - 1) {\n                    int steps = N - 1 - r2;\n                    for (int k = 0; k < steps; ++k) actions.push_back(\"M U\");\n                }\n                if (c2 < N - 1) {\n                    int steps = N - 1 - c2;\n                    for (int k = 0; k < steps; ++k) actions.push_back(\"M L\");\n                }\n                break;\n        }\n    }\n\n    // ----- output all actions -----\n    for (const string& act : actions) {\n        cout << act << '\\n';\n    }\n\n    return 0;\n}"},"8":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\n\nstruct Company {\n    int x, y, r;\n};\n\nstruct Node {\n    int x1, y1, x2, y2;\n    vector<int> ids;\n    int cut_type;   // 0: leaf, 1: vertical, 2: horizontal\n    int cut_pos;\n    Node *left, *right;\n    ll total_r;\n    Node() : left(nullptr), right(nullptr) {}\n};\n\nint n;\nvector<Company> comps;\nvector<int> a, b, c, d;\n\nNode* build(int x1, int y1, int x2, int y2, vector<int>& ids) {\n    Node* node = new Node();\n    node->x1 = x1; node->y1 = y1; node->x2 = x2; node->y2 = y2;\n    node->ids = ids;\n\n    if (ids.size() == 1) {\n        node->cut_type = 0;\n        node->total_r = comps[ids[0]].r;\n        return node;\n    }\n\n    ll total_r = 0;\n    for (int i : ids) total_r += comps[i].r;\n    node->total_r = total_r;\n\n    int min_x = 10000, max_x = 0, min_y = 10000, max_y = 0;\n    for (int i : ids) {\n        min_x = min(min_x, comps[i].x);\n        max_x = max(max_x, comps[i].x);\n        min_y = min(min_y, comps[i].y);\n        max_y = max(max_y, comps[i].y);\n    }\n\n    ll best_cost = LLONG_MAX;\n    int best_type = -1;\n    int best_pos = -1;\n\n    // Vertical cuts\n    if (max_x > min_x) {\n        for (int X = x1 + 1; X < x2; ++X) {\n            if (X <= min_x || X > max_x) continue;\n            ll left_sum = 0;\n            int left_count = 0;\n            for (int i : ids) {\n                if (comps[i].x < X) {\n                    left_sum += comps[i].r;\n                    left_count++;\n                }\n            }\n            if (left_count == 0 || left_count == ids.size()) continue;\n            \n            ll left_area = (ll)(X - x1) * (y2 - y1);\n            ll right_sum = total_r - left_sum;\n            int right_count = ids.size() - left_count;\n            ll right_area = (ll)(x2 - X) * (y2 - y1);\n            \n            ll area_cost = abs(left_area - left_sum) + abs(right_area - right_sum);\n            ll count_cost = abs(left_count - right_count);\n            ll cost = area_cost + count_cost * (total_r / 1000);\n            \n            if (cost < best_cost) {\n                best_cost = cost;\n                best_type = 1;\n                best_pos = X;\n            }\n        }\n    }\n\n    // Horizontal cuts\n    if (max_y > min_y) {\n        for (int Y = y1 + 1; Y < y2; ++Y) {\n            if (Y <= min_y || Y > max_y) continue;\n            ll bottom_sum = 0;\n            int bottom_count = 0;\n            for (int i : ids) {\n                if (comps[i].y < Y) {\n                    bottom_sum += comps[i].r;\n                    bottom_count++;\n                }\n            }\n            if (bottom_count == 0 || bottom_count == ids.size()) continue;\n            \n            ll bottom_area = (ll)(x2 - x1) * (Y - y1);\n            ll top_sum = total_r - bottom_sum;\n            int top_count = ids.size() - bottom_count;\n            ll top_area = (ll)(x2 - x1) * (y2 - Y);\n            \n            ll area_cost = abs(bottom_area - bottom_sum) + abs(top_area - top_sum);\n            ll count_cost = abs(bottom_count - top_count);\n            ll cost = area_cost + count_cost * (total_r / 1000);\n            \n            if (cost < best_cost) {\n                best_cost = cost;\n                best_type = 2;\n                best_pos = Y;\n            }\n        }\n    }\n\n    // Fallback if no valid cut found\n    if (best_type == -1) {\n        if (max_x > min_x) {\n            best_type = 1;\n            best_pos = (min_x + max_x + 1) / 2;\n            best_pos = max(x1 + 1, min(x2 - 1, best_pos));\n        } else {\n            best_type = 2;\n            best_pos = (min_y + max_y + 1) / 2;\n            best_pos = max(y1 + 1, min(y2 - 1, best_pos));\n        }\n    }\n\n    if (best_type == 1) {\n        vector<int> left_ids, right_ids;\n        for (int i : ids) {\n            if (comps[i].x < best_pos) left_ids.push_back(i);\n            else right_ids.push_back(i);\n        }\n        node->cut_type = 1;\n        node->cut_pos = best_pos;\n        node->left = build(x1, y1, best_pos, y2, left_ids);\n        node->right = build(best_pos, y1, x2, y2, right_ids);\n    } else {\n        vector<int> bottom_ids, top_ids;\n        for (int i : ids) {\n            if (comps[i].y < best_pos) bottom_ids.push_back(i);\n            else top_ids.push_back(i);\n        }\n        node->cut_type = 2;\n        node->cut_pos = best_pos;\n        node->left = build(x1, y1, x2, best_pos, bottom_ids);\n        node->right = build(x1, best_pos, x2, y2, top_ids);\n    }\n\n    return node;\n}\n\ndouble compute_score(Node* node) {\n    if (node->cut_type == 0) {\n        int i = node->ids[0];\n        ll area = (ll)(node->x2 - node->x1) * (node->y2 - node->y1);\n        ll ri = comps[i].r;\n        double ratio = min(area, ri) / (double)max(area, ri);\n        return 1.0 - (1.0 - ratio) * (1.0 - ratio);\n    }\n    return compute_score(node->left) + compute_score(node->right);\n}\n\nvoid collect(Node* node) {\n    if (node->cut_type == 0) {\n        int i = node->ids[0];\n        a[i] = node->x1;\n        b[i] = node->y1;\n        c[i] = node->x2;\n        d[i] = node->y2;\n        return;\n    }\n    collect(node->left);\n    collect(node->right);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n;\n    comps.resize(n);\n    for (int i = 0; i < n; ++i)\n        cin >> comps[i].x >> comps[i].y >> comps[i].r;\n\n    a.resize(n); b.resize(n); c.resize(n); d.resize(n);\n\n    vector<int> ids(n);\n    iota(ids.begin(), ids.end(), 0);\n    \n    Node* best_root = nullptr;\n    double best_score = -1.0;\n    \n    // Try 2 different random orders\n    for (int trial = 0; trial < 2; ++trial) {\n        if (trial > 0) {\n            shuffle(ids.begin(), ids.end(), mt19937(random_device{}()));\n        }\n        \n        Node* root = build(0, 0, 10000, 10000, ids);\n        double score = compute_score(root);\n        \n        if (score > best_score) {\n            best_score = score;\n            best_root = root;\n        }\n    }\n\n    collect(best_root);\n\n    for (int i = 0; i < n; ++i)\n        cout << a[i] << ' ' << b[i] << ' ' << c[i] << ' ' << d[i] << '\\n';\n\n    return 0;\n}","ahc002":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <cassert>\n#include <tuple>\n#include <set>\n\nusing namespace std;\n\nconst int N = 50;\nconst int dr[4] = {-1, 1, 0, 0};\nconst int dc[4] = {0, 0, -1, 1};\nconst char dir_char[4] = {'U', 'D', 'L', 'R'};\n\nstruct Neighbor {\n    int r, c;\n    char dir;\n};\n\n// Get valid neighbors from (r,c) given visited tiles.\nvector<Neighbor> get_neighbors(int r, int c, const vector<char>& visited,\n                               const vector<vector<int>>& tile_id) {\n    vector<Neighbor> res;\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) {\n            int tile = tile_id[nr][nc];\n            if (!visited[tile]) {\n                res.push_back({nr, nc, dir_char[d]});\n            }\n        }\n    }\n    return res;\n}\n\n// Count unvisited neighbors for a tile (considering all squares in the tile)\nint count_unvisited_neighbors(const pair<int,int>& square,\n                              const vector<char>& visited,\n                              const vector<vector<int>>& tile_id) {\n    int count = 0;\n    set<int> neighboring_tiles;\n    for (int d = 0; d < 4; ++d) {\n        int nr = square.first + dr[d], nc = square.second + dc[d];\n        if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n            int tile = tile_id[nr][nc];\n            if (!visited[tile] && neighboring_tiles.find(tile) == neighboring_tiles.end()) {\n                count++;\n                neighboring_tiles.insert(tile);\n            }\n        }\n    }\n    return count;\n}\n\n// Greedily extend the path from the last square with lookahead.\nvoid extend_greedy(vector<pair<int,int>>& path, vector<int>& tiles,\n                   vector<char>& visited, int& score,\n                   const vector<vector<int>>& p,\n                   const vector<vector<int>>& tile_id,\n                   mt19937& rng) {\n    while (true) {\n        int r = path.back().first, c = path.back().second;\n        auto candidates = get_neighbors(r, c, visited, tile_id);\n        if (candidates.empty()) break;\n        \n        // Score each candidate by p and number of unvisited neighbors\n        vector<pair<double, int>> candidate_scores;\n        for (size_t i = 0; i < candidates.size(); ++i) {\n            const auto& cand = candidates[i];\n            double score_val = p[cand.r][cand.c];\n            // Add bonus for having more unvisited neighbors (helps avoid dead ends)\n            int neighbor_count = count_unvisited_neighbors({cand.r, cand.c}, visited, tile_id);\n            score_val += 0.1 * neighbor_count;\n            candidate_scores.emplace_back(score_val, i);\n        }\n        \n        // Choose with probability proportional to score (softmax-like)\n        vector<double> weights;\n        for (const auto& cs : candidate_scores) {\n            weights.push_back(exp(cs.first / 10.0));\n        }\n        discrete_distribution<int> dist(weights.begin(), weights.end());\n        int idx = dist(rng);\n        \n        const auto& cand = candidates[idx];\n        path.push_back({cand.r, cand.c});\n        tiles.push_back(tile_id[cand.r][cand.c]);\n        visited[tile_id[cand.r][cand.c]] = 1;\n        score += p[cand.r][cand.c];\n    }\n}\n\n// Try to reverse a segment of the path\nbool try_reverse_segment(vector<pair<int,int>>& path, vector<int>& tiles,\n                         vector<char>& visited, int& score,\n                         const vector<vector<int>>& p,\n                         const vector<vector<int>>& tile_id,\n                         mt19937& rng) {\n    if (path.size() < 4) return false;\n    \n    uniform_int_distribution<int> len_dist(2, min(20, (int)path.size() - 2));\n    int seg_len = len_dist(rng);\n    uniform_int_distribution<int> start_dist(1, path.size() - seg_len - 1);\n    int start_idx = start_dist(rng);\n    \n    // Check if reversing this segment maintains validity\n    vector<pair<int,int>> new_path = path;\n    vector<int> new_tiles = tiles;\n    \n    // Temporarily mark tiles as unvisited for the segment\n    vector<char> temp_visited = visited;\n    for (int i = start_idx; i < start_idx + seg_len; ++i) {\n        temp_visited[tiles[i]] = 0;\n    }\n    \n    // Try to reverse\n    for (int i = 0; i < seg_len; ++i) {\n        int src_idx = start_idx + seg_len - 1 - i;\n        int dst_idx = start_idx + i;\n        new_path[dst_idx] = path[src_idx];\n        new_tiles[dst_idx] = tiles[src_idx];\n        \n        // Check if this tile is already used in the rest of the path\n        if (temp_visited[tiles[src_idx]]) return false;\n        temp_visited[tiles[src_idx]] = 1;\n    }\n    \n    // Check connectivity between segments\n    auto check_connection = [&](int from_idx, int to_idx) {\n        const auto& from = new_path[from_idx];\n        const auto& to = new_path[to_idx];\n        int dr = abs(from.first - to.first);\n        int dc = abs(from.second - to.second);\n        return (dr + dc == 1);\n    };\n    \n    if (!check_connection(start_idx - 1, start_idx)) return false;\n    if (!check_connection(start_idx + seg_len - 1, start_idx + seg_len)) return false;\n    \n    // If valid, apply the reversal\n    path = new_path;\n    tiles = new_tiles;\n    visited = temp_visited;\n    \n    // Recalculate score (could optimize but it's fine)\n    score = 0;\n    for (const auto& sq : path) {\n        score += p[sq.first][sq.second];\n    }\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Read input.\n    int si, sj;\n    cin >> si >> sj;\n    vector<vector<int>> tile_id(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> tile_id[i][j];\n    vector<vector<int>> 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    // Determine number of tiles.\n    int M = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            M = max(M, tile_id[i][j] + 1);\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    // Generate multiple initial paths and keep the best\n    vector<pair<int,int>> best_initial_path;\n    int best_initial_score = -1;\n    \n    for (int trial = 0; trial < 5; ++trial) {\n        vector<pair<int,int>> cur_path;\n        vector<int> cur_tiles;\n        vector<char> cur_visited(M, 0);\n        int cur_score = 0;\n\n        cur_path.emplace_back(si, sj);\n        cur_tiles.push_back(tile_id[si][sj]);\n        cur_visited[tile_id[si][sj]] = 1;\n        cur_score += p[si][sj];\n        \n        if (trial == 0) {\n            extend_greedy(cur_path, cur_tiles, cur_visited, cur_score, p, tile_id, rng);\n        } else {\n            // For other trials, use a more exploratory initial walk\n            uniform_int_distribution<int> walk_dist(50, 200);\n            int walk_length = walk_dist(rng);\n            for (int step = 0; step < walk_length; ++step) {\n                auto candidates = get_neighbors(cur_path.back().first, cur_path.back().second,\n                                               cur_visited, tile_id);\n                if (candidates.empty()) break;\n                \n                uniform_int_distribution<int> cand_dist(0, candidates.size() - 1);\n                int idx = cand_dist(rng);\n                const auto& cand = candidates[idx];\n                cur_path.push_back({cand.r, cand.c});\n                cur_tiles.push_back(tile_id[cand.r][cand.c]);\n                cur_visited[tile_id[cand.r][cand.c]] = 1;\n                cur_score += p[cand.r][cand.c];\n            }\n            // Then extend greedily\n            extend_greedy(cur_path, cur_tiles, cur_visited, cur_score, p, tile_id, rng);\n        }\n        \n        if (cur_score > best_initial_score) {\n            best_initial_score = cur_score;\n            best_initial_path = cur_path;\n        }\n    }\n\n    vector<pair<int,int>> cur_path = best_initial_path;\n    vector<int> cur_tiles;\n    vector<char> cur_visited(M, 0);\n    int cur_score = 0;\n    \n    // Rebuild tiles and visited from path\n    for (const auto& sq : cur_path) {\n        cur_tiles.push_back(tile_id[sq.first][sq.second]);\n        cur_visited[tile_id[sq.first][sq.second]] = 1;\n        cur_score += p[sq.first][sq.second];\n    }\n\n    vector<pair<int,int>> best_path = cur_path;\n    int best_score = cur_score;\n\n    // Simulated annealing parameters\n    const int ITER = 150000;\n    const double T_start = 200.0;\n    const double T_min = 1e-3;\n    double T = T_start;\n    double cooling_rate = pow(T_min / T_start, 1.0 / ITER);\n    \n    uniform_real_distribution<double> real_dist(0.0, 1.0);\n    auto start_time = chrono::steady_clock::now();\n    const chrono::milliseconds time_limit(1900); // 1.9 seconds\n    \n    int restart_count = 0;\n    const int RESTART_THRESHOLD = 50000; // restart if no improvement for this many iterations\n    int iterations_without_improvement = 0;\n\n    for (int iter = 0; iter < ITER; ++iter) {\n        // Time check\n        if (iter % 1000 == 0) {\n            auto now = chrono::steady_clock::now();\n            if (chrono::duration_cast<chrono::milliseconds>(now - start_time) > time_limit)\n                break;\n        }\n        \n        // Temperature restart if stuck\n        if (iterations_without_improvement > RESTART_THRESHOLD && restart_count < 3) {\n            // Revert to best solution found so far and reheat\n            cur_path = best_path;\n            cur_tiles.clear();\n            cur_visited.assign(M, 0);\n            cur_score = 0;\n            for (const auto& sq : cur_path) {\n                cur_tiles.push_back(tile_id[sq.first][sq.second]);\n                cur_visited[tile_id[sq.first][sq.second]] = 1;\n                cur_score += p[sq.first][sq.second];\n            }\n            T = T_start * pow(0.5, restart_count);\n            restart_count++;\n            iterations_without_improvement = 0;\n            continue;\n        }\n\n        // Copy current state\n        vector<pair<int,int>> new_path = cur_path;\n        vector<int> new_tiles = cur_tiles;\n        vector<char> new_visited = cur_visited;\n        int new_score = cur_score;\n\n        double op = real_dist(rng);\n        if (op < 0.3) {\n            // Extend: add one move at the end\n            if (!new_path.empty()) {\n                int r = new_path.back().first, c = new_path.back().second;\n                auto candidates = get_neighbors(r, c, new_visited, tile_id);\n                if (!candidates.empty()) {\n                    uniform_int_distribution<int> dist(0, candidates.size() - 1);\n                    int idx = dist(rng);\n                    auto& cand = candidates[idx];\n                    new_path.push_back({cand.r, cand.c});\n                    new_tiles.push_back(tile_id[cand.r][cand.c]);\n                    new_visited[tile_id[cand.r][cand.c]] = 1;\n                    new_score += p[cand.r][cand.c];\n                }\n            }\n        } else if (op < 0.5) {\n            // Shrink: remove last move\n            if (new_path.size() > 1) {\n                auto last = new_path.back();\n                int tile = new_tiles.back();\n                new_path.pop_back();\n                new_tiles.pop_back();\n                new_visited[tile] = 0;\n                new_score -= p[last.first][last.second];\n            }\n        } else if (op < 0.8) {\n            // Modify: truncate at random index, change next move, then extend\n            if (new_path.size() <= 1) {\n                // Fallback to extend\n                if (!new_path.empty()) {\n                    int r = new_path.back().first, c = new_path.back().second;\n                    auto candidates = get_neighbors(r, c, new_visited, tile_id);\n                    if (!candidates.empty()) {\n                        uniform_int_distribution<int> dist(0, candidates.size() - 1);\n                        int idx = dist(rng);\n                        auto& cand = candidates[idx];\n                        new_path.push_back({cand.r, cand.c});\n                        new_tiles.push_back(tile_id[cand.r][cand.c]);\n                        new_visited[tile_id[cand.r][cand.c]] = 1;\n                        new_score += p[cand.r][cand.c];\n                    }\n                }\n            } else {\n                int L = new_path.size();\n                uniform_int_distribution<int> idx_dist(1, L - 1);\n                int k = idx_dist(rng);\n                \n                // Remove squares from index k onward\n                for (int i = k; i < L; ++i) {\n                    int tile = new_tiles[i];\n                    new_visited[tile] = 0;\n                    new_score -= p[new_path[i].first][new_path[i].second];\n                }\n                new_path.resize(k);\n                new_tiles.resize(k);\n                \n                // Choose a new move from the square at index k-1\n                int r_prev = new_path.back().first, c_prev = new_path.back().second;\n                auto candidates = get_neighbors(r_prev, c_prev, new_visited, tile_id);\n                if (!candidates.empty()) {\n                    uniform_int_distribution<int> dist(0, candidates.size() - 1);\n                    int idx = dist(rng);\n                    auto& cand = candidates[idx];\n                    new_path.push_back({cand.r, cand.c});\n                    new_tiles.push_back(tile_id[cand.r][cand.c]);\n                    new_visited[tile_id[cand.r][cand.c]] = 1;\n                    new_score += p[cand.r][cand.c];\n                    \n                    // Extend greedily with lookahead\n                    extend_greedy(new_path, new_tiles, new_visited, new_score, p, tile_id, rng);\n                }\n            }\n        } else {\n            // Try to reverse a segment\n            if (try_reverse_segment(new_path, new_tiles, new_visited, new_score, p, tile_id, rng)) {\n                // Success - path was improved by reversal\n            } else {\n                // If reversal fails, do a simple extend\n                if (!new_path.empty()) {\n                    int r = new_path.back().first, c = new_path.back().second;\n                    auto candidates = get_neighbors(r, c, new_visited, tile_id);\n                    if (!candidates.empty()) {\n                        uniform_int_distribution<int> dist(0, candidates.size() - 1);\n                        int idx = dist(rng);\n                        auto& cand = candidates[idx];\n                        new_path.push_back({cand.r, cand.c});\n                        new_tiles.push_back(tile_id[cand.r][cand.c]);\n                        new_visited[tile_id[cand.r][cand.c]] = 1;\n                        new_score += p[cand.r][cand.c];\n                    }\n                }\n            }\n        }\n\n        // Metropolis criterion\n        int delta = new_score - cur_score;\n        bool accept = false;\n        if (delta > 0) {\n            accept = true;\n        } else {\n            double prob = exp(delta / T);\n            if (real_dist(rng) < prob) accept = true;\n        }\n\n        if (accept) {\n            cur_path = std::move(new_path);\n            cur_tiles = std::move(new_tiles);\n            cur_visited = std::move(new_visited);\n            cur_score = new_score;\n            if (cur_score > best_score) {\n                best_score = cur_score;\n                best_path = cur_path;\n                iterations_without_improvement = 0;\n            } else {\n                iterations_without_improvement++;\n            }\n        } else {\n            iterations_without_improvement++;\n        }\n\n        // Cooling\n        T *= cooling_rate;\n    }\n\n    // Convert best_path to move string\n    string moves;\n    for (size_t i = 1; i < best_path.size(); ++i) {\n        int dr = best_path[i].first - best_path[i-1].first;\n        int dc = best_path[i].second - best_path[i-1].second;\n        if (dr == -1 && dc == 0) moves += 'U';\n        else if (dr == 1 && dc == 0) moves += 'D';\n        else if (dr == 0 && dc == -1) moves += 'L';\n        else if (dr == 0 && dc == 1) moves += 'R';\n        else assert(false);\n    }\n\n    cout << moves << endl;\n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <string>\n\nusing namespace std;\n\nconst int N = 30;\n\ndouble h_est[N][N-1];\ndouble v_est[N-1][N];\nint h_count[N][N-1] = {0};\nint v_count[N-1][N] = {0};\n\nstruct Node {\n    int i, j;\n    bool operator==(const Node& other) const { return i == other.i && j == other.j; }\n    bool operator!=(const Node& other) const { return !(*this == other); }\n};\n\nusing PQElement = pair<double, Node>;\n\nstruct Compare {\n    bool operator()(const PQElement& a, const PQElement& b) const {\n        return a.first > b.first;\n    }\n};\n\ndouble getEdgeEstimate(int i, int j, int ni, int nj) {\n    if (i == ni) {\n        if (nj == j+1) return h_est[i][j];\n        else if (nj == j-1) return h_est[i][j-1];\n    } else if (j == nj) {\n        if (ni == i+1) return v_est[i][j];\n        else if (ni == i-1) return v_est[i-1][j];\n    }\n    return 0.0;\n}\n\nvoid updateEdge(int i, int j, int ni, int nj, double factor, double global_lr) {\n    if (i == ni) {\n        if (nj == j+1) {\n            h_count[i][j]++;\n            double lr = global_lr / (1.0 + sqrt(h_count[i][j]));\n            h_est[i][j] *= (1.0 + lr * (factor - 1.0));\n            if (h_est[i][j] < 1000.0) h_est[i][j] = 1000.0;\n            if (h_est[i][j] > 9000.0) h_est[i][j] = 9000.0;\n            \n            // Row regularization: pull toward row average\n            double sum = 0.0;\n            for (int jj = 0; jj < N-1; ++jj) sum += h_est[i][jj];\n            double avg = sum / (N-1);\n            h_est[i][j] = 0.99 * h_est[i][j] + 0.01 * avg;\n            \n        } else if (nj == j-1) {\n            h_count[i][j-1]++;\n            double lr = global_lr / (1.0 + sqrt(h_count[i][j-1]));\n            h_est[i][j-1] *= (1.0 + lr * (factor - 1.0));\n            if (h_est[i][j-1] < 1000.0) h_est[i][j-1] = 1000.0;\n            if (h_est[i][j-1] > 9000.0) h_est[i][j-1] = 9000.0;\n            \n            // Row regularization\n            double sum = 0.0;\n            for (int jj = 0; jj < N-1; ++jj) sum += h_est[i][jj];\n            double avg = sum / (N-1);\n            h_est[i][j-1] = 0.99 * h_est[i][j-1] + 0.01 * avg;\n        }\n    } else if (j == nj) {\n        if (ni == i+1) {\n            v_count[i][j]++;\n            double lr = global_lr / (1.0 + sqrt(v_count[i][j]));\n            v_est[i][j] *= (1.0 + lr * (factor - 1.0));\n            if (v_est[i][j] < 1000.0) v_est[i][j] = 1000.0;\n            if (v_est[i][j] > 9000.0) v_est[i][j] = 9000.0;\n            \n            // Column regularization: pull toward column average\n            double sum = 0.0;\n            for (int ii = 0; ii < N-1; ++ii) sum += v_est[ii][j];\n            double avg = sum / (N-1);\n            v_est[i][j] = 0.99 * v_est[i][j] + 0.01 * avg;\n            \n        } else if (ni == i-1) {\n            v_count[i-1][j]++;\n            double lr = global_lr / (1.0 + sqrt(v_count[i-1][j]));\n            v_est[i-1][j] *= (1.0 + lr * (factor - 1.0));\n            if (v_est[i-1][j] < 1000.0) v_est[i-1][j] = 1000.0;\n            if (v_est[i-1][j] > 9000.0) v_est[i-1][j] = 9000.0;\n            \n            // Column regularization\n            double sum = 0.0;\n            for (int ii = 0; ii < N-1; ++ii) sum += v_est[ii][j];\n            double avg = sum / (N-1);\n            v_est[i-1][j] = 0.99 * v_est[i-1][j] + 0.01 * avg;\n        }\n    }\n}\n\nvoid updateEstimates(const vector<Node>& path, int obs, int k) {\n    int path_length = path.size() - 1;\n    if (path_length == 0) return;\n    \n    double pred = 0.0;\n    for (int idx = 0; idx < path_length; idx++) {\n        auto& from = path[idx];\n        auto& to = path[idx+1];\n        pred += getEdgeEstimate(from.i, from.j, to.i, to.j);\n    }\n    \n    double factor = obs / pred;\n    // Effective learning rate schedule\n    double global_lr = 0.25 * pow(0.998, k);\n    \n    for (int idx = 0; idx < path_length; idx++) {\n        auto& from = path[idx];\n        auto& to = path[idx+1];\n        updateEdge(from.i, from.j, to.i, to.j, factor, global_lr);\n    }\n}\n\npair<string, vector<Node>> computePath(int si, int sj, int ti, int tj) {\n    // Early termination if start equals target\n    if (si == ti && sj == tj) {\n        return {\"\", {{si, sj}}};\n    }\n    \n    vector<vector<double>> dist(N, vector<double>(N, 1e18));\n    vector<vector<Node>> prev(N, vector<Node>(N, {-1,-1}));\n    dist[si][sj] = 0.0;\n    priority_queue<PQElement, vector<PQElement>, Compare> pq;\n    pq.push({0.0, {si, sj}});\n    \n    while (!pq.empty()) {\n        auto [d, node] = pq.top(); pq.pop();\n        if (d > dist[node.i][node.j]) continue;\n        if (node.i == ti && node.j == tj) break;\n        \n        // right\n        if (node.j+1 < N) {\n            double w = h_est[node.i][node.j];\n            if (dist[node.i][node.j] + w < dist[node.i][node.j+1]) {\n                dist[node.i][node.j+1] = dist[node.i][node.j] + w;\n                prev[node.i][node.j+1] = {node.i, node.j};\n                pq.push({dist[node.i][node.j+1], {node.i, node.j+1}});\n            }\n        }\n        // left\n        if (node.j-1 >= 0) {\n            double w = h_est[node.i][node.j-1];\n            if (dist[node.i][node.j] + w < dist[node.i][node.j-1]) {\n                dist[node.i][node.j-1] = dist[node.i][node.j] + w;\n                prev[node.i][node.j-1] = {node.i, node.j};\n                pq.push({dist[node.i][node.j-1], {node.i, node.j-1}});\n            }\n        }\n        // down\n        if (node.i+1 < N) {\n            double w = v_est[node.i][node.j];\n            if (dist[node.i][node.j] + w < dist[node.i+1][node.j]) {\n                dist[node.i+1][node.j] = dist[node.i][node.j] + w;\n                prev[node.i+1][node.j] = {node.i, node.j};\n                pq.push({dist[node.i+1][node.j], {node.i+1, node.j}});\n            }\n        }\n        // up\n        if (node.i-1 >= 0) {\n            double w = v_est[node.i-1][node.j];\n            if (dist[node.i][node.j] + w < dist[node.i-1][node.j]) {\n                dist[node.i-1][node.j] = dist[node.i][node.j] + w;\n                prev[node.i-1][node.j] = {node.i, node.j};\n                pq.push({dist[node.i-1][node.j], {node.i-1, node.j}});\n            }\n        }\n    }\n    \n    // reconstruct path\n    vector<Node> path_nodes;\n    Node cur = {ti, tj};\n    while (cur.i != si || cur.j != sj) {\n        path_nodes.push_back(cur);\n        cur = prev[cur.i][cur.j];\n    }\n    path_nodes.push_back({si, sj});\n    reverse(path_nodes.begin(), path_nodes.end());\n    \n    // convert to string\n    string path_str;\n    for (size_t idx = 0; idx < path_nodes.size()-1; idx++) {\n        auto& from = path_nodes[idx];\n        auto& to = path_nodes[idx+1];\n        if (to.i == from.i && to.j == from.j+1) path_str += 'R';\n        else if (to.i == from.i && to.j == from.j-1) path_str += 'L';\n        else if (to.i == from.i+1 && to.j == from.j) path_str += 'D';\n        else if (to.i == from.i-1 && to.j == from.j) path_str += 'U';\n    }\n    return {path_str, path_nodes};\n}\n\nint main() {\n    // Initialize estimates to midpoint of range\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N-1; ++j)\n            h_est[i][j] = 5000.0;\n    for (int i = 0; i < N-1; ++i)\n        for (int j = 0; j < N; ++j)\n            v_est[i][j] = 5000.0;\n\n    for (int k = 0; k < 1000; ++k) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n        \n        auto [path_str, path_nodes] = computePath(si, sj, ti, tj);\n        \n        cout << path_str << endl;\n        cout.flush();\n        \n        int obs;\n        cin >> obs;\n        \n        updateEstimates(path_nodes, obs, k);\n    }\n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <cmath>\n#include <numeric>\n#include <chrono>\n#include <cassert>\n#include <bitset>\n#include <cstring>\n\nusing namespace std;\n\nint N = 20;\nconst int ALPHABET = 8;\nconst char ALPHABET_CHARS[] = \"ABCDEFGH\";\n\nstruct Placement {\n    int str_idx;\n    int row, col;\n    int dir;\n    int len;\n};\n\nvector<string> strings;\nvector<Placement> placements;\nvector<vector<int>> placements_by_str;\nvector<vector<pair<int, char>>> cell_lists;\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\nvoid generate_placements() {\n    int M = strings.size();\n    placements_by_str.resize(M);\n    placements.clear();\n    placements.reserve(M * 800);\n    \n    for (int s = 0; s < M; ++s) {\n        int len = strings[s].size();\n        for (int dir = 0; dir < 2; ++dir) {\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    placements.push_back({s, r, c, dir, len});\n                    placements_by_str[s].push_back(placements.size() - 1);\n                }\n            }\n        }\n    }\n}\n\nvoid build_cell_lists() {\n    cell_lists.assign(N * N, {});\n    for (int pid = 0; pid < (int)placements.size(); ++pid) {\n        const Placement& p = placements[pid];\n        for (int off = 0; off < p.len; ++off) {\n            int r, c;\n            if (p.dir == 0) {\n                r = p.row;\n                c = (p.col + off) % N;\n            } else {\n                r = (p.row + off) % N;\n                c = p.col;\n            }\n            int cell = r * N + c;\n            char req = strings[p.str_idx][off];\n            cell_lists[cell].emplace_back(pid, req);\n        }\n    }\n}\n\nbool is_subsequence(const vector<vector<char>>& mat, const string& s) {\n    int len = s.size();\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            bool ok = true;\n            for (int p = 0; p < len; ++p) {\n                if (mat[i][(j + p) % N] != s[p]) {\n                    ok = false;\n                    break;\n                }\n            }\n            if (ok) return true;\n        }\n    }\n    for (int j = 0; j < N; ++j) {\n        for (int i = 0; i < N; ++i) {\n            bool ok = true;\n            for (int p = 0; p < len; ++p) {\n                if (mat[(i + p) % N][j] != s[p]) {\n                    ok = false;\n                    break;\n                }\n            }\n            if (ok) return true;\n        }\n    }\n    return false;\n}\n\nint evaluate(const vector<vector<char>>& mat) {\n    int cnt = 0;\n    for (const string& s : strings) {\n        if (is_subsequence(mat, s)) ++cnt;\n    }\n    return cnt;\n}\n\n// Enhanced greedy with more attempts\nvector<vector<char>> greedy(int seed) {\n    mt19937 gen(seed);\n    vector<vector<char>> mat(N, vector<char>(N, '.'));\n    int M = strings.size();\n    \n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    shuffle(order.begin(), order.end(), gen);\n    \n    for (int idx : order) {\n        const string& s = strings[idx];\n        int len = s.size();\n        vector<int> plist = placements_by_str[idx];\n        shuffle(plist.begin(), plist.end(), gen);\n        \n        int attempts = min(80, (int)plist.size());\n        bool placed = false;\n        \n        for (int i = 0; i < attempts && !placed; ++i) {\n            int pid = plist[i];\n            const Placement& p = placements[pid];\n            \n            bool compatible = true;\n            for (int off = 0; off < len; ++off) {\n                int r, c;\n                if (p.dir == 0) {\n                    r = p.row;\n                    c = (p.col + off) % N;\n                } else {\n                    r = (p.row + off) % N;\n                    c = p.col;\n                }\n                if (mat[r][c] != '.' && mat[r][c] != s[off]) {\n                    compatible = false;\n                    break;\n                }\n            }\n            \n            if (compatible) {\n                for (int off = 0; off < len; ++off) {\n                    int r, c;\n                    if (p.dir == 0) {\n                        r = p.row;\n                        c = (p.col + off) % N;\n                    } else {\n                        r = (p.row + off) % N;\n                        c = p.col;\n                    }\n                    if (mat[r][c] == '.') {\n                        mat[r][c] = s[off];\n                    }\n                }\n                placed = true;\n            }\n        }\n    }\n    \n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (mat[i][j] == '.')\n                mat[i][j] = 'A';\n    \n    return mat;\n}\n\n// Advanced voting with constraint propagation\nvector<vector<char>> build_by_voting_advanced() {\n    vector<vector<char>> mat(N, vector<char>(N, '.'));\n    \n    // Multiple passes with different weighting\n    for (int pass = 0; pass < 3; ++pass) {\n        vector<vector<vector<int>>> counts(N, vector<vector<int>>(N, vector<int>(ALPHABET, 0)));\n        \n        for (const auto& p : placements) {\n            for (int off = 0; off < p.len; ++off) {\n                int r, c;\n                if (p.dir == 0) {\n                    r = p.row;\n                    c = (p.col + off) % N;\n                } else {\n                    r = (p.row + off) % N;\n                    c = p.col;\n                }\n                char req = strings[p.str_idx][off];\n                int idx = req - 'A';\n                if (idx >= 0 && idx < ALPHABET) {\n                    // Weight by string length (longer strings more important)\n                    int weight = (pass == 0) ? 1 : (p.len / 2);\n                    counts[r][c][idx] += weight;\n                }\n            }\n        }\n        \n        // Assign characters\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (mat[i][j] == '.') {\n                    int best_idx = 0;\n                    for (int k = 1; k < ALPHABET; ++k) {\n                        if (counts[i][j][k] > counts[i][j][best_idx]) {\n                            best_idx = k;\n                        }\n                    }\n                    mat[i][j] = ALPHABET_CHARS[best_idx];\n                }\n            }\n        }\n    }\n    \n    return mat;\n}\n\n// Adaptive simulated annealing with dynamic iteration count\nvector<vector<char>> simulated_annealing(vector<vector<char>> mat, int max_iter = 20000) {\n    int M = strings.size();\n    int P = placements.size();\n    \n    vector<int> placement_match_count(P, 0);\n    vector<int> string_sat_count(M, 0);\n    int global_c = 0;\n    \n    for (int pid = 0; pid < P; ++pid) {\n        const Placement& p = placements[pid];\n        int cnt = 0;\n        for (int off = 0; off < p.len; ++off) {\n            int r, c;\n            if (p.dir == 0) {\n                r = p.row;\n                c = (p.col + off) % N;\n            } else {\n                r = (p.row + off) % N;\n                c = p.col;\n            }\n            if (mat[r][c] == strings[p.str_idx][off]) ++cnt;\n        }\n        placement_match_count[pid] = cnt;\n        if (cnt == p.len) {\n            ++string_sat_count[p.str_idx];\n        }\n    }\n    \n    for (int s = 0; s < M; ++s)\n        if (string_sat_count[s] > 0) ++global_c;\n    \n    double T = 5.0;\n    double cooling = pow(0.001 / T, 1.0 / max_iter);\n    uniform_int_distribution<int> cell_dist(0, N*N - 1);\n    uniform_int_distribution<int> char_dist(0, ALPHABET - 1);\n    uniform_real_distribution<double> prob_dist(0.0, 1.0);\n    \n    for (int iter = 0; iter < max_iter; ++iter) {\n        int cell = cell_dist(rng);\n        char old_char = mat[cell / N][cell % N];\n        char new_char = ALPHABET_CHARS[char_dist(rng)];\n        if (new_char == old_char) continue;\n        \n        int delta_c = 0;\n        vector<pair<int, int>> changed_placements;\n        vector<pair<int, int>> changed_strings;\n        \n        for (const auto& [pid, req] : cell_lists[cell]) {\n            int cur_cnt = placement_match_count[pid];\n            int new_cnt = cur_cnt;\n            if (old_char == req) --new_cnt;\n            if (new_char == req) ++new_cnt;\n            if (new_cnt == cur_cnt) continue;\n            \n            int len = placements[pid].len;\n            bool was_sat = (cur_cnt == len);\n            bool now_sat = (new_cnt == len);\n            \n            changed_placements.emplace_back(pid, cur_cnt);\n            placement_match_count[pid] = new_cnt;\n            \n            if (was_sat != now_sat) {\n                int str_idx = placements[pid].str_idx;\n                int delta = now_sat ? 1 : -1;\n                changed_strings.emplace_back(str_idx, delta);\n                string_sat_count[str_idx] += delta;\n                if (delta == 1 && string_sat_count[str_idx] == 1) ++delta_c;\n                if (delta == -1 && string_sat_count[str_idx] == 0) --delta_c;\n            }\n        }\n        \n        bool accept = false;\n        if (delta_c >= 0) {\n            accept = true;\n        } else {\n            double prob = exp(delta_c / T);\n            if (prob_dist(rng) < prob) accept = true;\n        }\n        \n        if (accept) {\n            mat[cell / N][cell % N] = new_char;\n            global_c += delta_c;\n            if (global_c == M) break;\n        } else {\n            for (auto& [pid, old_cnt] : changed_placements) {\n                placement_match_count[pid] = old_cnt;\n            }\n            for (auto& [str_idx, delta] : changed_strings) {\n                string_sat_count[str_idx] -= delta;\n            }\n        }\n        \n        T *= cooling;\n    }\n    \n    return mat;\n}\n\n// Generate a random matrix\nvector<vector<char>> random_matrix() {\n    vector<vector<char>> mat(N, vector<char>(N));\n    uniform_int_distribution<int> char_dist(0, ALPHABET - 1);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            mat[i][j] = ALPHABET_CHARS[char_dist(rng)];\n    return mat;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int M;\n    cin >> N >> M;\n    strings.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> strings[i];\n    }\n    \n    generate_placements();\n    build_cell_lists();\n    \n    // Strategy 1: Multiple greedy attempts\n    vector<vector<char>> best_mat;\n    int best_c = -1;\n    const int GREEDY_TRIES = 3;\n    \n    for (int t = 0; t < GREEDY_TRIES; ++t) {\n        auto mat = greedy(rng());\n        int c = evaluate(mat);\n        if (c > best_c) {\n            best_c = c;\n            best_mat = mat;\n        }\n        if (best_c == M) break;\n    }\n    \n    // Strategy 2: Advanced voting\n    if (best_c < M) {\n        auto mat = build_by_voting_advanced();\n        int c = evaluate(mat);\n        if (c > best_c) {\n            best_c = c;\n            best_mat = mat;\n        }\n    }\n    \n    // Strategy 3: Multiple voting with randomization\n    if (best_c < M) {\n        for (int trial = 0; trial < 3; ++trial) {\n            auto mat = build_by_voting_advanced();\n            uniform_int_distribution<int> cell_dist(0, N*N - 1);\n            uniform_int_distribution<int> char_dist(0, ALPHABET - 1);\n            \n            // Add controlled randomization\n            int changes = 10 + trial * 5;\n            for (int i = 0; i < changes; ++i) {\n                int cell = cell_dist(rng);\n                mat[cell / N][cell % N] = ALPHABET_CHARS[char_dist(rng)];\n            }\n            \n            int c = evaluate(mat);\n            if (c > best_c) {\n                best_c = c;\n                best_mat = mat;\n            }\n            if (best_c == M) break;\n        }\n    }\n    \n    // Strategy 4: SA with adaptive iterations\n    if (best_c > 0 && best_c < M) {\n        int sa_iters = (best_c < M/2) ? 25000 : 20000;\n        best_mat = simulated_annealing(best_mat, sa_iters);\n        best_c = evaluate(best_mat);\n    }\n    \n    // Strategy 5: Fallback for zero-score cases\n    if (best_c == 0) {\n        // Try random matrices with intensive SA\n        for (int trial = 0; trial < 2; ++trial) {\n            auto mat = random_matrix();\n            mat = simulated_annealing(mat, 30000);\n            int c = evaluate(mat);\n            if (c > best_c) {\n                best_c = c;\n                best_mat = mat;\n            }\n            if (best_c > 0) break;\n        }\n    }\n    \n    // Final output\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << best_mat[i][j];\n        }\n        cout << '\\n';\n    }\n    \n    return 0;\n}","ahc005":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <utility>\n\nusing namespace std;\n\nconst int INF = 1e9;\nconst int dr[4] = {-1, 1, 0, 0};\nconst int dc[4] = {0, 0, -1, 1};\nconst char dir_char[4] = {'U', 'D', 'L', 'R'};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, si, sj;\n    cin >> N >> si >> sj;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> grid[i];\n    }\n\n    // assign indices to road squares\n    vector<vector<int>> idx(N, vector<int>(N, -1));\n    vector<int> row, col, w;\n    int V = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != '#') {\n                idx[i][j] = V;\n                row.push_back(i);\n                col.push_back(j);\n                w.push_back(grid[i][j] - '0');\n                ++V;\n            }\n        }\n    }\n\n    // ---------- horizontal segments ----------\n    vector<int> seg_id_h(V, -1);\n    vector<vector<int>> seg_nodes_h;\n    int h_cnt = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != '#' && seg_id_h[idx[i][j]] == -1) {\n                int sid = h_cnt++;\n                seg_nodes_h.push_back({});\n                int jj = j;\n                while (jj < N && grid[i][jj] != '#') {\n                    int id = idx[i][jj];\n                    seg_id_h[id] = sid;\n                    seg_nodes_h[sid].push_back(id);\n                    ++jj;\n                }\n            }\n        }\n    }\n\n    // ---------- vertical segments ----------\n    vector<int> seg_id_v(V, -1);\n    vector<vector<int>> seg_nodes_v;\n    int v_cnt = 0;\n    for (int j = 0; j < N; ++j) {\n        for (int i = 0; i < N; ++i) {\n            if (grid[i][j] != '#' && seg_id_v[idx[i][j]] == -1) {\n                int sid = v_cnt++;\n                seg_nodes_v.push_back({});\n                int ii = i;\n                while (ii < N && grid[ii][j] != '#') {\n                    int id = idx[ii][j];\n                    seg_id_v[id] = sid;\n                    seg_nodes_v[sid].push_back(id);\n                    ++ii;\n                }\n            }\n        }\n    }\n\n    // choose the orientation with fewer segments\n    bool use_horiz = (h_cnt <= v_cnt);\n    int seg_cnt;\n    vector<int> seg_id(V);\n    vector<vector<int>> seg_nodes;\n    if (use_horiz) {\n        seg_cnt = h_cnt;\n        seg_id = seg_id_h;\n        seg_nodes = seg_nodes_h;\n    } else {\n        seg_cnt = v_cnt;\n        seg_id = seg_id_v;\n        seg_nodes = seg_nodes_v;\n    }\n\n    int start_idx = idx[si][sj];\n    int start_seg = seg_id[start_idx];\n    vector<bool> seg_visited(seg_cnt, false);\n    seg_visited[start_seg] = true;\n    int remaining = seg_cnt - 1;\n\n    string moves;\n    int cur = start_idx;\n\n    // Dijkstra from a source, filling dist and pred\n    auto dijkstra = [&](int src, vector<int>& dist, vector<int>& pred) {\n        dist.assign(V, INF);\n        pred.assign(V, -1);\n        dist[src] = 0;\n        using P = pair<int, int>;\n        priority_queue<P, vector<P>, greater<P>> pq;\n        pq.emplace(0, src);\n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop();\n            if (d != dist[u]) continue;\n            int r = row[u], c = col[u];\n            for (int k = 0; k < 4; ++k) {\n                int nr = r + dr[k];\n                int nc = c + dc[k];\n                if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n                int v = idx[nr][nc];\n                if (v == -1) continue;\n                int nd = d + w[v];\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    pred[v] = u;\n                    pq.emplace(nd, v);\n                }\n            }\n        }\n    };\n\n    // main loop: visit all segments\n    while (remaining > 0) {\n        vector<int> dist(V), pred(V);\n        dijkstra(cur, dist, pred);\n\n        // find the closest unvisited segment and its closest square\n        int best_seg = -1, best_node = -1, best_dist = INF;\n        for (int s = 0; s < seg_cnt; ++s) {\n            if (seg_visited[s]) continue;\n            int min_d = INF, node = -1;\n            for (int v : seg_nodes[s]) {\n                if (dist[v] < min_d) {\n                    min_d = dist[v];\n                    node = v;\n                }\n            }\n            if (min_d < best_dist) {\n                best_dist = min_d;\n                best_seg = s;\n                best_node = node;\n            }\n        }\n\n        // reconstruct the path from cur to best_node\n        vector<int> path;\n        for (int v = best_node; v != cur; v = pred[v]) {\n            path.push_back(v);\n        }\n        path.push_back(cur);\n        reverse(path.begin(), path.end());   // now path[0] = cur, path[last] = best_node\n\n        // walk along the path, record moves and mark newly visited segments\n        for (size_t i = 0; i + 1 < path.size(); ++i) {\n            int from = path[i];\n            int to = path[i+1];\n            int dr = row[to] - row[from];\n            int dc = col[to] - col[from];\n            char move;\n            if (dr == -1) move = 'U';\n            else if (dr == 1) move = 'D';\n            else if (dc == -1) move = 'L';\n            else if (dc == 1) move = 'R';\n            else { /* should not happen */ }\n            moves += move;\n            int s = seg_id[to];\n            if (!seg_visited[s]) {\n                seg_visited[s] = true;\n                --remaining;\n            }\n        }\n        cur = best_node;\n    }\n\n    // return to the start square\n    if (cur != start_idx) {\n        vector<int> dist(V), pred(V);\n        dijkstra(cur, dist, pred);\n        vector<int> path;\n        for (int v = start_idx; v != cur; v = pred[v]) {\n            path.push_back(v);\n        }\n        path.push_back(cur);\n        reverse(path.begin(), path.end());\n        for (size_t i = 0; i + 1 < path.size(); ++i) {\n            int from = path[i];\n            int to = path[i+1];\n            int dr = row[to] - row[from];\n            int dc = col[to] - col[from];\n            char move;\n            if (dr == -1) move = 'U';\n            else if (dr == 1) move = 'D';\n            else if (dc == -1) move = 'L';\n            else if (dc == 1) move = 'R';\n            moves += move;\n        }\n    }\n\n    cout << moves << '\\n';\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K, R;\n    cin >> N >> M >> K >> R;\n    \n    vector<vector<int>> d(N, vector<int>(K));\n    vector<double> d_sum_per_skill(K, 0.0);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < K; ++j) {\n            cin >> d[i][j];\n            d_sum_per_skill[j] += d[i][j];\n        }\n    }\n\n    // Compute average required skill per dimension\n    vector<double> avg_d(K);\n    for (int k = 0; k < K; ++k) {\n        avg_d[k] = d_sum_per_skill[k] / N;\n    }\n\n    vector<vector<int>> succ(N);\n    vector<vector<int>> pred(N);\n    vector<int> prereq_count(N, 0);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        succ[u].push_back(v);\n        pred[v].push_back(u);\n        ++prereq_count[v];\n    }\n\n    // Compute longest path (depth) for each task\n    vector<int> depth(N, 0);\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        return a < b;  // Process in natural order due to u<v guarantee\n    });\n    \n    for (int i = N-1; i >= 0; --i) {\n        int task = order[i];\n        if (succ[task].empty()) {\n            depth[task] = 1;\n        } else {\n            int max_depth = 0;\n            for (int next : succ[task]) {\n                max_depth = max(max_depth, depth[next]);\n            }\n            depth[task] = max_depth + 1;\n        }\n    }\n\n    vector<int> task_status(N, -1);\n    vector<int> task_start_day(N, -1);\n    vector<int> prereq_rem = prereq_count;\n    vector<int> member_task(M, -1);\n    vector<int> member_load(M, 0);\n    \n    // Initialize skill estimates based on s_j generation range\n    vector<vector<double>> est_s(M, vector<double>(K));\n    for (int j = 0; j < M; ++j) {\n        for (int k = 0; k < K; ++k) {\n            // s_j generation: norm between 20-60, so per dimension ~20/sqrt(K) to 60/sqrt(K)\n            // For K=15, that's about 5-15. Start with 10 as initial guess\n            est_s[j][k] = 10.0 + avg_d[k] * 0.5;\n        }\n    }\n\n    int day = 0;\n    int total_observations = 0;\n    while (true) {\n        ++day;\n        if (day > 2000) break;\n\n        if (day > 1) {\n            int n;\n            cin >> n;\n            if (n == -1) break;\n            for (int i = 0; i < n; ++i) {\n                int f;\n                cin >> f;\n                --f;\n                int task = member_task[f];\n                if (task != -1) {\n                    task_status[task] = 1;\n                    int t_obs = (day - 1) - task_start_day[task] + 1;\n                    ++total_observations;\n                    \n                    double w_pred = 0.0;\n                    int deficit_count = 0;\n                    for (int k = 0; k < K; ++k) {\n                        if (d[task][k] > est_s[f][k]) {\n                            w_pred += d[task][k] - est_s[f][k];\n                            ++deficit_count;\n                        }\n                    }\n                    \n                    // Learning rate decreases as we get more observations\n                    double lr = 0.7 / (1.0 + total_observations * 0.01);\n                    \n                    if (t_obs > 1) {\n                        double error = t_obs - w_pred;\n                        if (deficit_count > 0 && abs(error) > 1e-9) {\n                            double delta = lr * error / deficit_count;\n                            for (int k = 0; k < K; ++k) {\n                                if (d[task][k] > est_s[f][k]) {\n                                    est_s[f][k] = max(0.0, est_s[f][k] - delta);\n                                }\n                            }\n                        }\n                    } else {\n                        if (w_pred > 0 && deficit_count > 0) {\n                            double delta = lr * w_pred / deficit_count;\n                            for (int k = 0; k < K; ++k) {\n                                if (d[task][k] > est_s[f][k]) {\n                                    est_s[f][k] = min(double(d[task][k]), est_s[f][k] + delta);\n                                }\n                            }\n                        }\n                    }\n                    \n                    for (int s : succ[task]) {\n                        --prereq_rem[s];\n                    }\n                    member_task[f] = -1;\n                    member_load[f] = max(0, member_load[f] - 1);\n                }\n            }\n        }\n\n        vector<int> free_members;\n        for (int j = 0; j < M; ++j) {\n            if (member_task[j] == -1) free_members.push_back(j);\n        }\n\n        vector<int> ready_tasks;\n        for (int i = 0; i < N; ++i) {\n            if (task_status[i] == -1 && prereq_rem[i] == 0) {\n                ready_tasks.push_back(i);\n            }\n        }\n\n        if (free_members.empty() || ready_tasks.empty()) {\n            cout << \"0\\n\";\n            cout.flush();\n            continue;\n        }\n\n        // Sort tasks by criticality (longest path) descending, then by predicted difficulty\n        sort(ready_tasks.begin(), ready_tasks.end(), [&](int a, int b) {\n            if (depth[a] != depth[b]) return depth[a] > depth[b];\n            // If same depth, prefer tasks with higher total requirement\n            double sum_a = 0, sum_b = 0;\n            for (int k = 0; k < K; ++k) {\n                sum_a += d[a][k];\n                sum_b += d[b][k];\n            }\n            return sum_a > sum_b;\n        });\n\n        vector<pair<int, int>> assignments;\n        for (int task : ready_tasks) {\n            if (free_members.empty()) break;\n            \n            // Find best member considering both skill and load\n            int best_member = -1;\n            double best_score = -1e18;\n            \n            for (int j : free_members) {\n                double w = 0.0;\n                for (int k = 0; k < K; ++k) {\n                    if (d[task][k] > est_s[j][k]) {\n                        w += d[task][k] - est_s[j][k];\n                    }\n                }\n                double t_pred = max(1.0, w);\n                \n                // Score considers both predicted time and current load\n                // Lower predicted time is better, lower load is better\n                double score = -t_pred - member_load[j] * 0.5;\n                \n                if (score > best_score) {\n                    best_score = score;\n                    best_member = j;\n                }\n            }\n            \n            if (best_member != -1) {\n                task_status[task] = 0;\n                task_start_day[task] = day;\n                member_task[best_member] = task;\n                member_load[best_member]++;\n                assignments.emplace_back(best_member, task);\n                free_members.erase(find(free_members.begin(), free_members.end(), best_member));\n            }\n        }\n\n        cout << assignments.size();\n        for (auto [member, task] : assignments) {\n            cout << ' ' << member + 1 << ' ' << task + 1;\n        }\n        cout << '\\n';\n        cout.flush();\n    }\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point {\n    int x, y;\n    Point() {}\n    Point(int x, int y) : x(x), y(y) {}\n};\n\nint manhattan(const Point& a, const Point& b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    // Read 1000 orders\n    vector<Point> restaurants(1000), destinations(1000);\n    for (int i = 0; i < 1000; ++i) {\n        cin >> restaurants[i].x >> restaurants[i].y >> destinations[i].x >> destinations[i].y;\n    }\n\n    const Point depot(400, 400);\n\n    // Step 1: Select 50 orders with smallest max distance to depot\n    vector<int> order_cost(1000);\n    for (int i = 0; i < 1000; ++i) {\n        order_cost[i] = max(manhattan(depot, restaurants[i]), manhattan(depot, destinations[i]));\n    }\n    vector<int> indices(1000);\n    iota(indices.begin(), indices.end(), 0);\n    sort(indices.begin(), indices.end(), [&](int i, int j) {\n        return order_cost[i] < order_cost[j];\n    });\n\n    vector<int> selected_orders;\n    for (int i = 0; i < 50; ++i) {\n        selected_orders.push_back(indices[i]);\n    }\n\n    // Create points for selected orders\n    vector<Point> points;\n    vector<pair<int, int>> point_info; // (order_index, type) type: 0=pickup, 1=delivery\n    for (int i = 0; i < 50; ++i) {\n        int order_idx = selected_orders[i];\n        points.push_back(restaurants[order_idx]);\n        point_info.push_back({i, 0});\n        points.push_back(destinations[order_idx]);\n        point_info.push_back({i, 1});\n    }\n\n    // Step 2: Build initial tour using cheapest insertion with multiple starting points\n    const int total_points = 100;\n    // Precompute distances\n    vector<vector<int>> dist_mat(total_points, vector<int>(total_points));\n    vector<int> dist_to_depot(total_points);\n    for (int i = 0; i < total_points; ++i) {\n        for (int j = 0; j < total_points; ++j) {\n            dist_mat[i][j] = manhattan(points[i], points[j]);\n        }\n        dist_to_depot[i] = manhattan(points[i], depot);\n    }\n\n    // Try multiple starting orders and keep the best initial tour\n    vector<int> best_tour;\n    int best_tour_length = INT_MAX;\n    \n    // Try first 10 orders as starting points for better coverage\n    for (int start_order = 0; start_order < 10 && start_order < 50; ++start_order) {\n        vector<int> tour = {start_order * 2, start_order * 2 + 1};\n        vector<bool> used(50, false);\n        used[start_order] = true;\n        \n        // Insert remaining orders\n        for (int step = 1; step < 50; ++step) {\n            int best_increase = INT_MAX;\n            int best_order = -1;\n            int best_pickup_pos = -1;\n            int best_delivery_pos = -1;\n\n            // Try each unused order\n            for (int order = 0; order < 50; ++order) {\n                if (used[order]) continue;\n                int pickup_idx = order * 2;\n                int delivery_idx = order * 2 + 1;\n\n                // Try all insertion positions\n                int tour_size = tour.size();\n                for (int i = 0; i <= tour_size; ++i) {\n                    for (int j = i; j <= tour_size; ++j) {\n                        int increase = 0;\n                        if (i == j) {\n                            Point A = (i == 0) ? depot : points[tour[i-1]];\n                            Point B = (i == tour_size) ? depot : points[tour[i]];\n                            int dAB = (i == 0 || i == tour_size) ? 0 : manhattan(A, B);\n                            increase = manhattan(A, points[pickup_idx]) + \n                                       dist_mat[pickup_idx][delivery_idx] + \n                                       manhattan(points[delivery_idx], B) - dAB;\n                        } else {\n                            Point A1 = (i == 0) ? depot : points[tour[i-1]];\n                            Point B1 = (i == tour_size) ? depot : points[tour[i]];\n                            int dA1B1 = (i == 0 || i == tour_size) ? 0 : manhattan(A1, B1);\n                            int inc_pickup = manhattan(A1, points[pickup_idx]) + \n                                             manhattan(points[pickup_idx], B1) - dA1B1;\n                            \n                            Point C = (j == 0) ? depot : points[tour[j-1]];\n                            Point D = (j == tour_size) ? depot : points[tour[j]];\n                            int dCD = (j == 0 || j == tour_size) ? 0 : manhattan(C, D);\n                            int inc_delivery = manhattan(C, points[delivery_idx]) + \n                                               manhattan(points[delivery_idx], D) - dCD;\n                            increase = inc_pickup + inc_delivery;\n                        }\n\n                        if (increase < best_increase) {\n                            best_increase = increase;\n                            best_order = order;\n                            best_pickup_pos = i;\n                            best_delivery_pos = j;\n                        }\n                    }\n                }\n            }\n\n            // Insert the best order\n            int pickup_idx = best_order * 2;\n            int delivery_idx = best_order * 2 + 1;\n            \n            if (best_pickup_pos == best_delivery_pos) {\n                tour.insert(tour.begin() + best_pickup_pos, pickup_idx);\n                tour.insert(tour.begin() + best_pickup_pos + 1, delivery_idx);\n            } else {\n                tour.insert(tour.begin() + best_pickup_pos, pickup_idx);\n                if (best_delivery_pos > best_pickup_pos) {\n                    best_delivery_pos++;\n                }\n                tour.insert(tour.begin() + best_delivery_pos, delivery_idx);\n            }\n            used[best_order] = true;\n        }\n        \n        // Calculate tour length\n        int tour_length = dist_to_depot[tour[0]] + dist_to_depot[tour.back()];\n        for (size_t i = 0; i < tour.size() - 1; ++i) {\n            tour_length += dist_mat[tour[i]][tour[i+1]];\n        }\n        \n        if (tour_length < best_tour_length) {\n            best_tour_length = tour_length;\n            best_tour = tour;\n        }\n    }\n    \n    vector<int> seq = best_tour;\n\n    // Step 3: Enhanced simulated annealing with adaptive parameters and or-opt moves\n    auto is_feasible = [&](const vector<int>& sequence) {\n        vector<int> first_pickup(50, -1);\n        vector<int> first_delivery(50, -1);\n        for (int idx = 0; idx < sequence.size(); ++idx) {\n            int point_idx = sequence[idx];\n            auto [order, type] = point_info[point_idx];\n            if (type == 0 && first_pickup[order] == -1) {\n                first_pickup[order] = idx;\n            }\n            if (type == 1 && first_delivery[order] == -1) {\n                first_delivery[order] = idx;\n            }\n        }\n        for (int i = 0; i < 50; ++i) {\n            if (first_pickup[i] > first_delivery[i]) {\n                return false;\n            }\n        }\n        return true;\n    };\n\n    // Calculate tour length\n    auto calculate_length = [&](const vector<int>& sequence) {\n        int length = dist_to_depot[sequence[0]] + dist_to_depot[sequence.back()];\n        for (size_t i = 0; i < sequence.size() - 1; ++i) {\n            length += dist_mat[sequence[i]][sequence[i+1]];\n        }\n        return length;\n    };\n\n    // Run multiple SA attempts with different parameters\n    int global_best_length = calculate_length(seq);\n    vector<int> global_best_seq = seq;\n    \n    for (int sa_attempt = 0; sa_attempt < 3; ++sa_attempt) {\n        vector<int> current_seq = seq;\n        int current_length = calculate_length(current_seq);\n        \n        // Different SA parameters for each attempt\n        double temperature, cooling_rate;\n        int sa_iterations;\n        if (sa_attempt == 0) {\n            temperature = 1000.0;\n            cooling_rate = 0.9997;\n            sa_iterations = 100000;\n        } else if (sa_attempt == 1) {\n            temperature = 2000.0;\n            cooling_rate = 0.9995;\n            sa_iterations = 120000;\n        } else {\n            temperature = 500.0;\n            cooling_rate = 0.9998;\n            sa_iterations = 80000;\n        }\n        \n        int best_length = current_length;\n        vector<int> best_seq = current_seq;\n        int no_improve_count = 0;\n        \n        for (int iter = 0; iter < sa_iterations && temperature > 0.1; ++iter) {\n            // Decide move type: 70% 2-opt, 30% or-opt\n            bool use_two_opt = (rand() % 100) < 70;\n            int delta = 0;\n            bool feasible = true;\n            \n            if (use_two_opt) {\n                // Generate a random 2-opt move\n                int i = rand() % (total_points - 1);\n                int j = i + 1 + rand() % (total_points - i - 1);\n                \n                // Calculate delta\n                int a = current_seq[i];\n                int b = current_seq[i + 1];\n                int c = current_seq[j];\n                int d = (j + 1 < total_points) ? current_seq[j + 1] : -1;\n\n                int old_len = dist_mat[a][b];\n                if (d == -1) old_len += dist_to_depot[c];\n                else old_len += dist_mat[c][d];\n\n                int new_len = dist_mat[a][c];\n                if (d == -1) new_len += dist_to_depot[b];\n                else new_len += dist_mat[b][d];\n\n                delta = new_len - old_len;\n                \n                // Check feasibility if move improves\n                if (delta < 0) {\n                    vector<int> new_seq = current_seq;\n                    reverse(new_seq.begin() + i + 1, new_seq.begin() + j + 1);\n                    feasible = is_feasible(new_seq);\n                }\n                \n                // Apply move if accepted\n                if (feasible && (delta < 0 || exp(-delta / temperature) > (rand() / (RAND_MAX + 1.0)))) {\n                    reverse(current_seq.begin() + i + 1, current_seq.begin() + j + 1);\n                    current_length += delta;\n                }\n            } else {\n                // Or-opt move: move a segment of 1-3 points\n                int seg_len = 1 + rand() % 3; // 1, 2, or 3\n                if (seg_len >= total_points) seg_len = total_points - 1;\n                \n                int from = rand() % (total_points - seg_len + 1);\n                int to = rand() % (total_points - seg_len + 1);\n                while (abs(from - to) < seg_len) { // Ensure non-overlapping\n                    to = rand() % (total_points - seg_len + 1);\n                }\n                \n                // Calculate delta for or-opt (simplified calculation)\n                // In practice, we need to compute exact delta, but for speed we'll estimate\n                // We'll apply the move and calculate the new length\n                vector<int> new_seq = current_seq;\n                // Extract segment\n                vector<int> segment(new_seq.begin() + from, new_seq.begin() + from + seg_len);\n                // Remove segment\n                new_seq.erase(new_seq.begin() + from, new_seq.begin() + from + seg_len);\n                // Insert segment at new position\n                new_seq.insert(new_seq.begin() + (to > from ? to - seg_len : to), \n                              segment.begin(), segment.end());\n                \n                if (is_feasible(new_seq)) {\n                    int new_length = calculate_length(new_seq);\n                    delta = new_length - current_length;\n                    \n                    if (delta < 0 || exp(-delta / temperature) > (rand() / (RAND_MAX + 1.0))) {\n                        current_seq = new_seq;\n                        current_length = new_length;\n                    }\n                }\n            }\n            \n            // Update best solution\n            if (current_length < best_length) {\n                best_length = current_length;\n                best_seq = current_seq;\n                no_improve_count = 0;\n            } else {\n                no_improve_count++;\n                // Restart if stuck\n                if (no_improve_count > 10000) {\n                    current_seq = best_seq;\n                    current_length = best_length;\n                    no_improve_count = 0;\n                    temperature *= 1.5; // Reheat\n                }\n            }\n            \n            temperature *= cooling_rate;\n        }\n        \n        // Update global best\n        if (best_length < global_best_length) {\n            global_best_length = best_length;\n            global_best_seq = best_seq;\n        }\n    }\n    \n    seq = global_best_seq;\n    \n    // Final deterministic local search\n    bool improved = true;\n    int passes = 0;\n    const int max_passes = 150;\n    while (improved && passes < max_passes) {\n        improved = false;\n        passes++;\n        \n        // Try 2-opt moves\n        for (int i = 0; i < total_points - 1; ++i) {\n            for (int j = i + 1; j < total_points; ++j) {\n                int a = seq[i];\n                int b = seq[i + 1];\n                int c = seq[j];\n                int d = (j + 1 < total_points) ? seq[j + 1] : -1;\n\n                int old_len = dist_mat[a][b];\n                if (d == -1) old_len += dist_to_depot[c];\n                else old_len += dist_mat[c][d];\n\n                int new_len = dist_mat[a][c];\n                if (d == -1) new_len += dist_to_depot[b];\n                else new_len += dist_mat[b][d];\n\n                int delta = new_len - old_len;\n                \n                if (delta < 0) {\n                    vector<int> new_seq = seq;\n                    reverse(new_seq.begin() + i + 1, new_seq.begin() + j + 1);\n                    if (is_feasible(new_seq)) {\n                        seq = new_seq;\n                        improved = true;\n                        break;\n                    }\n                }\n            }\n            if (improved) break;\n        }\n        \n        // If no 2-opt improvement, try or-opt moves\n        if (!improved) {\n            for (int seg_len = 1; seg_len <= 3; ++seg_len) {\n                for (int from = 0; from <= total_points - seg_len; ++from) {\n                    for (int to = 0; to <= total_points - seg_len; ++to) {\n                        if (abs(from - to) < seg_len) continue; // Overlap\n                        \n                        vector<int> new_seq = seq;\n                        vector<int> segment(new_seq.begin() + from, new_seq.begin() + from + seg_len);\n                        new_seq.erase(new_seq.begin() + from, new_seq.begin() + from + seg_len);\n                        new_seq.insert(new_seq.begin() + (to > from ? to - seg_len : to), \n                                      segment.begin(), segment.end());\n                        \n                        if (is_feasible(new_seq)) {\n                            int new_length = calculate_length(new_seq);\n                            int old_length = calculate_length(seq);\n                            if (new_length < old_length) {\n                                seq = new_seq;\n                                improved = true;\n                                goto next_pass;\n                            }\n                        }\n                    }\n                }\n            }\n            next_pass:;\n        }\n    }\n\n    // Step 4: Output results\n    cout << 50 << \" \";\n    for (int i = 0; i < 50; ++i) {\n        cout << selected_orders[i] + 1 << \" \";\n    }\n    cout << \"\\n\";\n\n    cout << 102 << \" 400 400 \";\n    for (int idx : seq) {\n        cout << points[idx].x << \" \" << points[idx].y << \" \";\n    }\n    cout << \"400 400\\n\";\n\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Edge {\n    int u, v, d;\n};\n\nstruct DSU {\n    vector<int> parent, sz;\n    DSU(int n) : parent(n), sz(n, 1) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        if (parent[x] != x) parent[x] = find(parent[x]);\n        return parent[x];\n    }\n    bool unite(int x, int y) {\n        x = find(x), y = find(y);\n        if (x == y) return false;\n        if (sz[x] < sz[y]) swap(x, y);\n        parent[y] = x;\n        sz[x] += sz[y];\n        return true;\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(N), y(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> x[i] >> y[i];\n    }\n\n    const int M = 5 * (N - 1);   // 1995\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        int dx = x[u] - x[v];\n        int dy = y[u] - y[v];\n        double dist = sqrt(dx * dx + dy * dy);\n        int d = (int)(dist + 0.5);   // round to nearest integer\n        edges[i] = {u, v, d};\n    }\n\n    // Precompute for each edge whether it is a bridge in the suffix graph (edges i..M-1)\n    vector<bool> is_bridge(M, false);\n    for (int i = 0; i < M; ++i) {\n        // build adjacency for edges i..M-1\n        vector<vector<pair<int, int>>> adj(N);\n        for (int j = i; j < M; ++j) {\n            int u = edges[j].u, v = edges[j].v;\n            adj[u].emplace_back(v, j);\n            adj[v].emplace_back(u, j);\n        }\n\n        vector<int> disc(N, -1), low(N, -1);\n        int timer = 0;\n        vector<bool> bridge_this(M, false);\n\n        function<void(int, int)> dfs = [&](int v, int parent_edge) {\n            disc[v] = low[v] = timer++;\n            for (auto [to, id] : adj[v]) {\n                if (id == parent_edge) continue;\n                if (disc[to] == -1) {\n                    dfs(to, id);\n                    low[v] = min(low[v], low[to]);\n                    if (low[to] > disc[v]) {\n                        bridge_this[id] = true;\n                    }\n                } else {\n                    low[v] = min(low[v], disc[to]);\n                }\n            }\n        };\n\n        for (int v = 0; v < N; ++v) {\n            if (disc[v] == -1) {\n                dfs(v, -1);\n            }\n        }\n        is_bridge[i] = bridge_this[i];\n    }\n\n    DSU dsu(N);\n    for (int i = 0; i < M; ++i) {\n        int l;\n        cin >> l;\n        int u = edges[i].u, v = edges[i].v;\n        bool accept = false;\n        if (dsu.find(u) == dsu.find(v)) {\n            accept = false;   // would create a cycle\n        } else {\n            if (is_bridge[i]) {\n                accept = true;   // forced to keep connectivity\n            } else {\n                // accept if weight is at most twice the lower bound (mean)\n                if (l <= 2 * edges[i].d) {\n                    accept = true;\n                } else {\n                    accept = false;\n                }\n            }\n        }\n        cout << (accept ? 1 : 0) << endl;\n        if (accept) {\n            dsu.unite(u, v);\n        }\n    }\n    return 0;\n}","ahc008":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <string>\n#include <algorithm>\n#include <utility>\n#include <cmath>\n\nusing namespace std;\n\nconst int MAXN = 30;\nconst int dirs[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};\n\n// Global grids\nbool wall[MAXN][MAXN] = {false};\nbool to_build[MAXN][MAXN] = {false};\nint owner[MAXN][MAXN];\n\nstruct HumanState {\n    int state; // 0: building non-gate walls, 1: waiting (gate not built), 2: done (gate built)\n    int gate_x, gate_y;\n    int out_x, out_y;\n    vector<pair<int, int>> non_gate_walls;\n};\n\n// BFS returning distances and parent pointers\npair<vector<vector<int>>, vector<vector<pair<int, int>>>> bfs(int sx, int sy, int owner_idx, bool allow_all_owners = false) {\n    vector<vector<int>> dist(MAXN, vector<int>(MAXN, -1));\n    vector<vector<pair<int, int>>> parent(MAXN, vector<pair<int, int>>(MAXN, {-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 + dirs[d][0], ny = y + dirs[d][1];\n            if (nx < 0 || nx >= MAXN || ny < 0 || ny >= MAXN) continue;\n            if (wall[nx][ny]) continue;\n            if (!allow_all_owners && owner[nx][ny] != owner_idx) continue;\n            if (dist[nx][ny] != -1) continue;\n            dist[nx][ny] = dist[x][y] + 1;\n            parent[nx][ny] = {x, y};\n            q.push({nx, ny});\n        }\n    }\n    return {dist, parent};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N;\n    vector<pair<int, int>> pets(N);\n    vector<int> pet_types(N);\n    for (int i = 0; i < N; ++i) {\n        int x, y, t;\n        cin >> x >> y >> t;\n        pets[i] = {x - 1, y - 1};\n        pet_types[i] = t;\n    }\n    cin >> M;\n    vector<pair<int, int>> humans(M);\n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        humans[i] = {x - 1, y - 1};\n    }\n\n    // compute owner based on initial human positions\n    for (int x = 0; x < MAXN; ++x) {\n        for (int y = 0; y < MAXN; ++y) {\n            int best_dist = 1000000, best_idx = -1;\n            for (int i = 0; i < M; ++i) {\n                int d = abs(x - humans[i].first) + abs(y - humans[i].second);\n                if (d < best_dist) {\n                    best_dist = d;\n                    best_idx = i;\n                }\n            }\n            owner[x][y] = best_idx;\n        }\n    }\n\n    // mark boundary cells as to_build\n    for (int x = 0; x < MAXN; ++x) {\n        for (int y = 0; y < MAXN; ++y) {\n            bool is_human = false;\n            for (int i = 0; i < M; ++i) {\n                if (humans[i].first == x && humans[i].second == y) {\n                    is_human = true;\n                    break;\n                }\n            }\n            if (is_human) continue;\n\n            bool boundary = false;\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 >= MAXN || ny < 0 || ny >= MAXN) continue;\n                if (owner[nx][ny] != owner[x][y]) {\n                    boundary = true;\n                    break;\n                }\n            }\n            if (boundary) {\n                to_build[x][y] = true;\n            }\n        }\n    }\n\n    // initialize human states with gate and outside cell\n    vector<HumanState> human_states(M);\n    for (int i = 0; i < M; ++i) {\n        HumanState hs;\n        hs.state = 0;\n\n        // collect all to_build cells owned by this human\n        vector<pair<int, int>> walls;\n        for (int x = 0; x < MAXN; ++x) {\n            for (int y = 0; y < MAXN; ++y) {\n                if (to_build[x][y] && owner[x][y] == i) {\n                    walls.push_back({x, y});\n                }\n            }\n        }\n\n        // choose gate: closest to initial human position\n        int best_dist = 1000000;\n        pair<int, int> gate = {-1, -1};\n        for (auto& w : walls) {\n            int d = abs(w.first - humans[i].first) + abs(w.second - humans[i].second);\n            if (d < best_dist) {\n                best_dist = d;\n                gate = w;\n            }\n        }\n        hs.gate_x = gate.first;\n        hs.gate_y = gate.second;\n\n        // find outside cell (neighbor with different owner)\n        for (int d = 0; d < 4; ++d) {\n            int nx = gate.first + dirs[d][0], ny = gate.second + dirs[d][1];\n            if (nx < 0 || nx >= MAXN || ny < 0 || ny >= MAXN) continue;\n            if (owner[nx][ny] != i) {\n                hs.out_x = nx;\n                hs.out_y = ny;\n                break;\n            }\n        }\n\n        // non-gate walls\n        for (auto& w : walls) {\n            if (w.first != gate.first || w.second != gate.second) {\n                hs.non_gate_walls.push_back(w);\n            }\n        }\n        human_states[i] = hs;\n    }\n\n    // main loop for 300 turns\n    for (int turn = 0; turn < 300; ++turn) {\n        string actions(M, '.');\n\n        for (int i = 0; i < M; ++i) {\n            auto& hs = human_states[i];\n            if (hs.state == 2) {\n                actions[i] = '.';\n                continue;\n            }\n\n            bool handled = false;\n            if (hs.state == 0) {\n                if (hs.non_gate_walls.empty()) {\n                    hs.state = 1;\n                    // fall through to state 1\n                } else {\n                    // state 0: build non-gate walls\n                    auto [dist, parent] = bfs(humans[i].first, humans[i].second, i);\n                    int best_wall_x = -1, best_wall_y = -1;\n                    int best_adj_x = -1, best_adj_y = -1;\n                    int best_dist = -1;\n\n                    for (auto& w : hs.non_gate_walls) {\n                        int wx = w.first, wy = w.second;\n                        if (wall[wx][wy]) continue;\n                        for (int d = 0; d < 4; ++d) {\n                            int nx = wx + dirs[d][0], ny = wy + dirs[d][1];\n                            if (nx < 0 || nx >= MAXN || ny < 0 || ny >= MAXN) continue;\n                            if (wall[nx][ny]) continue;\n                            if (owner[nx][ny] != i) continue;\n                            if (dist[nx][ny] == -1) continue;\n                            if (dist[nx][ny] > best_dist) {\n                                best_dist = dist[nx][ny];\n                                best_wall_x = wx;\n                                best_wall_y = wy;\n                                best_adj_x = nx;\n                                best_adj_y = ny;\n                            }\n                        }\n                    }\n\n                    if (best_wall_x == -1) {\n                        actions[i] = '.';\n                    } else {\n                        if (abs(humans[i].first - best_wall_x) + abs(humans[i].second - best_wall_y) == 1) {\n                            // try to build\n                            bool safe = true;\n                            for (const auto& p : pets) {\n                                if (p.first == best_wall_x && p.second == best_wall_y) {\n                                    safe = false;\n                                    break;\n                                }\n                            }\n                            if (safe) {\n                                for (int d = 0; d < 4; ++d) {\n                                    int nx = best_wall_x + dirs[d][0], ny = best_wall_y + dirs[d][1];\n                                    if (nx < 0 || nx >= MAXN || ny < 0 || ny >= MAXN) continue;\n                                    for (const auto& p : pets) {\n                                        if (p.first == nx && p.second == ny) {\n                                            safe = false;\n                                            break;\n                                        }\n                                    }\n                                    if (!safe) break;\n                                }\n                            }\n                            if (safe) {\n                                if (best_wall_x == humans[i].first - 1 && best_wall_y == humans[i].second)\n                                    actions[i] = 'u';\n                                else if (best_wall_x == humans[i].first + 1 && best_wall_y == humans[i].second)\n                                    actions[i] = 'd';\n                                else if (best_wall_x == humans[i].first && best_wall_y == humans[i].second - 1)\n                                    actions[i] = 'l';\n                                else if (best_wall_x == humans[i].first && best_wall_y == humans[i].second + 1)\n                                    actions[i] = 'r';\n                                else\n                                    actions[i] = '.';\n\n                                if (actions[i] != '.') {\n                                    auto it = find(hs.non_gate_walls.begin(), hs.non_gate_walls.end(),\n                                                   make_pair(best_wall_x, best_wall_y));\n                                    if (it != hs.non_gate_walls.end())\n                                        hs.non_gate_walls.erase(it);\n                                }\n                            } else {\n                                actions[i] = '.';\n                            }\n                        } else {\n                            // move towards best_adj\n                            pair<int, int> next = {best_adj_x, best_adj_y};\n                            while (parent[next.first][next.second] != make_pair(humans[i].first, humans[i].second)) {\n                                next = parent[next.first][next.second];\n                            }\n                            if (next.first == humans[i].first - 1 && next.second == humans[i].second)\n                                actions[i] = 'U';\n                            else if (next.first == humans[i].first + 1 && next.second == humans[i].second)\n                                actions[i] = 'D';\n                            else if (next.first == humans[i].first && next.second == humans[i].second - 1)\n                                actions[i] = 'L';\n                            else if (next.first == humans[i].first && next.second == humans[i].second + 1)\n                                actions[i] = 'R';\n                            else\n                                actions[i] = '.';\n                        }\n                    }\n                    handled = true;\n                }\n            }\n\n            if (!handled && hs.state == 1) {\n                // state 1: waiting for pets to leave\n                // compute connected component and count pets\n                vector<vector<bool>> visited(MAXN, vector<bool>(MAXN, false));\n                queue<pair<int, int>> q;\n                q.push({humans[i].first, humans[i].second});\n                visited[humans[i].first][humans[i].second] = true;\n                int pet_count = 0;\n                while (!q.empty()) {\n                    auto [x, y] = q.front(); q.pop();\n                    for (const auto& p : pets) {\n                        if (p.first == x && p.second == y) {\n                            pet_count++;\n                            break;\n                        }\n                    }\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 >= MAXN || ny < 0 || ny >= MAXN) continue;\n                        if (wall[nx][ny]) continue;\n                        if (visited[nx][ny]) continue;\n                        visited[nx][ny] = true;\n                        q.push({nx, ny});\n                    }\n                }\n\n                if (pet_count == 0) {\n                    // no pets in component\n                    if (humans[i].first == hs.gate_x && humans[i].second == hs.gate_y) {\n                        // on gate, try to build\n                        bool safe = true;\n                        for (const auto& p : pets) {\n                            if (p.first == hs.gate_x && p.second == hs.gate_y) {\n                                safe = false;\n                                break;\n                            }\n                        }\n                        if (safe) {\n                            for (int d = 0; d < 4; ++d) {\n                                int nx = hs.gate_x + dirs[d][0], ny = hs.gate_y + dirs[d][1];\n                                if (nx < 0 || nx >= MAXN || ny < 0 || ny >= MAXN) continue;\n                                for (const auto& p : pets) {\n                                    if (p.first == nx && p.second == ny) {\n                                        safe = false;\n                                        break;\n                                    }\n                                }\n                                if (!safe) break;\n                            }\n                        }\n                        if (safe) {\n                            if (hs.gate_x == humans[i].first - 1 && hs.gate_y == humans[i].second)\n                                actions[i] = 'u';\n                            else if (hs.gate_x == humans[i].first + 1 && hs.gate_y == humans[i].second)\n                                actions[i] = 'd';\n                            else if (hs.gate_x == humans[i].first && hs.gate_y == humans[i].second - 1)\n                                actions[i] = 'l';\n                            else if (hs.gate_x == humans[i].first && hs.gate_y == humans[i].second + 1)\n                                actions[i] = 'r';\n                            else\n                                actions[i] = '.';\n\n                            if (actions[i] != '.') {\n                                hs.state = 2;\n                                wall[hs.gate_x][hs.gate_y] = true;\n                                to_build[hs.gate_x][hs.gate_y] = false;\n                            }\n                        } else {\n                            actions[i] = '.';\n                        }\n                    } else {\n                        // move towards gate\n                        auto [dist, parent] = bfs(humans[i].first, humans[i].second, i);\n                        if (dist[hs.gate_x][hs.gate_y] == -1) {\n                            actions[i] = '.';\n                        } else {\n                            pair<int, int> cur = {hs.gate_x, hs.gate_y};\n                            while (parent[cur.first][cur.second] != make_pair(humans[i].first, humans[i].second)) {\n                                cur = parent[cur.first][cur.second];\n                            }\n                            if (cur.first == humans[i].first - 1 && cur.second == humans[i].second)\n                                actions[i] = 'U';\n                            else if (cur.first == humans[i].first + 1 && cur.second == humans[i].second)\n                                actions[i] = 'D';\n                            else if (cur.first == humans[i].first && cur.second == humans[i].second - 1)\n                                actions[i] = 'L';\n                            else if (cur.first == humans[i].first && cur.second == humans[i].second + 1)\n                                actions[i] = 'R';\n                            else\n                                actions[i] = '.';\n                        }\n                    }\n                } else {\n                    // pets present, move to outside cell\n                    if (wall[hs.out_x][hs.out_y]) {\n                        // outside cell is a wall, cannot move there\n                        actions[i] = '.';\n                    } else if (humans[i].first == hs.out_x && humans[i].second == hs.out_y) {\n                        actions[i] = '.';\n                    } else {\n                        auto [dist, parent] = bfs(humans[i].first, humans[i].second, i, true);\n                        if (dist[hs.out_x][hs.out_y] == -1) {\n                            actions[i] = '.';\n                        } else {\n                            pair<int, int> cur = {hs.out_x, hs.out_y};\n                            while (parent[cur.first][cur.second] != make_pair(humans[i].first, humans[i].second)) {\n                                cur = parent[cur.first][cur.second];\n                            }\n                            if (cur.first == humans[i].first - 1 && cur.second == humans[i].second)\n                                actions[i] = 'U';\n                            else if (cur.first == humans[i].first + 1 && cur.second == humans[i].second)\n                                actions[i] = 'D';\n                            else if (cur.first == humans[i].first && cur.second == humans[i].second - 1)\n                                actions[i] = 'L';\n                            else if (cur.first == humans[i].first && cur.second == humans[i].second + 1)\n                                actions[i] = 'R';\n                            else\n                                actions[i] = '.';\n                        }\n                    }\n                }\n            }\n        }\n\n        // output actions\n        cout << actions << endl;\n        cout.flush();\n\n        // apply human actions\n        for (int i = 0; i < M; ++i) {\n            char act = actions[i];\n            int x = humans[i].first, y = humans[i].second;\n            if (act == 'u' || act == 'd' || act == 'l' || act == 'r') {\n                int wx = x, wy = y;\n                if (act == 'u') wx = x - 1;\n                else if (act == 'd') wx = x + 1;\n                else if (act == 'l') wy = y - 1;\n                else if (act == 'r') wy = y + 1;\n                wall[wx][wy] = true;\n                to_build[wx][wy] = false;\n            } else if (act == 'U' || act == 'D' || act == 'L' || act == 'R') {\n                if (act == 'U') humans[i].first = x - 1;\n                else if (act == 'D') humans[i].first = x + 1;\n                else if (act == 'L') humans[i].second = y - 1;\n                else if (act == 'R') humans[i].second = y + 1;\n            }\n        }\n\n        // read pet movements\n        vector<string> pet_moves(N);\n        for (int i = 0; i < N; ++i) {\n            cin >> pet_moves[i];\n        }\n\n        // update pet positions\n        for (int i = 0; i < N; ++i) {\n            int x = pets[i].first, y = pets[i].second;\n            for (char c : pet_moves[i]) {\n                if (c == 'U') --x;\n                else if (c == 'D') ++x;\n                else if (c == 'L') --y;\n                else if (c == 'R') ++y;\n            }\n            pets[i] = {x, y};\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cstring>\n#include <algorithm>\n#include <cmath>\nusing namespace std;\n\nconst int N = 20;\nconst int L = 200;\nconst int STATES = N * N;\nconst int BEAM_WIDTH = 25;  // increased from 20 to 25\n\nint neighbor[STATES][4];\ndouble stay_prob[STATES][4];\ndouble move_prob[STATES][4];\ndouble V[STATES][L + 1];\nint goal_id, start_id;\n\nstruct Candidate {\n    vector<double> bel;\n    double accum;\n    string seq;\n    double estimate;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj, ti, tj;\n    double p;\n    cin >> si >> sj >> ti >> tj >> p;\n\n    vector<string> h(N);\n    for (int i = 0; i < N; ++i) cin >> h[i];\n    vector<string> v(N - 1);\n    for (int i = 0; i < N - 1; ++i) cin >> v[i];\n\n    // Build neighbour table and transition probabilities\n    memset(neighbor, -1, sizeof(neighbor));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int id = i * N + j;\n            // up\n            if (i > 0 && v[i - 1][j] == '0')\n                neighbor[id][0] = (i - 1) * N + j;\n            // down\n            if (i < N - 1 && v[i][j] == '0')\n                neighbor[id][1] = (i + 1) * N + j;\n            // left\n            if (j > 0 && h[i][j - 1] == '0')\n                neighbor[id][2] = i * N + (j - 1);\n            // right\n            if (j < N - 1 && h[i][j] == '0')\n                neighbor[id][3] = i * N + (j + 1);\n        }\n    }\n\n    // Precompute stay_prob and move_prob for each state and action\n    for (int s = 0; s < STATES; ++s) {\n        for (int a = 0; a < 4; ++a) {\n            if (neighbor[s][a] == -1) {\n                stay_prob[s][a] = 1.0;\n                move_prob[s][a] = 0.0;\n            } else {\n                stay_prob[s][a] = p;\n                move_prob[s][a] = 1.0 - p;\n            }\n        }\n    }\n\n    start_id = si * N + sj;\n    goal_id = ti * N + tj;\n\n    // DP for optimal closed\u2011loop value V[state][rem]\n    for (int s = 0; s < STATES; ++s)\n        for (int r = 0; r <= L; ++r)\n            V[s][r] = 0.0;\n\n    for (int rem = 1; rem <= L; ++rem) {\n        double reward_reach = 200.0 + rem;   // 401 - (200 - rem + 1)\n        for (int s = 0; s < STATES; ++s) {\n            if (s == goal_id) {\n                V[s][rem] = 0.0;\n                continue;\n            }\n            double best = 0.0;\n            for (int a = 0; a < 4; ++a) {\n                int nb = neighbor[s][a];\n                double sp = stay_prob[s][a];\n                double mp = move_prob[s][a];\n                double expected = sp * V[s][rem - 1];\n                if (mp > 0.0) {\n                    if (nb == goal_id) {\n                        expected += mp * reward_reach;\n                    } else {\n                        expected += mp * V[nb][rem - 1];\n                    }\n                }\n                if (expected > best) best = expected;\n            }\n            V[s][rem] = best;\n        }\n    }\n\n    // Beam search for the memorized string\n    vector<Candidate> beam;\n    vector<double> start_bel(STATES, 0.0);\n    start_bel[start_id] = 1.0;\n    beam.push_back({start_bel, 0.0, \"\", 0.0});\n\n    const char dir_chars[] = \"UDLR\";\n\n    for (int step = 1; step <= L; ++step) {\n        int rem = L - step;   // steps remaining after this one\n        vector<Candidate> next_beam;\n        next_beam.reserve(beam.size() * 4);\n\n        for (const auto& cand : beam) {\n            for (int a = 0; a < 4; ++a) {\n                vector<double> new_bel(STATES, 0.0);\n                double immediate_reward = 0.0;\n                // Compute new belief and immediate reward for this step\n                for (int s = 0; s < STATES; ++s) {\n                    double prob = cand.bel[s];\n                    if (prob == 0.0) continue;\n                    int nb = neighbor[s][a];\n                    double sp = stay_prob[s][a];\n                    double mp = move_prob[s][a];\n                    new_bel[s] += prob * sp;\n                    if (mp > 0.0) {\n                        if (nb == goal_id) {\n                            immediate_reward += prob * mp * (401 - step);\n                        } else {\n                            new_bel[nb] += prob * mp;\n                        }\n                    }\n                }\n                double new_accum = cand.accum + immediate_reward;\n                double heuristic = 0.0;\n                for (int s = 0; s < STATES; ++s)\n                    heuristic += new_bel[s] * V[s][rem];\n                double estimate = new_accum + heuristic;\n\n                Candidate new_cand;\n                new_cand.bel = move(new_bel);\n                new_cand.accum = new_accum;\n                new_cand.seq = cand.seq + dir_chars[a];\n                new_cand.estimate = estimate;\n                next_beam.push_back(move(new_cand));\n            }\n        }\n\n        // Keep only the top BEAM_WIDTH candidates by estimate\n        sort(next_beam.begin(), next_beam.end(),\n             [](const Candidate& x, const Candidate& y) {\n                 return x.estimate > y.estimate;\n             });\n        if (next_beam.size() > BEAM_WIDTH)\n            next_beam.resize(BEAM_WIDTH);\n        beam = move(next_beam);\n    }\n\n    // Select the candidate with the highest actual accumulated score\n    Candidate best = *max_element(beam.begin(), beam.end(),\n                                  [](const Candidate& x, const Candidate& y) {\n                                      return x.accum < y.accum;\n                                  });\n    cout << best.seq << endl;\n\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30;\nconst int D = 4; // 0: left, 1: up, 2: right, 3: down\nconst int di[D] = {0, -1, 0, 1};\nconst int dj[D] = {-1, 0, 1, 0};\nconst int MAX_STATES = N * N * D;\n\n// to[t][d] = exit direction when entering from d, or -1 if impossible\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\nint type[N][N];\nint rot[N][N];\nint best_rot[N][N];\nint best_score = 0;\n\ninline int get_exit(int t, int r, int d) {\n    int d_in = ((d - r) + 4) & 3;\n    int e = to[t][d_in];\n    if (e == -1) return -1;\n    return (e + r) & 3;\n}\n\ninline int state_id(int i, int j, int d) {\n    return (i * N + j) * D + d;\n}\n\ninline void state_coord(int id, int& i, int& j, int& d) {\n    d = id % D;\n    int ij = id / D;\n    j = ij % N;\n    i = ij / N;\n}\n\nint compute_score(const int rot[N][N]) {\n    static int status[MAX_STATES]; // 0: unvisited, 1: visiting, 2: processed\n    memset(status, 0, sizeof(status));\n    \n    vector<int> cycles;\n    int path[MAX_STATES];\n    \n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            for (int d = 0; d < D; ++d) {\n                int sid = state_id(i, j, d);\n                if (status[sid]) continue;\n                \n                int t = type[i][j];\n                int r = rot[i][j];\n                if (get_exit(t, r, d) == -1) {\n                    status[sid] = 2;\n                    continue;\n                }\n                \n                int path_len = 0;\n                int ci = i, cj = j, cd = d;\n                int cur_sid = sid;\n                \n                while (true) {\n                    if (status[cur_sid] == 2) {\n                        // Mark all states in path as processed\n                        for (int k = 0; k < path_len; ++k) {\n                            status[path[k]] = 2;\n                        }\n                        break;\n                    }\n                    if (status[cur_sid] == 1) {\n                        // Found a cycle\n                        int cycle_start = -1;\n                        for (int k = 0; k < path_len; ++k) {\n                            if (path[k] == cur_sid) {\n                                cycle_start = k;\n                                break;\n                            }\n                        }\n                        int cycle_len = path_len - cycle_start;\n                        cycles.push_back(cycle_len);\n                        // Mark all states in path as processed\n                        for (int k = 0; k < path_len; ++k) {\n                            status[path[k]] = 2;\n                        }\n                        break;\n                    }\n                    \n                    status[cur_sid] = 1;\n                    path[path_len++] = cur_sid;\n                    \n                    // Compute next state\n                    int t2 = type[ci][cj];\n                    int r2 = rot[ci][cj];\n                    int d2 = get_exit(t2, r2, cd);\n                    if (d2 == -1) {\n                        for (int k = 0; k < path_len; ++k) {\n                            status[path[k]] = 2;\n                        }\n                        break;\n                    }\n                    \n                    int ni = ci + di[d2];\n                    int nj = cj + dj[d2];\n                    if (ni < 0 || ni >= N || nj < 0 || nj >= N) {\n                        for (int k = 0; k < path_len; ++k) {\n                            status[path[k]] = 2;\n                        }\n                        break;\n                    }\n                    \n                    int nd = (d2 + 2) & 3;\n                    if (get_exit(type[ni][nj], rot[ni][nj], nd) == -1) {\n                        for (int k = 0; k < path_len; ++k) {\n                            status[path[k]] = 2;\n                        }\n                        break;\n                    }\n                    \n                    ci = ni;\n                    cj = nj;\n                    cd = nd;\n                    cur_sid = state_id(ci, cj, cd);\n                }\n            }\n        }\n    }\n    \n    sort(cycles.rbegin(), cycles.rend());\n    if (cycles.size() < 2) return 0;\n    return cycles[0] * cycles[1];\n}\n\nvoid greedy_init() {\n    for (int iter = 0; iter < 5; ++iter) {\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                int best_r = rot[i][j];\n                int best_match = -1;\n                for (int r = 0; r < 4; ++r) {\n                    rot[i][j] = r;\n                    int match = 0;\n                    for (int d = 0; d < 4; ++d) {\n                        int t = type[i][j];\n                        if (get_exit(t, r, d) != -1) {\n                            int ni = i + di[d];\n                            int nj = j + dj[d];\n                            if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                                int nd = (d+2)%4;\n                                if (get_exit(type[ni][nj], rot[ni][nj], nd) != -1) {\n                                    match++;\n                                }\n                            }\n                        }\n                    }\n                    if (match > best_match) {\n                        best_match = match;\n                        best_r = r;\n                    }\n                }\n                rot[i][j] = best_r;\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // read input\n    for (int i = 0; i < N; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; ++j) {\n            type[i][j] = s[j] - '0';\n        }\n    }\n\n    // random number generator\n    random_device rd;\n    mt19937 rng(rd());\n    uniform_real_distribution<double> uni(0.0, 1.0);\n    uniform_int_distribution<int> rand_tile(0, N-1);\n    uniform_int_distribution<int> rand_rot(0, 3);\n\n    // initialize with greedy method\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            rot[i][j] = rand_rot(rng);\n    \n    greedy_init();\n    \n    int current_score = compute_score(rot);\n    best_score = current_score;\n    memcpy(best_rot, rot, sizeof(rot));\n\n    // simulated annealing parameters\n    const int max_iter = 20000;\n    const double T0 = 1000.0;\n    double T = T0;\n\n    for (int iter = 0; iter < max_iter; ++iter) {\n        // pick a random tile\n        int i = rand_tile(rng);\n        int j = rand_tile(rng);\n        int old_r = rot[i][j];\n        int new_r = (old_r + 1 + rand_rot(rng)) % 4;\n        rot[i][j] = new_r;\n\n        int new_score = compute_score(rot);\n        double delta = new_score - current_score;\n        if (delta > 0 || uni(rng) < exp(delta / T)) {\n            current_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            rot[i][j] = old_r;\n        }\n\n        // cool down\n        T = T0 * (1.0 - iter / (double)max_iter);\n    }\n\n    // output best rotations\n    string ans;\n    ans.reserve(N * N);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            ans += char('0' + best_rot[i][j]);\n    cout << ans << endl;\n\n    return 0;\n}","ahc011":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <cstring>\n#include <stack>\n\nusing namespace std;\n\nint N, T;\nint board[10][10];\nint empty_r, empty_c;\nint total_tiles; // N*N-1\n\n// precomputed bits for patterns 0..15\nbool has_up[16], has_down[16], has_left[16], has_right[16];\n\n// direction vectors and corresponding move characters\nconst int dr[4] = {-1, 1, 0, 0};\nconst int dc[4] = {0, 0, -1, 1};\nconst char move_char[4] = {'U', 'D', 'L', 'R'};\n\nvoid precompute_bits() {\n    for (int p = 0; p < 16; ++p) {\n        has_left[p]  = p & 1;\n        has_up[p]    = p & 2;\n        has_right[p] = p & 4;\n        has_down[p]  = p & 8;\n    }\n}\n\nint hex_to_int(char c) {\n    if ('0' <= c && c <= '9') return c - '0';\n    return 10 + c - 'a';\n}\n\n// compute number of mutual edges for a cell\nint mutual_edges(int b[10][10], int i, int j) {\n    if (b[i][j] == 0) return 0;\n    int cnt = 0;\n    int p = b[i][j];\n    if (i > 0 && b[i-1][j] && has_up[p] && has_down[b[i-1][j]]) ++cnt;\n    if (i+1 < N && b[i+1][j] && has_down[p] && has_up[b[i+1][j]]) ++cnt;\n    if (j > 0 && b[i][j-1] && has_left[p] && has_right[b[i][j-1]]) ++cnt;\n    if (j+1 < N && b[i][j+1] && has_right[p] && has_left[b[i][j+1]]) ++cnt;\n    return cnt;\n}\n\n// compute change in total mutual edges when swapping empty at (er,ec) with tile at (nr,nc)\nint delta_edges(int b[10][10], int er, int ec, int nr, int nc) {\n    vector<pair<int,int>> cells;\n    cells.emplace_back(er, ec);\n    cells.emplace_back(nr, nc);\n    for (int d = 0; d < 4; ++d) {\n        int r1 = er + dr[d], c1 = ec + dc[d];\n        if (r1 >= 0 && r1 < N && c1 >= 0 && c1 < N) cells.emplace_back(r1, c1);\n        int r2 = nr + dr[d], c2 = nc + dc[d];\n        if (r2 >= 0 && r2 < N && c2 >= 0 && c2 < N) cells.emplace_back(r2, c2);\n    }\n    sort(cells.begin(), cells.end());\n    cells.erase(unique(cells.begin(), cells.end()), cells.end());\n\n    int before = 0;\n    for (auto [x,y] : cells) {\n        before += mutual_edges(b, x, y);\n    }\n\n    swap(b[er][ec], b[nr][nc]);\n\n    int after = 0;\n    for (auto [x,y] : cells) {\n        after += mutual_edges(b, x, y);\n    }\n\n    swap(b[er][ec], b[nr][nc]);\n\n    return after - before;\n}\n\n// compute size of largest tree using union-find\nint compute_tree_size(int b[10][10]) {\n    int parent[100];\n    int sz[100];\n    int edge_count[100] = {0};\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int idx = i * N + j;\n            if (b[i][j] == 0) {\n                parent[idx] = -1;\n            } else {\n                parent[idx] = idx;\n                sz[idx] = 1;\n            }\n        }\n    }\n\n    auto find = [&](int x) {\n        while (parent[x] != x) {\n            parent[x] = parent[parent[x]];\n            x = parent[x];\n        }\n        return x;\n    };\n\n    auto unite = [&](int x, int y) {\n        x = find(x);\n        y = find(y);\n        if (x == y) {\n            edge_count[x]++;\n            return;\n        }\n        if (sz[x] < sz[y]) swap(x, y);\n        parent[y] = x;\n        sz[x] += sz[y];\n        edge_count[x] += edge_count[y] + 1;\n    };\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (b[i][j] == 0) continue;\n            int idx = i * N + j;\n            int p = b[i][j];\n            if (j+1 < N && b[i][j+1] != 0) {\n                int q = b[i][j+1];\n                if (has_right[p] && has_left[q]) {\n                    unite(idx, i * N + (j+1));\n                }\n            }\n            if (i+1 < N && b[i+1][j] != 0) {\n                int q = b[i+1][j];\n                if (has_down[p] && has_up[q]) {\n                    unite(idx, (i+1) * N + j);\n                }\n            }\n        }\n    }\n\n    int max_size = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int idx = i * N + j;\n            if (b[i][j] != 0 && parent[idx] == idx) {\n                int vertices = sz[idx];\n                int edges = edge_count[idx];\n                if (edges == vertices - 1) {\n                    max_size = max(max_size, vertices);\n                }\n            }\n        }\n    }\n    return max_size;\n}\n\n// simulated annealing solver\nstring solve() {\n    precompute_bits();\n    total_tiles = N * N - 1;\n\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (board[i][j] == 0) {\n                empty_r = i;\n                empty_c = j;\n            }\n\n    int cur_board[10][10];\n    memcpy(cur_board, board, sizeof(board));\n    int cur_er = empty_r, cur_ec = empty_c;\n    int cur_S = compute_tree_size(cur_board);\n    string cur_moves = \"\";\n    int steps = 0;\n\n    int best_S = cur_S;\n    string best_moves = \"\";\n    int best_score;\n    if (cur_S == total_tiles)\n        best_score = (int)round(500000.0 * (2.0 - 0.0 / T));\n    else\n        best_score = (int)round(500000.0 * cur_S / total_tiles);\n\n    // SA parameters from the first successful run\n    double temp = 5.0;\n    const double cooling = 0.99995;\n    const double min_temp = 1e-3;\n    const double edge_weight = 0.1;\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> dir_dist(0, 3);\n    uniform_real_distribution<double> prob_dist(0.0, 1.0);\n\n    auto start_time = chrono::steady_clock::now();\n    const double time_limit = 2.9;\n    int iteration = 0;\n\n    while (steps < T) {\n        if ((iteration & 20000) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > time_limit) break;\n        }\n        ++iteration;\n\n        int dir = dir_dist(rng);\n        int nr = cur_er + dr[dir];\n        int nc = cur_ec + dc[dir];\n        if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n\n        int d_edges = delta_edges(cur_board, cur_er, cur_ec, nr, nc);\n\n        swap(cur_board[cur_er][cur_ec], cur_board[nr][nc]);\n        int new_S = compute_tree_size(cur_board);\n        double delta = new_S - cur_S;\n        bool accept = false;\n\n        if (delta > 0)\n            accept = true;\n        else {\n            double combined = delta + edge_weight * d_edges;\n            if (temp > 1e-9) {\n                double prob = exp(combined / temp);\n                if (prob_dist(rng) < prob)\n                    accept = true;\n            }\n        }\n\n        if (accept) {\n            cur_moves += move_char[dir];\n            ++steps;\n            cur_er = nr;\n            cur_ec = nc;\n            cur_S = new_S;\n\n            if (cur_S == total_tiles) {\n                best_moves = cur_moves;\n                break;\n            }\n\n            int K = steps;\n            int score;\n            if (cur_S == total_tiles)\n                score = (int)round(500000.0 * (2.0 - (double)K / T));\n            else\n                score = (int)round(500000.0 * cur_S / total_tiles);\n            if (score > best_score) {\n                best_score = score;\n                best_S = cur_S;\n                best_moves = cur_moves;\n            }\n        } else {\n            swap(cur_board[cur_er][cur_ec], cur_board[nr][nc]);\n        }\n\n        temp *= cooling;\n        if (temp < min_temp) temp = min_temp;\n    }\n\n    return best_moves;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> T;\n    for (int i = 0; i < N; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; ++j) {\n            board[i][j] = hex_to_int(s[j]);\n        }\n    }\n\n    string ans = solve();\n    cout << ans << endl;\n\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\nusing int64 = long long;\n\nstruct Line {\n    int64 px, py, qx, qy;\n    int64 dx, dy;\n};\n\nstruct ArrayHash {\n    size_t operator()(const array<uint64_t,2>& a) const {\n        return a[0] ^ (a[1] * 0x9e3779b97f4a7c15ULL);\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, K;\n    cin >> N >> K;\n    int a[11] = {0};\n    for (int d = 1; d <= 10; ++d) cin >> a[d];\n    vector<int64> xs(N), ys(N);\n    for (int i = 0; i < N; ++i) cin >> xs[i] >> ys[i];\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> coord_dist(-20000, 20000);\n    uniform_int_distribution<int> delta_dist(-5, 5);\n\n    // Helper to check that a line does not pass through any strawberry\n    auto is_valid_line = [&](const Line& line) -> bool {\n        if (line.px == line.qx && line.py == line.qy) return false;\n        for (int i = 0; i < N; ++i) {\n            int64 cross = line.dx * (ys[i] - line.py) - line.dy * (xs[i] - line.px);\n            if (cross == 0) return false;\n        }\n        return true;\n    };\n\n    // Helper to check that the line actually cuts the cake (distance < 10000)\n    auto line_cuts_circle = [&](const Line& line) -> bool {\n        int64 num = abs(line.qx * line.py - line.qy * line.px);\n        int64 len2 = line.dx * line.dx + line.dy * line.dy;\n        return num * num < 10000LL * 10000LL * len2;\n    };\n\n    // Generate initial K lines\n    vector<Line> lines(K);\n    for (int i = 0; i < K; ++i) {\n        while (true) {\n            Line line;\n            line.px = coord_dist(rng);\n            line.py = coord_dist(rng);\n            line.qx = coord_dist(rng);\n            line.qy = coord_dist(rng);\n            line.dx = line.qx - line.px;\n            line.dy = line.qy - line.py;\n            if (!is_valid_line(line)) continue;\n            if (!line_cuts_circle(line)) continue;\n            lines[i] = line;\n            break;\n        }\n    }\n\n    // Compute initial patterns and group counts\n    vector<array<uint64_t,2>> point_pat(N);\n    unordered_map<array<uint64_t,2>, int, ArrayHash> pat_cnt;\n    for (int i = 0; i < N; ++i) {\n        array<uint64_t,2> pat = {0, 0};\n        for (int l = 0; l < K; ++l) {\n            int side = (lines[l].dx * (ys[i] - lines[l].py) -\n                        lines[l].dy * (xs[i] - lines[l].px)) > 0 ? 1 : 0;\n            if (l < 64)\n                pat[0] |= (uint64_t(side) << l);\n            else\n                pat[1] |= (uint64_t(side) << (l - 64));\n        }\n        point_pat[i] = pat;\n        pat_cnt[pat]++;\n    }\n\n    int b[11] = {0};\n    for (auto& [pat, cnt] : pat_cnt) {\n        if (cnt >= 1 && cnt <= 10) b[cnt]++;\n    }\n\n    int current_score = 0;\n    for (int d = 1; d <= 10; ++d) current_score += min(a[d], b[d]);\n\n    // Simulated annealing parameters\n    double T = 50.0;\n    const double cooling = 0.9995;\n    const double large_prob = 0.01;\n    auto start_time = chrono::steady_clock::now();\n    const double time_limit = 2.8;  // seconds\n\n    for (int iter = 0; ; ++iter) {\n        // Time check every 1000 iterations\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 > time_limit) break;\n        }\n\n        int l = rng() % K;\n        bool large = (rng() % 100) < 1;\n\n        Line new_line;\n        bool valid = false;\n\n        if (!large) { // small perturbation\n            new_line = lines[l];\n            int which = rng() % 2;\n            if (which == 0) {\n                new_line.px += delta_dist(rng);\n                new_line.py += delta_dist(rng);\n            } else {\n                new_line.qx += delta_dist(rng);\n                new_line.qy += delta_dist(rng);\n            }\n            if (new_line.px == new_line.qx && new_line.py == new_line.qy) continue;\n            new_line.dx = new_line.qx - new_line.px;\n            new_line.dy = new_line.qy - new_line.py;\n            valid = true;\n            for (int i = 0; i < N; ++i) {\n                int64 cross = new_line.dx * (ys[i] - new_line.py) -\n                              new_line.dy * (xs[i] - new_line.px);\n                if (cross == 0) { valid = false; break; }\n            }\n        } else { // large change: completely new line\n            while (true) {\n                new_line.px = coord_dist(rng);\n                new_line.py = coord_dist(rng);\n                new_line.qx = coord_dist(rng);\n                new_line.qy = coord_dist(rng);\n                new_line.dx = new_line.qx - new_line.px;\n                new_line.dy = new_line.qy - new_line.py;\n                if (is_valid_line(new_line)) {\n                    valid = true;\n                    break;\n                }\n            }\n        }\n        if (!valid) continue;\n\n        // Apply changes incrementally\n        vector<pair<int, array<uint64_t,2>>> changed; // point index, old pattern\n\n        for (int i = 0; i < N; ++i) {\n            int64 cross = new_line.dx * (ys[i] - new_line.py) -\n                          new_line.dy * (xs[i] - new_line.px);\n            int new_side = cross > 0 ? 1 : 0;\n\n            // current side from pattern\n            uint64_t& low = point_pat[i][0];\n            uint64_t& high = point_pat[i][1];\n            int old_side;\n            if (l < 64) old_side = (low >> l) & 1;\n            else old_side = (high >> (l - 64)) & 1;\n\n            if (old_side == new_side) continue;\n\n            array<uint64_t,2> old_pat = {low, high};\n\n            // toggle the bit for line l\n            if (l < 64) low ^= (1ULL << l);\n            else high ^= (1ULL << (l - 64));\n            array<uint64_t,2> new_pat = {low, high};\n\n            // update map and b for old_pat -> new_pat\n            // decrement old_pat\n            auto it = pat_cnt.find(old_pat);\n            int c_old = it->second;\n            if (c_old >= 1 && c_old <= 10) b[c_old]--;\n            if (--c_old == 0) pat_cnt.erase(it);\n            else it->second = c_old;\n\n            // increment new_pat\n            auto it2 = pat_cnt.find(new_pat);\n            if (it2 != pat_cnt.end()) {\n                int c_new = it2->second;\n                if (c_new >= 1 && c_new <= 10) b[c_new]--;\n                it2->second = c_new + 1;\n                c_new++;\n                if (c_new >= 1 && c_new <= 10) b[c_new]++;\n            } else {\n                pat_cnt[new_pat] = 1;\n                if (1 <= 10) b[1]++;\n            }\n\n            changed.emplace_back(i, old_pat);\n        }\n\n        // Compute new score\n        int new_score = 0;\n        for (int d = 1; d <= 10; ++d) new_score += min(a[d], b[d]);\n\n        // Acceptance test\n        bool accept = false;\n        if (new_score >= current_score) {\n            accept = true;\n        } else {\n            double delta = new_score - current_score;\n            double prob = exp(delta / T);\n            uniform_real_distribution<double> real_dist(0.0, 1.0);\n            if (real_dist(rng) < prob) accept = true;\n        }\n\n        if (accept) {\n            lines[l] = new_line;\n            current_score = new_score;\n        } else {\n            // Revert all changes\n            for (auto& p : changed) {\n                int i = p.first;\n                array<uint64_t,2> old_pat = p.second;\n                array<uint64_t,2> new_pat = point_pat[i]; // current\n\n                // decrement new_pat\n                auto it = pat_cnt.find(new_pat);\n                int c_new = it->second;\n                if (c_new >= 1 && c_new <= 10) b[c_new]--;\n                if (--c_new == 0) pat_cnt.erase(it);\n                else it->second = c_new;\n\n                // increment old_pat\n                auto it2 = pat_cnt.find(old_pat);\n                if (it2 != pat_cnt.end()) {\n                    int c_old = it2->second;\n                    if (c_old >= 1 && c_old <= 10) b[c_old]--;\n                    it2->second = c_old + 1;\n                    c_old++;\n                    if (c_old >= 1 && c_old <= 10) b[c_old]++;\n                } else {\n                    pat_cnt[old_pat] = 1;\n                    if (1 <= 10) b[1]++;\n                }\n\n                point_pat[i] = old_pat;\n            }\n        }\n\n        T *= cooling;\n    }\n\n    // Output the final lines\n    cout << K << \"\\n\";\n    for (int i = 0; i < K; ++i) {\n        cout << lines[i].px << \" \" << lines[i].py << \" \"\n             << lines[i].qx << \" \" << lines[i].qy << \"\\n\";\n    }\n\n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <array>\n#include <random>\n#include <chrono>\n#include <algorithm>\n\nusing namespace std;\n\nstruct MoveCandidate {\n    array<int, 8> pts;\n    double score;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::steady_clock::now();\n    const double TIME_LIMIT = 4.5;  // seconds\n    \n    int N, M;\n    cin >> N >> M;\n\n    const int c = (N - 1) / 2;\n    vector<vector<int>> w(N, vector<int>(N));\n    long long totalS = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int dx = i - c, dy = j - c;\n            w[i][j] = dx * dx + dy * dy + 1;\n            totalS += w[i][j];\n        }\n    }\n\n    vector<pair<int, int>> init(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> init[i].first >> init[i].second;\n    }\n\n    vector<array<int, 8>> best_ops;\n    long long best_score = -1;\n    int trial = 0;\n    \n    while (true) {\n        auto current_time = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(current_time - start_time).count();\n        if (elapsed > TIME_LIMIT) break;\n        trial++;\n        \n        // Initialize state\n        vector<vector<char>> dot(N, vector<char>(N, 0));\n        for (auto& p : init) dot[p.first][p.second] = 1;\n\n        vector<vector<char>> h_edge(N, vector<char>(N, 0));\n        vector<vector<char>> v_edge(N, vector<char>(N, 0));\n        vector<vector<char>> d1_edge(N, vector<char>(N, 0));\n        vector<vector<char>> d2_edge(N, vector<char>(N, 0));\n\n        vector<array<int, 8>> ops;\n        mt19937 rng(chrono::steady_clock::now().time_since_epoch().count() + trial);\n        uniform_real_distribution<double> noise(0.0, 0.1);\n\n        while (true) {\n            vector<MoveCandidate> candidates;\n            double max_score = -1.0;\n\n            for (int x = 0; x < N; ++x) {\n                for (int y = 0; y < N; ++y) {\n                    if (dot[x][y]) continue;\n                    int pw = w[x][y];\n\n                    // Unit squares (4 orientations)\n                    // lower-left\n                    if (x + 1 < N && y + 1 < N) {\n                        if (dot[x+1][y] && dot[x][y+1] && dot[x+1][y+1]) {\n                            if (!h_edge[x][y] && !h_edge[x][y+1] && !v_edge[x][y] && !v_edge[x+1][y]) {\n                                array<int,8> pts = {x, y, x+1, y, x+1, y+1, x, y+1};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                    // lower-right\n                    if (x - 1 >= 0 && y + 1 < N) {\n                        if (dot[x-1][y] && dot[x-1][y+1] && dot[x][y+1]) {\n                            if (!h_edge[x-1][y] && !h_edge[x-1][y+1] && !v_edge[x-1][y] && !v_edge[x][y]) {\n                                array<int,8> pts = {x, y, x, y+1, x-1, y+1, x-1, y};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                    // upper-left\n                    if (x + 1 < N && y - 1 >= 0) {\n                        if (dot[x][y-1] && dot[x+1][y-1] && dot[x+1][y]) {\n                            if (!h_edge[x][y-1] && !h_edge[x][y] && !v_edge[x][y-1] && !v_edge[x+1][y-1]) {\n                                array<int,8> pts = {x, y, x+1, y, x+1, y-1, x, y-1};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                    // upper-right\n                    if (x - 1 >= 0 && y - 1 >= 0) {\n                        if (dot[x-1][y-1] && dot[x][y-1] && dot[x-1][y]) {\n                            if (!h_edge[x-1][y-1] && !h_edge[x-1][y] && !v_edge[x-1][y-1] && !v_edge[x][y-1]) {\n                                array<int,8> pts = {x, y, x-1, y, x-1, y-1, x, y-1};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n\n                    // Unit diamonds (4 orientations)\n                    // case A\n                    if (x <= N-3 && y >= 1 && y <= N-2) {\n                        int lx = x, ly = y;\n                        if (dot[lx+1][ly+1] && dot[lx+2][ly] && dot[lx+1][ly-1]) {\n                            if (!d1_edge[lx][ly] && !d2_edge[lx+1][ly+1] && !d1_edge[lx+1][ly-1] && !d2_edge[lx][ly]) {\n                                array<int,8> pts = {lx, ly, lx+1, ly+1, lx+2, ly, lx+1, ly-1};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                    // case B\n                    if (x >= 1 && x <= N-2 && y >= 2 && y <= N-1) {\n                        int lx = x-1, ly = y-1;\n                        if (dot[lx][ly] && dot[lx+2][ly] && dot[lx+1][ly-1]) {\n                            if (!d1_edge[lx][ly] && !d2_edge[lx+1][ly+1] && !d1_edge[lx+1][ly-1] && !d2_edge[lx][ly]) {\n                                array<int,8> pts = {lx+1, ly+1, lx+2, ly, lx+1, ly-1, lx, ly};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                    // case C\n                    if (x >= 2 && y >= 1 && y <= N-2) {\n                        int lx = x-2, ly = y;\n                        if (dot[lx][ly] && dot[lx+1][ly+1] && dot[lx+1][ly-1]) {\n                            if (!d1_edge[lx][ly] && !d2_edge[lx+1][ly+1] && !d1_edge[lx+1][ly-1] && !d2_edge[lx][ly]) {\n                                array<int,8> pts = {lx+2, ly, lx+1, ly-1, lx, ly, lx+1, ly+1};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                    // case D\n                    if (x >= 1 && x <= N-2 && y >= 0 && y <= N-3) {\n                        int lx = x-1, ly = y+1;\n                        if (dot[lx][ly] && dot[lx+1][ly+1] && dot[lx+2][ly]) {\n                            if (!d1_edge[lx][ly] && !d2_edge[lx+1][ly+1] && !d1_edge[lx+1][ly-1] && !d2_edge[lx][ly]) {\n                                array<int,8> pts = {lx+1, ly-1, lx, ly, lx+1, ly+1, lx+2, ly};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (candidates.empty()) break;\n\n            // Select candidate with highest score\n            vector<int> best_idx;\n            for (size_t i = 0; i < candidates.size(); ++i) {\n                if (candidates[i].score == max_score) {\n                    best_idx.push_back(i);\n                }\n            }\n            int chosen = best_idx[uniform_int_distribution<int>(0, best_idx.size()-1)(rng)];\n            MoveCandidate& mv = candidates[chosen];\n\n            // Apply move\n            int x1 = mv.pts[0], y1 = mv.pts[1];\n            dot[x1][y1] = 1;\n\n            // Determine shape and mark edges\n            int minx = mv.pts[0], maxx = mv.pts[0], miny = mv.pts[1], maxy = mv.pts[1];\n            for (int i = 0; i < 4; ++i) {\n                int px = mv.pts[2*i], py = mv.pts[2*i+1];\n                if (px < minx) minx = px;\n                if (px > maxx) maxx = px;\n                if (py < miny) miny = py;\n                if (py > maxy) maxy = py;\n            }\n            \n            if (maxx - minx == 1 && maxy - miny == 1) {  // unit square\n                h_edge[minx][miny] = 1;\n                h_edge[minx][maxy] = 1;\n                v_edge[minx][miny] = 1;\n                v_edge[maxx][miny] = 1;\n            } else {  // unit diamond\n                int lx = minx, ly = -1;\n                for (int i = 0; i < 4; ++i) {\n                    if (mv.pts[2*i] == lx) {\n                        ly = mv.pts[2*i+1];\n                        break;\n                    }\n                }\n                d1_edge[lx][ly] = 1;\n                d2_edge[lx+1][ly+1] = 1;\n                d1_edge[lx+1][ly-1] = 1;\n                d2_edge[lx][ly] = 1;\n            }\n\n            ops.push_back(mv.pts);\n        }\n\n        // Calculate score for this trial\n        long long sum_w = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (dot[i][j]) sum_w += w[i][j];\n            }\n        }\n        double factor = (double)(N * N) / M;\n        double ratio = (double)sum_w / totalS;\n        long long score = llround(1e6 * factor * ratio);\n\n        if (score > best_score) {\n            best_score = score;\n            best_ops = ops;\n        }\n    }\n\n    // Output\n    cout << best_ops.size() << \"\\n\";\n    for (auto& op : best_ops) {\n        for (int i = 0; i < 8; ++i) {\n            if (i) cout << \" \";\n            cout << op[i];\n        }\n        cout << \"\\n\";\n    }\n\n    return 0;\n}","ahc015":"#include <iostream>\n#include <vector>\n#include <array>\n#include <queue>\n#include <utility>\n#include <algorithm>\n#include <cmath>\n#include <iomanip>\n#include <unordered_map>\n#include <string>\n#include <random>\n\nusing namespace std;\n\n// global flavors (1-indexed)\nvector<int> flavors(101);\n\n// 10x10 grid: 0 = empty, 1..3 = flavor\nusing Grid = array<array<int, 10>, 10>;\n\n// random generator with fixed seed\nmt19937 rng(12345);\n\n// ------------------------------------------------------------\n// tilt simulation\nGrid tilt(const Grid& g, char dir) {\n    Grid ng = {}; // zero-initialized\n    if (dir == 'F') {\n        for (int c = 0; c < 10; ++c) {\n            int idx = 0;\n            for (int r = 0; r < 10; ++r) {\n                if (g[r][c] != 0) {\n                    ng[idx++][c] = g[r][c];\n                }\n            }\n        }\n    } else if (dir == 'B') {\n        for (int c = 0; c < 10; ++c) {\n            int idx = 9;\n            for (int r = 9; r >= 0; --r) {\n                if (g[r][c] != 0) {\n                    ng[idx--][c] = g[r][c];\n                }\n            }\n        }\n    } else if (dir == 'L') {\n        for (int r = 0; r < 10; ++r) {\n            int idx = 0;\n            for (int c = 0; c < 10; ++c) {\n                if (g[r][c] != 0) {\n                    ng[r][idx++] = g[r][c];\n                }\n            }\n        }\n    } else if (dir == 'R') {\n        for (int r = 0; r < 10; ++r) {\n            int idx = 9;\n            for (int c = 9; c >= 0; --c) {\n                if (g[r][c] != 0) {\n                    ng[r][idx--] = g[r][c];\n                }\n            }\n        }\n    }\n    return ng;\n}\n\n// ------------------------------------------------------------\n// compute sum of squares of connected components\nint compute_sum_squares(const Grid& g) {\n    bool visited[10][10] = {};\n    int sum = 0;\n    for (int r = 0; r < 10; ++r) {\n        for (int c = 0; c < 10; ++c) {\n            if (g[r][c] != 0 && !visited[r][c]) {\n                int flavor = g[r][c];\n                int size = 0;\n                queue<pair<int, int>> q;\n                q.push({r, c});\n                visited[r][c] = true;\n                while (!q.empty()) {\n                    auto [x, y] = q.front(); q.pop();\n                    ++size;\n                    // four neighbors\n                    if (x > 0 && !visited[x-1][y] && g[x-1][y] == flavor) {\n                        visited[x-1][y] = true;\n                        q.push({x-1, y});\n                    }\n                    if (x < 9 && !visited[x+1][y] && g[x+1][y] == flavor) {\n                        visited[x+1][y] = true;\n                        q.push({x+1, y});\n                    }\n                    if (y > 0 && !visited[x][y-1] && g[x][y-1] == flavor) {\n                        visited[x][y-1] = true;\n                        q.push({x, y-1});\n                    }\n                    if (y < 9 && !visited[x][y+1] && g[x][y+1] == flavor) {\n                        visited[x][y+1] = true;\n                        q.push({x, y+1});\n                    }\n                }\n                sum += size * size;\n            }\n        }\n    }\n    return sum;\n}\n\n// ------------------------------------------------------------\n// compute total spread (sum of squared distances to centroid)\ndouble compute_spread(const Grid& g) {\n    vector<int> cnt(4, 0);\n    vector<double> sum_r(4, 0.0), sum_c(4, 0.0);\n    vector<double> sum_r2(4, 0.0), sum_c2(4, 0.0);\n    for (int r = 0; r < 10; ++r) {\n        for (int c = 0; c < 10; ++c) {\n            int f = g[r][c];\n            if (f != 0) {\n                cnt[f]++;\n                sum_r[f] += r;\n                sum_c[f] += c;\n                sum_r2[f] += r * r;\n                sum_c2[f] += c * c;\n            }\n        }\n    }\n    double total = 0.0;\n    for (int f = 1; f <= 3; ++f) {\n        if (cnt[f] > 0) {\n            double mean_r = sum_r[f] / cnt[f];\n            double mean_c = sum_c[f] / cnt[f];\n            total += (sum_r2[f] + sum_c2[f]) -\n                     (sum_r[f] * sum_r[f] + sum_c[f] * sum_c[f]) / cnt[f];\n        }\n    }\n    return total;\n}\n\n// ------------------------------------------------------------\n// helper to convert grid to string for memoization\nstring grid_to_string(const Grid& g) {\n    string s;\n    s.reserve(100);\n    for (int r = 0; r < 10; ++r) {\n        for (int c = 0; c < 10; ++c) {\n            s.push_back('0' + g[r][c]);\n        }\n    }\n    return s;\n}\n\n// ------------------------------------------------------------\n// recursive expectimax for remaining \u2264 4 candies, with memoization\ndouble expected_score(const Grid& grid, int next_idx,\n                      unordered_map<string, double>& memo) {\n    if (next_idx > 100) {\n        return compute_sum_squares(grid);\n    }\n\n    string key = grid_to_string(grid) + \":\" + to_string(next_idx);\n    auto it = memo.find(key);\n    if (it != memo.end()) {\n        return it->second;\n    }\n\n    // collect empty cells\n    vector<pair<int, int>> empties;\n    for (int r = 0; r < 10; ++r)\n        for (int c = 0; c < 10; ++c)\n            if (grid[r][c] == 0)\n                empties.emplace_back(r, c);\n\n    int E = empties.size();\n    double total = 0.0;\n\n    for (auto [r, c] : empties) {\n        // place the next candy\n        Grid g2 = grid;\n        g2[r][c] = flavors[next_idx];\n\n        // choose the best direction for this placement\n        double best = -1.0;\n        for (char dir : {'F', 'B', 'L', 'R'}) {\n            Grid g3 = tilt(g2, dir);\n            double val = expected_score(g3, next_idx + 1, memo);\n            if (val > best) best = val;\n        }\n        total += best;\n    }\n\n    double result = total / E;\n    memo[key] = result;\n    return result;\n}\n\n// ------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // read all flavors\n    for (int i = 1; i <= 100; ++i) {\n        cin >> flavors[i];\n    }\n\n    Grid grid = {};  // initially empty\n    const int SAMPLES = 12; // increased for better estimation\n    const double SPREAD_WEIGHT = 0.1; // weight for spread penalty\n\n    for (int t = 1; t <= 100; ++t) {\n        int p;\n        cin >> p;\n\n        // place the t\u2011th candy in the p\u2011th empty cell (row\u2011major order)\n        int cnt = 0;\n        int r_place = -1, c_place = -1;\n        for (int r = 0; r < 10; ++r) {\n            for (int c = 0; c < 10; ++c) {\n                if (grid[r][c] == 0) {\n                    ++cnt;\n                    if (cnt == p) {\n                        r_place = r;\n                        c_place = c;\n                        break;\n                    }\n                }\n            }\n            if (cnt == p) break;\n        }\n        grid[r_place][c_place] = flavors[t];\n\n        // last tilt does nothing \u2013 output any direction and finish\n        if (t == 100) {\n            cout << 'F' << endl;\n            return 0;\n        }\n\n        int remaining = 100 - t;  // candies still to be placed after this step\n        char best_dir;\n        Grid best_grid;\n\n        if (remaining <= 4) {\n            // deep evaluation using expectimax with memoization\n            double best_val = -1.0;\n            for (char dir : {'F', 'B', 'L', 'R'}) {\n                Grid after_tilt = tilt(grid, dir);\n                unordered_map<string, double> memo;\n                double val = expected_score(after_tilt, t + 1, memo);\n                if (val > best_val) {\n                    best_val = val;\n                    best_dir = dir;\n                    best_grid = after_tilt;\n                }\n            }\n        } else {\n            // Monte Carlo lookahead with enhanced evaluation\n            double best_expected = -1.0;\n            for (char dir : {'F', 'B', 'L', 'R'}) {\n                Grid after_tilt = tilt(grid, dir);\n\n                // collect empty cells\n                vector<pair<int, int>> empties;\n                for (int r = 0; r < 10; ++r)\n                    for (int c = 0; c < 10; ++c)\n                        if (after_tilt[r][c] == 0)\n                            empties.emplace_back(r, c);\n\n                if (empties.empty()) {\n                    continue; // should not happen when remaining > 0\n                }\n\n                double total = 0.0;\n                for (int s = 0; s < SAMPLES; ++s) {\n                    // choose a random empty cell\n                    uniform_int_distribution<int> dist(0, empties.size() - 1);\n                    int idx = dist(rng);\n                    auto [r, c] = empties[idx];\n\n                    Grid g2 = after_tilt;\n                    g2[r][c] = flavors[t + 1]; // next candy\n\n                    // evaluate the best next tilt using combined score\n                    double best_score = -1e9;\n                    for (char dir2 : {'F', 'B', 'L', 'R'}) {\n                        Grid g3 = tilt(g2, dir2);\n                        int sum_sq = compute_sum_squares(g3);\n                        double spread = compute_spread(g3);\n                        double score = sum_sq - SPREAD_WEIGHT * spread;\n                        if (score > best_score) best_score = score;\n                    }\n                    total += best_score;\n                }\n\n                double expected = total / SAMPLES;\n                if (expected > best_expected) {\n                    best_expected = expected;\n                    best_dir = dir;\n                    best_grid = after_tilt;\n                }\n            }\n\n            // Fallback: if no direction was chosen (shouldn't happen), use greedy\n            if (best_expected < 0) {\n                int best_sum_sq = -1;\n                double best_spread = 1e9;\n                for (char dir : {'F', 'B', 'L', 'R'}) {\n                    Grid after_tilt = tilt(grid, dir);\n                    int sum_sq = compute_sum_squares(after_tilt);\n                    double spread = compute_spread(after_tilt);\n                    if (sum_sq > best_sum_sq ||\n                        (sum_sq == best_sum_sq && spread < best_spread)) {\n                        best_sum_sq = sum_sq;\n                        best_spread = spread;\n                        best_dir = dir;\n                        best_grid = after_tilt;\n                    }\n                }\n            }\n        }\n\n        cout << best_dir << endl;\n        grid = best_grid;\n    }\n\n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <string>\n#include <cmath>\n#include <cassert>\n#include <Eigen/Dense>\n\nusing namespace std;\nusing namespace Eigen;\n\n// Compute sorted eigenvalues of adjacency matrix\nvector<double> compute_eigenvalues(const vector<vector<bool>>& adj, int N) {\n    MatrixXd mat(N, N);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            mat(i, j) = adj[i][j] ? 1.0 : 0.0;\n        }\n    }\n    SelfAdjointEigenSolver<MatrixXd> solver(mat);\n    VectorXd eigenvalues = solver.eigenvalues();\n    vector<double> result(eigenvalues.data(), eigenvalues.data() + eigenvalues.size());\n    sort(result.begin(), result.end(), greater<double>());\n    return result;\n}\n\nint main() {\n    // Problem parameters\n    int M;\n    double epsilon;\n    cin >> M >> epsilon;\n\n    // Fixed design choices\n    const int N = 30;                     // number of vertices\n    const int T = N * (N - 1) / 2;        // number of possible edges\n    const int TRIALS = 500;               // number of noise trials for precomputation\n    const double EIG_WEIGHT = 0.7;        // increased weight for eigenvalue distance\n\n    // ------------------------------------------------------------\n    // 1. Precompute all vertex pairs in lexicographic order\n    // ------------------------------------------------------------\n    vector<pair<int, int>> pairs;\n    pairs.reserve(T);\n    for (int i = 0; i < N; ++i)\n        for (int j = i + 1; j < N; ++j)\n            pairs.emplace_back(i, j);\n    assert(pairs.size() == T);\n\n    // ------------------------------------------------------------\n    // 2. Generate M random graphs with edge probability p_i = i/(M-1)\n    // ------------------------------------------------------------\n    // Random generator for graph construction (deterministic seed)\n    mt19937 rng_graph(12345);\n    uniform_real_distribution<double> dist_graph(0.0, 1.0);\n\n    // Storage: adjacency matrices and the output strings\n    vector<vector<vector<bool>>> adj(M, vector<vector<bool>>(N, vector<bool>(N, false)));\n    vector<string> graph_strings(M);\n\n    for (int idx = 0; idx < M; ++idx) {\n        double p = (M > 1) ? double(idx) / (M - 1) : 0.0;   // edge probability for this graph\n        string s(T, '0');\n        for (int e = 0; e < T; ++e) {\n            auto [u, v] = pairs[e];\n            if (dist_graph(rng_graph) < p) {\n                adj[idx][u][v] = true;\n                s[e] = '1';\n            }\n        }\n        graph_strings[idx] = s;\n    }\n\n    // ------------------------------------------------------------\n    // 3. Output the chosen N and the M graphs\n    // ------------------------------------------------------------\n    cout << N << endl;\n    for (int i = 0; i < M; ++i)\n        cout << graph_strings[i] << endl;\n    cout.flush();\n\n    // ------------------------------------------------------------\n    // 4. Precompute mean and variance of sorted degree sequences AND eigenvalues\n    //    under the noise model (edge flips with probability epsilon)\n    // ------------------------------------------------------------\n    // Random generator for noise simulation (different seed)\n    mt19937 rng_noise(54321);\n    uniform_real_distribution<double> dist_noise(0.0, 1.0);\n\n    // Means and variances for degree sequences\n    vector<vector<double>> mean_deg(M, vector<double>(N, 0.0));\n    vector<vector<double>> var_deg(M, vector<double>(N, 0.0));\n    \n    // Means and variances for eigenvalues\n    vector<vector<double>> mean_eig(M, vector<double>(N, 0.0));\n    vector<vector<double>> var_eig(M, vector<double>(N, 0.0));\n\n    for (int g = 0; g < M; ++g) {\n        // For degree sequences\n        vector<double> sum_deg(N, 0.0), sum_sq_deg(N, 0.0);\n        // For eigenvalues\n        vector<double> sum_eig(N, 0.0), sum_sq_eig(N, 0.0);\n        \n        for (int trial = 0; trial < TRIALS; ++trial) {\n            // Build noisy adjacency matrix\n            vector<vector<bool>> noisy_adj(N, vector<bool>(N, false));\n            for (int e = 0; e < T; ++e) {\n                auto [u, v] = pairs[e];\n                bool present = adj[g][u][v];\n                // flip with probability epsilon\n                if (dist_noise(rng_noise) < epsilon)\n                    present = !present;\n                if (present) {\n                    noisy_adj[u][v] = true;\n                    noisy_adj[v][u] = true;\n                }\n            }\n            \n            // Compute degree sequence\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_adj[i][j]) {\n                        deg[i]++;\n                        deg[j]++;\n                    }\n                }\n            }\n            sort(deg.begin(), deg.end());\n            for (int j = 0; j < N; ++j) {\n                sum_deg[j] += deg[j];\n                sum_sq_deg[j] += deg[j] * deg[j];\n            }\n            \n            // Compute eigenvalues\n            vector<double> eigenvalues = compute_eigenvalues(noisy_adj, N);\n            for (int j = 0; j < N; ++j) {\n                sum_eig[j] += eigenvalues[j];\n                sum_sq_eig[j] += eigenvalues[j] * eigenvalues[j];\n            }\n        }\n        \n        // Compute statistics for degree sequences\n        for (int j = 0; j < N; ++j) {\n            mean_deg[g][j] = sum_deg[j] / TRIALS;\n            double variance = sum_sq_deg[j] / TRIALS - mean_deg[g][j] * mean_deg[g][j];\n            if (variance < 1e-9) variance = 1e-9;\n            var_deg[g][j] = variance;\n        }\n        \n        // Compute statistics for eigenvalues\n        for (int j = 0; j < N; ++j) {\n            mean_eig[g][j] = sum_eig[j] / TRIALS;\n            double variance = sum_sq_eig[j] / TRIALS - mean_eig[g][j] * mean_eig[g][j];\n            if (variance < 1e-9) variance = 1e-9;\n            var_eig[g][j] = variance;\n        }\n    }\n\n    // ------------------------------------------------------------\n    // 5. Process the 100 queries\n    // ------------------------------------------------------------\n    for (int q = 0; q < 100; ++q) {\n        string H_str;\n        cin >> H_str;\n        assert(H_str.size() == T);\n\n        // Build adjacency matrix for H\n        vector<vector<bool>> H_adj(N, vector<bool>(N, false));\n        for (int e = 0; e < T; ++e) {\n            if (H_str[e] == '1') {\n                auto [u, v] = pairs[e];\n                H_adj[u][v] = true;\n                H_adj[v][u] = true;\n            }\n        }\n        \n        // Compute degree sequence of H\n        vector<int> deg_H(N, 0);\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) {\n                if (H_adj[i][j]) {\n                    deg_H[i]++;\n                    deg_H[j]++;\n                }\n            }\n        }\n        sort(deg_H.begin(), deg_H.end());\n        \n        // Compute eigenvalues of H\n        vector<double> eig_H = compute_eigenvalues(H_adj, N);\n\n        // Find the graph with smallest combined chi\u2011squared distance\n        int best_graph = 0;\n        double best_dist = 1e100;\n        for (int g = 0; g < M; ++g) {\n            // Degree sequence distance\n            double dist_deg = 0.0;\n            for (int j = 0; j < N; ++j) {\n                double diff = deg_H[j] - mean_deg[g][j];\n                dist_deg += (diff * diff) / var_deg[g][j];\n            }\n            \n            // Eigenvalue distance\n            double dist_eig = 0.0;\n            for (int j = 0; j < N; ++j) {\n                double diff = eig_H[j] - mean_eig[g][j];\n                dist_eig += (diff * diff) / var_eig[g][j];\n            }\n            \n            // Combined distance with increased weight for eigenvalues\n            double total_dist = dist_deg + EIG_WEIGHT * dist_eig;\n            \n            if (total_dist < best_dist) {\n                best_dist = total_dist;\n                best_graph = g;\n            }\n        }\n\n        cout << best_graph << endl;\n        cout.flush();\n    }\n\n    return 0;\n}","ahc017":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cassert>\n#include <limits>\n\nusing namespace std;\n\nstruct Point {\n    double x, y;\n    double dist(const Point& other) const {\n        double dx = x - other.x;\n        double dy = y - other.y;\n        return sqrt(dx*dx + dy*dy);\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n\n    vector<pair<int, int>> edges(M);\n    vector<long long> weights(M);\n    for (int i = 0; i < M; ++i) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        --u; --v;\n        edges[i] = {u, v};\n        weights[i] = w;\n    }\n\n    // Read coordinates\n    vector<Point> pts(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> pts[i].x >> pts[i].y;\n    }\n\n    // Compute edge midpoints\n    vector<Point> mid(M);\n    for (int i = 0; i < M; ++i) {\n        auto [u, v] = edges[i];\n        mid[i].x = (pts[u].x + pts[v].x) * 0.5;\n        mid[i].y = (pts[u].y + pts[v].y) * 0.5;\n    }\n\n    // Greedy assignment: farthest-first to maximize spatial dispersion per day\n    vector<int> day_of(M, -1);\n    vector<int> cnt(D, 0);\n    vector<vector<Point>> day_points(D);  // store midpoints of edges assigned to each day\n\n    // Process edges in random order for diversity\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    shuffle(order.begin(), order.end(), rng);\n\n    const double INF_DIST = 1e9;\n\n    for (int idx : order) {\n        int best_day = -1;\n        double best_min_dist = -1.0;\n        for (int d = 0; d < D; ++d) {\n            if (cnt[d] >= K) continue;\n            double min_dist = INF_DIST;\n            if (day_points[d].empty()) {\n                min_dist = INF_DIST;  // large value to prioritize empty days\n            } else {\n                // Compute minimum distance from current edge's midpoint to any edge already in day d\n                for (const Point& p : day_points[d]) {\n                    double dist = mid[idx].dist(p);\n                    if (dist < min_dist) min_dist = dist;\n                }\n            }\n            if (min_dist > best_min_dist) {\n                best_min_dist = min_dist;\n                best_day = d;\n            }\n        }\n        assert(best_day != -1);\n        day_of[idx] = best_day;\n        cnt[best_day]++;\n        day_points[best_day].push_back(mid[idx]);\n    }\n\n    // Output assignments (1-indexed days)\n    for (int i = 0; i < M; ++i) {\n        cout << day_of[i] + 1 << (i == M-1 ? \"\\n\" : \" \");\n    }\n\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAXD = 14;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    int D;\n    cin >> D;\n    vector<string> f1(D), r1(D), f2(D), r2(D);\n    for (int i = 0; i < D; ++i) cin >> f1[i];\n    for (int i = 0; i < D; ++i) cin >> r1[i];\n    for (int i = 0; i < D; ++i) cin >> f2[i];\n    for (int i = 0; i < D; ++i) cin >> r2[i];\n    \n    // Convert to boolean arrays for quick access\n    bool f1b[D][D] = {}, r1b[D][D] = {};\n    bool f2b[D][D] = {}, r2b[D][D] = {};\n    for (int z = 0; z < D; ++z) {\n        for (int x = 0; x < D; ++x) {\n            f1b[z][x] = (f1[z][x] == '1');\n            f2b[z][x] = (f2[z][x] == '1');\n        }\n        for (int y = 0; y < D; ++y) {\n            r1b[z][y] = (r1[z][y] == '1');\n            r2b[z][y] = (r2[z][y] == '1');\n        }\n    }\n    \n    // Allowed regions for each object\n    bool allowed1[D][D][D] = {};\n    bool allowed2[D][D][D] = {};\n    // Intersection I\n    bool I[D][D][D] = {};\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                allowed1[x][y][z] = f1b[z][x] && r1b[z][y];\n                allowed2[x][y][z] = f2b[z][x] && r2b[z][y];\n                I[x][y][z] = allowed1[x][y][z] && allowed2[x][y][z];\n            }\n        }\n    }\n    \n    // Connected components of I\n    int compI[D][D][D];\n    memset(compI, -1, sizeof(compI));\n    int num_components_I = 0;\n    const int dx[6] = {1,-1,0,0,0,0};\n    const int dy[6] = {0,0,1,-1,0,0};\n    const int dz[6] = {0,0,0,0,1,-1};\n    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 (I[x][y][z] && compI[x][y][z] == -1) {\n                    queue<tuple<int,int,int>> q;\n                    q.push({x, y, z});\n                    compI[x][y][z] = num_components_I;\n                    while (!q.empty()) {\n                        auto [cx, cy, cz] = q.front(); q.pop();\n                        for (int d = 0; d < 6; ++d) {\n                            int nx = cx + dx[d];\n                            int ny = cy + dy[d];\n                            int nz = cz + dz[d];\n                            if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D &&\n                                I[nx][ny][nz] && compI[nx][ny][nz] == -1) {\n                                compI[nx][ny][nz] = num_components_I;\n                                q.push({nx, ny, nz});\n                            }\n                        }\n                    }\n                    ++num_components_I;\n                }\n            }\n        }\n    }\n    \n    // Initialize objects with all cells from I (shared)\n    bool obj1[D][D][D] = {};\n    bool obj2[D][D][D] = {};\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 (I[x][y][z]) {\n                    obj1[x][y][z] = true;\n                    obj2[x][y][z] = true;\n                }\n    \n    // For each object, add minimal extra cells to satisfy silhouettes\n    for (int obj_id = 0; obj_id < 2; ++obj_id) {\n        bool (*obj)[D][D] = (obj_id == 0) ? obj1 : obj2;\n        bool (*fb)[D] = (obj_id == 0) ? f1b : f2b;\n        bool (*rb)[D] = (obj_id == 0) ? r1b : r2b;\n        for (int z = 0; z < D; ++z) {\n            // Lists of required x and y\n            vector<int> X, Y;\n            for (int x = 0; x < D; ++x) if (fb[z][x]) X.push_back(x);\n            for (int y = 0; y < D; ++y) if (rb[z][y]) Y.push_back(y);\n            \n            // Determine which x and y are already covered by I\n            vector<bool> x_covered(D, false), y_covered(D, false);\n            for (int x : X) {\n                for (int y = 0; y < D; ++y) {\n                    if (I[x][y][z]) {\n                        x_covered[x] = true;\n                        break;\n                    }\n                }\n            }\n            for (int y : Y) {\n                for (int x = 0; x < D; ++x) {\n                    if (I[x][y][z]) {\n                        y_covered[y] = true;\n                        break;\n                    }\n                }\n            }\n            \n            vector<int> X_rem, Y_rem;\n            for (int x : X) if (!x_covered[x]) X_rem.push_back(x);\n            for (int y : Y) if (!y_covered[y]) Y_rem.push_back(y);\n            \n            int a = X_rem.size(), b = Y_rem.size();\n            int M = max(a, b);\n            // Add cells to cover remaining requirements\n            if (a >= b) {\n                for (int i = 0; i < b; ++i) {\n                    int x = X_rem[i], y = Y_rem[i];\n                    obj[x][y][z] = true;\n                }\n                for (int i = b; i < a; ++i) {\n                    int x = X_rem[i];\n                    int y = Y.empty() ? 0 : Y[0]; // Y non\u2011empty because silhouette guarantees at least one y\n                    obj[x][y][z] = true;\n                }\n            } else {\n                for (int i = 0; i < a; ++i) {\n                    int x = X_rem[i], y = Y_rem[i];\n                    obj[x][y][z] = true;\n                }\n                for (int i = a; i < b; ++i) {\n                    int y = Y_rem[i];\n                    int x = X.empty() ? 0 : X[0];\n                    obj[x][y][z] = true;\n                }\n            }\n        }\n    }\n    \n    // Shared blocks are exactly the connected components of I\n    // Assign IDs to shared components\n    vector<int> comp_id(num_components_I);\n    int cur_id = 1;\n    for (int i = 0; i < num_components_I; ++i) comp_id[i] = cur_id++;\n    \n    // Prepare output arrays\n    vector<vector<vector<int>>> b1(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    vector<vector<vector<int>>> b2(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    \n    // Fill shared blocks in both objects\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 (I[x][y][z]) {\n                    int id = comp_id[compI[x][y][z]];\n                    b1[x][y][z] = id;\n                    b2[x][y][z] = id;\n                }\n    \n    // Unit blocks for non\u2011shared cells in obj1\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 (obj1[x][y][z] && !I[x][y][z])\n                    b1[x][y][z] = cur_id++;\n    \n    // Unit blocks for non\u2011shared cells in obj2\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 (obj2[x][y][z] && !I[x][y][z])\n                    b2[x][y][z] = cur_id++;\n    \n    // Output\n    int total_blocks = cur_id - 1;\n    cout << total_blocks << \"\\n\";\n    // b1\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                cout << b1[x][y][z];\n                if (x == D-1 && y == D-1 && z == D-1) cout << \"\\n\";\n                else cout << \" \";\n            }\n    // b2\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                cout << b2[x][y][z];\n                if (x == D-1 && y == D-1 && z == D-1) cout << \"\\n\";\n                else cout << \" \";\n            }\n    \n    return 0;\n}","ahc020":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <climits>\n#include <numeric>\n\nusing namespace std;\ntypedef long long ll;\n\nstruct Candidate {\n    int type;      // 0: active vertex, 1: inactive vertex\n    int idx;       // vertex index\n    int new_P;     // new output strength\n    ll cost;       // total cost of the action\n    int count;     // number of newly covered residents\n    int first_idx; // first index in sorted_res[idx] to cover\n    int last_idx;  // last index (exclusive) in sorted_res[idx] to cover\n};\n\n// integer ceil(sqrt(x))\nint ceil_sqrt(ll x) {\n    int r = sqrt(x);\n    while ((ll)r * r < x) ++r;\n    return r;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\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\n    vector<int> u(M), v(M), w(M);\n    vector<vector<pair<int, int>>> adj(N); // (neighbor, edge index)\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]].emplace_back(v[j], j);\n        adj[v[j]].emplace_back(u[j], j);\n    }\n\n    vector<int> a(K), b(K);\n    for (int k = 0; k < K; ++k) cin >> a[k] >> b[k];\n\n    // squared distances from vertices to residents\n    vector<vector<ll>> dist2(N, vector<ll>(K));\n    for (int i = 0; i < N; ++i) {\n        for (int k = 0; k < K; ++k) {\n            ll dx = x[i] - a[k];\n            ll dy = y[i] - b[k];\n            dist2[i][k] = dx * dx + dy * dy;\n        }\n    }\n\n    // for each vertex, residents sorted by distance\n    vector<vector<int>> sorted_res(N);\n    for (int i = 0; i < N; ++i) {\n        sorted_res[i].resize(K);\n        iota(sorted_res[i].begin(), sorted_res[i].end(), 0);\n        sort(sorted_res[i].begin(), sorted_res[i].end(),\n             [&](int k1, int k2) { return dist2[i][k1] < dist2[i][k2]; });\n    }\n\n    // state\n    vector<bool> covered(K, false);\n    int covered_cnt = 0;\n    vector<int> P(N, 0);\n    vector<int> next_uncovered(N, 0); // for active vertices\n    vector<bool> is_vertex_active(N, false);\n    is_vertex_active[0] = true; // station 1 (index 0)\n    vector<bool> is_edge_on(M, false);\n\n    // main loop\n    while (covered_cnt < K) {\n        // Dijkstra to compute additional connection costs\n        vector<ll> dist_conn(N, LLONG_MAX);\n        vector<int> prev_vertex(N, -1), prev_edge(N, -1);\n        priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<>> pq;\n        for (int i = 0; i < N; ++i) {\n            if (is_vertex_active[i]) {\n                dist_conn[i] = 0;\n                pq.emplace(0, i);\n            }\n        }\n        while (!pq.empty()) {\n            auto [d, u_idx] = pq.top(); pq.pop();\n            if (d != dist_conn[u_idx]) continue;\n            for (auto [v_idx, e_idx] : adj[u_idx]) {\n                ll cost = is_edge_on[e_idx] ? 0 : w[e_idx];\n                if (dist_conn[u_idx] + cost < dist_conn[v_idx]) {\n                    dist_conn[v_idx] = dist_conn[u_idx] + cost;\n                    prev_vertex[v_idx] = u_idx;\n                    prev_edge[v_idx] = e_idx;\n                    pq.emplace(dist_conn[v_idx], v_idx);\n                }\n            }\n        }\n\n        // evaluate all possible actions\n        Candidate best;\n        bool found = false;\n\n        // actions on active vertices - consider up to 7 candidate P values\n        for (int i = 0; i < N; ++i) {\n            if (!is_vertex_active[i]) continue;\n            // move to first uncovered resident\n            while (next_uncovered[i] < K && covered[sorted_res[i][next_uncovered[i]]])\n                ++next_uncovered[i];\n            if (next_uncovered[i] == K) continue;\n\n            int first = next_uncovered[i];\n            // Consider up to 7 candidate P values\n            for (int offset = 0; offset < 7 && first + offset < K; ++offset) {\n                int idx = first + offset;\n                int k = sorted_res[i][idx];\n                ll d2 = dist2[i][k];\n                int new_P = ceil_sqrt(d2);\n                if (new_P > 5000) continue;\n                ll new_P2 = (ll)new_P * new_P;\n                ll old_P2 = (ll)P[i] * P[i];\n\n                // count newly covered residents with d2 <= new_P2\n                int cnt = 0;\n                int last = first;\n                for (int j = first; j < K; ++j) {\n                    int res = sorted_res[i][j];\n                    if (dist2[i][res] > new_P2) break;\n                    if (!covered[res]) ++cnt;\n                    last = j + 1;\n                }\n                if (cnt == 0) continue;\n\n                ll cost_inc = new_P2 - old_P2;\n                // Use weighted efficiency: cost / (cnt^1.5) to favor covering more residents\n                double efficiency = (double)cost_inc / pow(cnt, 1.5);\n                double best_efficiency = found ? (double)best.cost / pow(best.count, 1.5) : 1e18;\n                if (efficiency < best_efficiency) {\n                    best = {0, i, new_P, cost_inc, cnt, first, last};\n                    found = true;\n                }\n            }\n        }\n\n        // actions on inactive vertices - consider up to 7 candidate P values\n        for (int i = 0; i < N; ++i) {\n            if (is_vertex_active[i]) continue;\n            if (dist_conn[i] == LLONG_MAX) continue; // should not happen\n\n            // find first uncovered resident\n            int first_idx = 0;\n            while (first_idx < K && covered[sorted_res[i][first_idx]]) ++first_idx;\n            if (first_idx == K) continue;\n\n            // Consider up to 7 candidate P values\n            for (int offset = 0; offset < 7 && first_idx + offset < K; ++offset) {\n                int idx = first_idx + offset;\n                int k = sorted_res[i][idx];\n                ll d2 = dist2[i][k];\n                int new_P = ceil_sqrt(d2);\n                if (new_P > 5000) continue;\n                ll new_P2 = (ll)new_P * new_P;\n\n                // count uncovered residents within new_P\n                int cnt = 0;\n                int last_idx = first_idx;\n                for (int j = first_idx; j < K; ++j) {\n                    int res = sorted_res[i][j];\n                    if (dist2[i][res] > new_P2) break;\n                    if (!covered[res]) ++cnt;\n                    last_idx = j + 1;\n                }\n                if (cnt == 0) continue;\n\n                ll total_cost = dist_conn[i] + new_P2;\n                // Use weighted efficiency: cost / (cnt^1.5)\n                double efficiency = (double)total_cost / pow(cnt, 1.5);\n                double best_efficiency = found ? (double)best.cost / pow(best.count, 1.5) : 1e18;\n                if (efficiency < best_efficiency) {\n                    best = {1, i, new_P, total_cost, cnt, first_idx, last_idx};\n                    found = true;\n                }\n            }\n        }\n\n        if (!found) break; // should not happen\n\n        // apply the best action\n        if (best.type == 0) { // active vertex\n            int i = best.idx;\n            P[i] = best.new_P;\n            for (int j = best.first_idx; j < best.last_idx; ++j) {\n                int res = sorted_res[i][j];\n                if (!covered[res]) {\n                    covered[res] = true;\n                    ++covered_cnt;\n                }\n            }\n            next_uncovered[i] = best.last_idx;\n        } else { // inactive vertex\n            int j = best.idx;\n            // turn on edges along the shortest path\n            int cur = j;\n            while (!is_vertex_active[cur]) {\n                int e = prev_edge[cur];\n                if (!is_edge_on[e]) is_edge_on[e] = true;\n                int prev = prev_vertex[cur];\n                is_vertex_active[cur] = true;\n                next_uncovered[cur] = 0; // newly activated, P=0 initially\n                P[cur] = 0;\n                cur = prev;\n            }\n            P[j] = best.new_P;\n            for (int idx = best.first_idx; idx < best.last_idx; ++idx) {\n                int res = sorted_res[j][idx];\n                if (!covered[res]) {\n                    covered[res] = true;\n                    ++covered_cnt;\n                }\n            }\n            next_uncovered[j] = best.last_idx;\n        }\n    }\n\n    // output\n    for (int i = 0; i < N; ++i) {\n        cout << P[i] << (i + 1 == N ? \"\\n\" : \" \");\n    }\n    for (int j = 0; j < M; ++j) {\n        cout << (is_edge_on[j] ? 1 : 0) << (j + 1 == M ? \"\\n\" : \" \");\n    }\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30; // fixed pyramid size\n\nint main() {\n    // read input\n    vector<vector<int>> a(N);\n    for (int x = 0; x < N; ++x) {\n        a[x].resize(x + 1);\n        for (int y = 0; y <= x; ++y) {\n            cin >> a[x][y];\n        }\n    }\n\n    vector<array<int, 4>> ops; // stores swaps (x1,y1,x2,y2)\n\n    // swap two adjacent balls and record the operation\n    auto do_swap = [&](int x1, int y1, int x2, int y2) {\n        swap(a[x1][y1], a[x2][y2]);\n        ops.push_back({x1, y1, x2, y2});\n    };\n\n    // sift down a value starting from (x,y) until heap property holds\n    auto sift = [&](int x, int y) {\n        while (x < N - 1) { // while not a leaf\n            int x_left = x + 1, y_left = y;      // left child\n            int x_right = x + 1, y_right = y + 1; // right child\n            // choose the child with the smaller value\n            int nx, ny;\n            if (a[x_left][y_left] <= a[x_right][y_right]) {\n                nx = x_left; ny = y_left;\n            } else {\n                nx = x_right; ny = y_right;\n            }\n            if (a[x][y] > a[nx][ny]) {\n                do_swap(x, y, nx, ny);\n                x = nx; y = ny; // continue sifting with the moved value\n            } else {\n                break;\n            }\n        }\n    };\n\n    // process rows from bottom to top\n    for (int x = N - 2; x >= 0; --x) {\n        // collect nodes in this row and sort by value descending\n        vector<pair<int, int>> nodes;\n        for (int y = 0; y <= x; ++y) {\n            nodes.emplace_back(a[x][y], y);\n        }\n        sort(nodes.begin(), nodes.end(), greater<pair<int, int>>());\n        // sift each node in that order\n        for (auto& p : nodes) {\n            sift(x, p.second);\n        }\n    }\n\n    // output\n    cout << ops.size() << '\\n';\n    for (auto& sw : ops) {\n        cout << sw[0] << ' ' << sw[1] << ' ' << sw[2] << ' ' << sw[3] << '\\n';\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int D = 9;  // Grid size is fixed at 9\nint entrance_r = 0, entrance_c = (D - 1) / 2;  // (0,4)\n\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\n\nbool obstacle[D][D] = {false};\nbool occupied[D][D] = {false};\nint container_num[D][D];       // -1 if no container\n\nint dist[D][D];                // BFS distance from entrance\nint cell_rank[D][D];           // index in the sorted order (0..M-1)\nvector<pair<int, int>> order;  // free squares sorted by (dist, row, col)\nint M;                         // number of containers\n\n// ---------- preprocessing ----------\nvoid compute_bfs_distances() {\n    for (int i = 0; i < D; ++i)\n        for (int j = 0; j < D; ++j)\n            dist[i][j] = -1;\n\n    queue<pair<int, int>> q;\n    dist[entrance_r][entrance_c] = 0;\n    q.push({entrance_r, entrance_c});\n\n    while (!q.empty()) {\n        auto [r, c] = q.front(); q.pop();\n        for (int d = 0; d < 4; ++d) {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n            if (obstacle[nr][nc]) continue;\n            if (dist[nr][nc] == -1) {\n                dist[nr][nc] = dist[r][c] + 1;\n                q.push({nr, nc});\n            }\n        }\n    }\n}\n\nvoid build_order() {\n    order.clear();\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            if (i == entrance_r && j == entrance_c) continue;\n            if (obstacle[i][j]) continue;\n            order.push_back({i, j});\n        }\n    }\n    sort(order.begin(), order.end(),\n         [](const auto& a, const auto& b) {\n             int da = dist[a.first][a.second];\n             int db = dist[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    M = order.size();\n    for (int i = 0; i < D; ++i)\n        for (int j = 0; j < D; ++j)\n            cell_rank[i][j] = -1;\n    for (int i = 0; i < M; ++i) {\n        auto [r, c] = order[i];\n        cell_rank[r][c] = i;\n    }\n}\n\n// ---------- helper for articulation test ----------\n// temporarily block (br,bc) and count reachable empty squares from entrance\nint count_reachable_without(int br, int bc, bool is_empty[D][D]) {\n    bool original = is_empty[br][bc];\n    is_empty[br][bc] = false;          // block the square\n\n    bool visited[D][D] = {false};\n    int cnt = 0;\n    queue<pair<int, int>> q;\n    q.push({entrance_r, entrance_c});\n    visited[entrance_r][entrance_c] = true;\n    ++cnt;\n\n    while (!q.empty()) {\n        auto [r, c] = q.front(); q.pop();\n        for (int d = 0; d < 4; ++d) {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n            if (!is_empty[nr][nc]) continue;\n            if (!visited[nr][nc]) {\n                visited[nr][nc] = true;\n                q.push({nr, nc});\n                ++cnt;\n            }\n        }\n    }\n\n    is_empty[br][bc] = original;       // restore\n    return cnt;\n}\n\n// ---------- main ----------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    int input_D;  // We'll read D but ignore it since it's always 9\n    cin >> input_D >> N;\n\n    // read obstacles\n    for (int i = 0; i < N; ++i) {\n        int r, c;\n        cin >> r >> c;\n        obstacle[r][c] = true;\n    }\n\n    // preprocessing\n    compute_bfs_distances();\n    build_order();\n\n    // initialise container numbers\n    for (int i = 0; i < D; ++i)\n        for (int j = 0; j < D; ++j)\n            container_num[i][j] = -1;\n\n    // ---------- placement phase ----------\n    for (int step = 0; step < M; ++step) {\n        int t;\n        cin >> t;\n\n        // build current empty mask (entrance + all non\u2011occupied, non\u2011obstacle)\n        bool is_empty[D][D] = {false};\n        for (int i = 0; i < D; ++i)\n            for (int j = 0; j < D; ++j) {\n                if (obstacle[i][j]) is_empty[i][j] = false;\n                else if (occupied[i][j]) is_empty[i][j] = false;\n                else is_empty[i][j] = true;      // includes entrance\n            }\n\n        // collect all reachable empty squares (except entrance)\n        vector<pair<int, int>> reachable;\n        bool visited[D][D] = {false};\n        queue<pair<int, int>> q;\n        q.push({entrance_r, entrance_c});\n        visited[entrance_r][entrance_c] = true;\n\n        while (!q.empty()) {\n            auto [r, c] = q.front(); q.pop();\n            if (!(r == entrance_r && c == entrance_c))\n                reachable.push_back({r, c});\n            for (int d = 0; d < 4; ++d) {\n                int nr = r + dr[d], nc = c + dc[d];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (!is_empty[nr][nc]) continue;\n                if (!visited[nr][nc]) {\n                    visited[nr][nc] = true;\n                    q.push({nr, nc});\n                }\n            }\n        }\n\n        // among reachable squares, keep only those that are not articulation points\n        vector<pair<int, int>> safe;\n        int total_empty = reachable.size() + 1;   // +1 for entrance\n        for (auto& s : reachable) {\n            int r = s.first, c = s.second;\n            int cnt = count_reachable_without(r, c, is_empty);\n            if (cnt == total_empty - 1)          // graph stays connected\n                safe.push_back(s);\n        }\n\n        // choose a square\n        pair<int, int> chosen;\n        if (!safe.empty()) {\n            // pick the safe square whose rank is closest to t\n            int best_diff = 1e9, best_dist = 1e9;\n            for (auto& s : safe) {\n                int r = s.first, c = s.second;\n                int rnk = cell_rank[r][c];\n                int diff = abs(rnk - t);\n                int d = dist[r][c];\n                if (diff < best_diff || (diff == best_diff && d < best_dist)) {\n                    best_diff = diff;\n                    best_dist = d;\n                    chosen = s;\n                }\n            }\n        } else {\n            // fallback \u2013 should never happen, but choose the closest reachable square\n            int best_dist = 1e9;\n            for (auto& s : reachable) {\n                int d = dist[s.first][s.second];\n                if (d < best_dist) {\n                    best_dist = d;\n                    chosen = s;\n                }\n            }\n        }\n\n        // output placement\n        cout << chosen.first << \" \" << chosen.second << endl;\n\n        // update state\n        occupied[chosen.first][chosen.second] = true;\n        container_num[chosen.first][chosen.second] = t;\n    }\n\n    // ---------- retrieval phase ----------\n    int remaining = M;\n    while (remaining > 0) {\n        // rebuild empty mask\n        bool is_empty[D][D] = {false};\n        for (int i = 0; i < D; ++i)\n            for (int j = 0; j < D; ++j) {\n                if (obstacle[i][j]) is_empty[i][j] = false;\n                else if (occupied[i][j]) is_empty[i][j] = false;\n                else is_empty[i][j] = true;\n            }\n\n        // find all containers adjacent to an empty square\n        vector<pair<int, int>> accessible;\n        for (int i = 0; i < D; ++i) {\n            for (int j = 0; j < D; ++j) {\n                if (!occupied[i][j]) continue;\n                bool adj = false;\n                for (int d = 0; d < 4; ++d) {\n                    int ni = i + dr[d], nj = j + dc[d];\n                    if (ni < 0 || ni >= D || nj < 0 || nj >= D) continue;\n                    if (is_empty[ni][nj]) {\n                        adj = true;\n                        break;\n                    }\n                }\n                if (adj) accessible.push_back({i, j});\n            }\n        }\n\n        // choose the one with the smallest number\n        auto best = accessible[0];\n        int best_num = container_num[best.first][best.second];\n        for (auto& p : accessible) {\n            int num = container_num[p.first][p.second];\n            if (num < best_num) {\n                best_num = num;\n                best = p;\n            }\n        }\n\n        // output retrieval\n        cout << best.first << \" \" << best.second << endl;\n\n        // remove it\n        occupied[best.first][best.second] = false;\n        container_num[best.first][best.second] = -1;\n        --remaining;\n    }\n\n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <utility>\n#include <algorithm>\n#include <random>\n#include <cstring>\nusing namespace std;\n\nconst int MAXN = 50;\nconst int MAXM = 100;\n\nint n, m;\nint cur[MAXN][MAXN];\nint colorCount[MAXM+1] = {0};          // 0..100\nint edgeCount[MAXM+1][MAXM+1] = {0};   // only upper triangular used\nbool required[MAXM+1][MAXM+1] = {false};\nbool allowed[MAXM+1] = {false};        // colors that may touch 0\n\nconst int dx[4] = {1, -1, 0, 0};\nconst int dy[4] = {0, 0, 1, -1};\n\n// Check if we can safely recolor (i,j) to 0\nbool isRemovable(int i, int j) {\n    int c = cur[i][j];\n    if (c == 0) return false;\n    if (!allowed[c]) return false;\n    if (colorCount[c] <= 1) return false;\n\n    int cnt[MAXM+1] = {0};   // count of neighbor colors (0..m)\n    bool adj_to_0 = false;\n    int same_color_neighbors = 0;\n\n    // examine four neighbours (outside counts as color 0)\n    for (int d = 0; d < 4; ++d) {\n        int ni = i + dx[d], nj = j + dy[d];\n        int col;\n        if (ni >= 0 && ni < n && nj >= 0 && nj < n)\n            col = cur[ni][nj];\n        else\n            col = 0;   // outside\n        cnt[col]++;\n        if (col == 0) adj_to_0 = true;\n        else if (!allowed[col]) return false;   // would create forbidden 0\u2013col adjacency\n        if (col == c) same_color_neighbors++;\n    }\n    if (!adj_to_0) return false;\n\n    // Edge count constraints\n    for (int d = 0; d <= m; ++d) {\n        if (cnt[d] == 0 || d == c) continue;\n        if (d == 0) {\n            // need at least one edge between c and 0 after removal\n            if (edgeCount[0][c] - cnt[0] < 1) return false;\n        } else {\n            int a = min(c, d), b = max(c, d);\n            if (required[a][b] && edgeCount[a][b] - cnt[d] < 1) return false;\n        }\n    }\n\n    // Connectivity of color c after removal\n    if (same_color_neighbors == 0) return false;   // should not happen\n    if (same_color_neighbors == 1) return true;    // leaf \u2013 safe\n\n    // BFS on color c, excluding (i,j)\n    int start_i = -1, start_j = -1;\n    for (int d = 0; d < 4; ++d) {\n        int ni = i + dx[d], nj = j + dy[d];\n        if (ni >= 0 && ni < n && nj >= 0 && nj < n && cur[ni][nj] == c) {\n            start_i = ni; start_j = nj; break;\n        }\n    }\n    if (start_i == -1) return false;   // no neighbour of same colour \u2013 impossible\n\n    bool visited[MAXN][MAXN] = {false};\n    queue<pair<int,int>> q;\n    visited[start_i][start_j] = true;\n    q.push({start_i, start_j});\n    int count = 0;\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        count++;\n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (nx >= 0 && nx < n && ny >= 0 && ny < n && !visited[nx][ny] &&\n                cur[nx][ny] == c && !(nx == i && ny == j)) {\n                visited[nx][ny] = true;\n                q.push({nx, ny});\n            }\n        }\n    }\n    return (count == colorCount[c] - 1);\n}\n\n// Actually recolor (i,j) from its colour c to 0\nvoid removeCell(int i, int j) {\n    int c = cur[i][j];\n    // Update edge counts for all incident edges\n    for (int d = 0; d < 4; ++d) {\n        int ni = i + dx[d], nj = j + dy[d];\n        int col;\n        if (ni >= 0 && ni < n && nj >= 0 && nj < n)\n            col = cur[ni][nj];\n        else\n            col = 0;   // outside\n        if (col == c) continue;   // no edge between same colours\n        // Remove edge c\u2013col\n        if (col == 0) {\n            edgeCount[0][c]--;\n        } else {\n            int a = min(c, col), b = max(c, col);\n            edgeCount[a][b]--;\n        }\n        // After recoloring, add edge 0\u2013col (if col != 0)\n        if (col != 0) {\n            edgeCount[0][col]++;\n        }\n    }\n    // Perform the recolor\n    cur[i][j] = 0;\n    colorCount[c]--;\n    colorCount[0]++;\n}\n\n// Compute colorCount and edgeCount from current grid\nvoid computeCounts() {\n    memset(colorCount, 0, sizeof(colorCount));\n    memset(edgeCount, 0, sizeof(edgeCount));\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c = cur[i][j];\n            colorCount[c]++;\n            // down\n            if (i+1 < n) {\n                int d = cur[i+1][j];\n                if (c != d) {\n                    int a = min(c,d), b = max(c,d);\n                    edgeCount[a][b]++;\n                }\n            }\n            // right\n            if (j+1 < n) {\n                int d = cur[i][j+1];\n                if (c != d) {\n                    int a = min(c,d), b = max(c,d);\n                    edgeCount[a][b]++;\n                }\n            }\n            // outside sides\n            if (i == 0) edgeCount[0][c]++;\n            if (i == n-1) edgeCount[0][c]++;\n            if (j == 0) edgeCount[0][c]++;\n            if (j == n-1) edgeCount[0][c]++;\n        }\n    }\n}\n\n// Perform erosion with given shuffle option and seed, returns number of 0 cells\nint erosion(bool do_shuffle, int seed) {\n    vector<pair<int,int>> cells;\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cells.emplace_back(i, j);\n        }\n    }\n    mt19937 rng(seed);\n    bool changed;\n    do {\n        if (do_shuffle) {\n            shuffle(cells.begin(), cells.end(), rng);\n        }\n        changed = false;\n        for (auto [i, j] : cells) {\n            if (cur[i][j] == 0) continue;\n            if (isRemovable(i, j)) {\n                removeCell(i, j);\n                changed = true;\n            }\n        }\n    } while (changed);\n    return colorCount[0];\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Read original map\n    int orig_cur[MAXN][MAXN];\n    cin >> n >> m;\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cin >> orig_cur[i][j];\n        }\n    }\n\n    // Compute allowed and required from original map (they remain constant)\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (i == 0 || i == n-1 || j == 0 || j == n-1)\n                allowed[orig_cur[i][j]] = true;\n        }\n    }\n    // required for 0-c from boundary\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (i == 0 || i == n-1 || j == 0 || j == n-1) {\n                int c = orig_cur[i][j];\n                required[0][c] = true;\n            }\n        }\n    }\n    // required for c-d from internal edges\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c = orig_cur[i][j];\n            if (i+1 < n) {\n                int d = orig_cur[i+1][j];\n                if (c != d) {\n                    int a = min(c,d), b = max(c,d);\n                    required[a][b] = true;\n                }\n            }\n            if (j+1 < n) {\n                int d = orig_cur[i][j+1];\n                if (c != d) {\n                    int a = min(c,d), b = max(c,d);\n                    required[a][b] = true;\n                }\n            }\n        }\n    }\n\n    int best_E = -1;\n    int best_cur[MAXN][MAXN];\n    vector<pair<bool, int>> attempts = {\n        {false, 0},      // row-major order\n        {true, 12345},   // random shuffle with seed 12345\n        {true, 67890},   // random shuffle with seed 67890\n        {true, 11111},   // random shuffle with seed 11111\n        {true, 22222}    // random shuffle with seed 22222\n    };\n\n    for (auto [do_shuffle, seed] : attempts) {\n        // Copy original grid to cur\n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                cur[i][j] = orig_cur[i][j];\n            }\n        }\n        computeCounts();\n        int E = erosion(do_shuffle, seed);\n        if (E > best_E) {\n            best_E = E;\n            for (int i = 0; i < n; ++i) {\n                for (int j = 0; j < n; ++j) {\n                    best_cur[i][j] = cur[i][j];\n                }\n            }\n        }\n    }\n\n    // Output the best map\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (j) cout << ' ';\n            cout << best_cur[i][j];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, D, Q;\nvector<vector<int>> cmp;   // -2 unknown, -1: <, 0: =, 1: >\nint queries_used = 0;\n\n// Compare items i and j\nint compare_items(int i, int j) {\n    if (i == j) return 0;\n    if (cmp[i][j] != -2) return cmp[i][j];\n    cout << \"1 1 \" << i << \" \" << j << endl;\n    cout.flush();\n    string res;\n    cin >> res;\n    ++queries_used;\n    int ans;\n    if (res == \"<\") ans = -1;\n    else if (res == \">\") ans = 1;\n    else ans = 0;\n    cmp[i][j] = ans;\n    cmp[j][i] = -ans;\n    return ans;\n}\n\n// Compare two groups by total weight\nint compare_groups(const vector<int>& A, const vector<int>& B) {\n    if (A.empty() || B.empty()) return 0;\n    if (queries_used >= Q) return 0; // Fallback if no queries left\n    cout << A.size() << \" \" << B.size();\n    for (int x : A) cout << \" \" << x;\n    for (int x : B) cout << \" \" << x;\n    cout << endl;\n    cout.flush();\n    string res;\n    cin >> res;\n    ++queries_used;\n    if (res == \"<\") return -1;\n    else if (res == \">\") return 1;\n    else return 0;\n}\n\n// Merge sort for items\nvoid merge_sort(vector<int>& arr, int left, int right) {\n    if (left >= right || queries_used >= Q) return;\n    int mid = (left + right) / 2;\n    merge_sort(arr, left, mid);\n    merge_sort(arr, mid+1, right);\n    \n    vector<int> temp;\n    int i = left, j = mid+1;\n    while (i <= mid && j <= right && queries_used < Q) {\n        int res = compare_items(arr[i], arr[j]);\n        if (res <= 0) {\n            temp.push_back(arr[i++]);\n        } else {\n            temp.push_back(arr[j++]);\n        }\n    }\n    while (i <= mid) temp.push_back(arr[i++]);\n    while (j <= right) temp.push_back(arr[j++]);\n    \n    for (int k = 0; k < (int)temp.size(); ++k) {\n        arr[left + k] = temp[k];\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cout.tie(nullptr);\n\n    cin >> N >> D >> Q;\n    cmp.assign(N, vector<int>(N, -2));\n\n    // Estimate assignment cost: N * log2(D) comparisons\n    int logD = 0;\n    for (int t = D; t > 1; t >>= 1) ++logD;\n    logD = max(1, logD); // Ensure at least 1\n    int assign_budget = N * (logD + 1); // Conservative estimate\n    \n    int sort_budget = Q;\n    bool use_group_comparisons = (Q >= assign_budget);\n    if (use_group_comparisons) {\n        sort_budget = max(0, Q - assign_budget);\n    }\n\n    // Create item indices and sort using merge sort\n    vector<int> items(N);\n    iota(items.begin(), items.end(), 0);\n    \n    // Shuffle for better average-case performance\n    mt19937 rng(123456);\n    shuffle(items.begin(), items.end(), rng);\n    \n    // Perform merge sort with budget\n    merge_sort(items, 0, N-1);\n    \n    // If we didn't finish sorting due to budget, do insertion sort on remaining\n    if (queries_used < sort_budget) {\n        // Partial insertion sort to improve order\n        for (int i = 1; i < N && queries_used < sort_budget; ++i) {\n            int key = items[i];\n            int j = i - 1;\n            while (j >= 0 && queries_used < sort_budget) {\n                int res = compare_items(key, items[j]);\n                if (res < 0) {\n                    items[j+1] = items[j];\n                    --j;\n                } else break;\n            }\n            items[j+1] = key;\n        }\n    }\n\n    // Now items are sorted in ascending order (lightest to heaviest)\n    // We'll assign from heaviest to lightest\n    \n    vector<vector<int>> groups(D);\n    \n    // Seed groups with D heaviest items\n    for (int i = 0; i < D && i < N; ++i) {\n        int item = items[N-1-i]; // heaviest first\n        groups[i].push_back(item);\n    }\n\n    // Prepare items to assign (remaining heaviest to lightest)\n    vector<int> to_assign;\n    for (int i = D; i < N; ++i) {\n        to_assign.push_back(items[N-1-i]);\n    }\n\n    int assigned_idx = 0;\n    if (use_group_comparisons && queries_used < Q) {\n        // Use heap for efficient group selection\n        auto cmp_groups = [&](int i, int j) {\n            return compare_groups(groups[i], groups[j]) > 0; // Min-heap by weight\n        };\n        priority_queue<int, vector<int>, decltype(cmp_groups)> pq(cmp_groups);\n        \n        for (int i = 0; i < D; ++i) pq.push(i);\n        \n        while (assigned_idx < (int)to_assign.size() && queries_used < Q) {\n            // Estimate cost: 2*logD comparisons for pop+push\n            if (queries_used + 2*logD > Q) break;\n            \n            int g = pq.top(); pq.pop();\n            groups[g].push_back(to_assign[assigned_idx++]);\n            pq.push(g);\n        }\n    }\n\n    // Assign any remaining items without comparisons (round-robin)\n    for (; assigned_idx < (int)to_assign.size(); ++assigned_idx) {\n        int g = assigned_idx % D;\n        groups[g].push_back(to_assign[assigned_idx]);\n    }\n\n    // Output assignment\n    vector<int> ans(N);\n    for (int g = 0; g < D; ++g) {\n        for (int item : groups[g]) {\n            ans[item] = g;\n        }\n    }\n\n    // Dummy queries if needed\n    while (queries_used < Q) {\n        cout << \"1 1 0 1\" << endl;\n        cout.flush();\n        string dummy;\n        cin >> dummy;\n        ++queries_used;\n    }\n\n    // Output final division\n    for (int i = 0; i < N; ++i) {\n        cout << ans[i];\n        if (i < N-1) cout << \" \";\n    }\n    cout << endl;\n    cout.flush();\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int n, m;\n    cin >> n >> m;\n    int k = n / m;\n    vector<vector<int>> stacks(m);\n    for (int i = 0; i < m; ++i) {\n        stacks[i].resize(k);\n        for (int j = 0; j < k; ++j) {\n            cin >> stacks[i][j];\n        }\n    }\n\n    vector<pair<int, int>> ops;\n\n    // Function to get target stack for a number (0-indexed)\n    auto target_stack = [&](int v) {\n        return (v - 1) / k;\n    };\n\n    for (int v = 1; v <= n; ++v) {\n        // locate box v\n        int cur = -1, pos = -1;\n        for (int i = 0; i < m; ++i) {\n            for (int j = 0; j < (int)stacks[i].size(); ++j) {\n                if (stacks[i][j] == v) {\n                    cur = i;\n                    pos = j;\n                    break;\n                }\n            }\n            if (cur != -1) break;\n        }\n\n        // v is on top -> extract directly\n        if (pos == (int)stacks[cur].size() - 1) {\n            ops.emplace_back(v, 0);\n            stacks[cur].pop_back();\n        } else {\n            // move the block above v\n            int w = stacks[cur][pos + 1];   // box directly above v\n            \n            // Find maximum value in the block and count target stacks\n            int max_in_block = -1;\n            vector<int> target_counts(m, 0);\n            for (int j = pos + 1; j < (int)stacks[cur].size(); ++j) {\n                int box = stacks[cur][j];\n                max_in_block = max(max_in_block, box);\n                target_counts[target_stack(box)]++;\n            }\n            \n            // Find the target stack with the most boxes in the block\n            int best_target = -1;\n            int max_count = 0;\n            for (int i = 0; i < m; ++i) {\n                if (target_counts[i] > max_count) {\n                    max_count = target_counts[i];\n                    best_target = i;\n                } else if (target_counts[i] == max_count && best_target != -1) {\n                    // Tie-break: choose the one with larger top\n                    int top_best = stacks[best_target].empty() ? -1 : stacks[best_target].back();\n                    int top_i = stacks[i].empty() ? -1 : stacks[i].back();\n                    if (top_i > top_best) {\n                        best_target = i;\n                    }\n                }\n            }\n            \n            // Choose destination stack with improved strategy\n            int dest = -1;\n            // First, prefer an empty stack\n            for (int i = 0; i < m; ++i) {\n                if (i != cur && stacks[i].empty()) {\n                    dest = i;\n                    break;\n                }\n            }\n            \n            if (dest == -1 && best_target != -1 && best_target != cur) {\n                // Consider moving to the best target stack if conditions are good\n                int top_target = stacks[best_target].empty() ? -1 : stacks[best_target].back();\n                if (top_target > max_in_block) {\n                    dest = best_target;\n                }\n            }\n            \n            if (dest == -1) {\n                // Look for stacks where top > max_in_block\n                // Among these, choose the one with smallest top\n                int best_top = INT_MAX;\n                for (int i = 0; i < m; ++i) {\n                    if (i == cur || stacks[i].empty()) continue;\n                    int top_val = stacks[i].back();\n                    if (top_val > max_in_block && top_val < best_top) {\n                        best_top = top_val;\n                        dest = i;\n                    }\n                }\n                \n                // If no such stack, choose stack with largest top\n                if (dest == -1) {\n                    int max_top = -1;\n                    for (int i = 0; i < m; ++i) {\n                        if (i == cur) continue;\n                        if (!stacks[i].empty()) {\n                            int top_val = stacks[i].back();\n                            if (top_val > max_top) {\n                                max_top = top_val;\n                                dest = i;\n                            }\n                        }\n                    }\n                }\n            }\n            \n            // If still no destination (shouldn't happen), use current stack's first empty or something\n            if (dest == -1) {\n                for (int i = 0; i < m; ++i) {\n                    if (i != cur) {\n                        dest = i;\n                        break;\n                    }\n                }\n            }\n\n            // perform the move\n            ops.emplace_back(w, dest + 1);\n            // extract the block from cur\n            vector<int> moved(stacks[cur].begin() + pos + 1, stacks[cur].end());\n            stacks[cur].erase(stacks[cur].begin() + pos + 1, stacks[cur].end());\n            // append to destination\n            stacks[dest].insert(stacks[dest].end(), moved.begin(), moved.end());\n\n            // now v is on top -> extract it\n            ops.emplace_back(v, 0);\n            stacks[cur].pop_back();\n        }\n    }\n\n    // output the operation sequence\n    for (auto& p : ops) {\n        cout << p.first << \" \" << p.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAX_MOVES = 100000;\n\n// directions: up, down, left, right\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\nconst char move_char[] = {'U', 'D', 'L', 'R'};\nconst char opposite_char[] = {'D', 'U', 'R', 'L'};\n\nint N;\nvector<string> h, v;\nvector<vector<int>> d;\n\n// adjacency list: for each cell (i,j) list of (ni,nj,move_char)\nvector<vector<vector<tuple<int,int,char>>>> adj;\n\n// for coverage\nvector<vector<bool>> visited;\n\n// distances to (0,0)\nvector<vector<int>> dist0;\n\nchar get_opposite(char c) {\n    for (int k = 0; k < 4; ++k)\n        if (move_char[k] == c) return opposite_char[k];\n    return '?';\n}\n\nvoid build_graph() {\n    adj.assign(N, vector<vector<tuple<int,int,char>>>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            // down\n            if (i+1 < N && h[i][j] == '0')\n                adj[i][j].emplace_back(i+1, j, 'D');\n            // up\n            if (i-1 >= 0 && h[i-1][j] == '0')\n                adj[i][j].emplace_back(i-1, j, 'U');\n            // right\n            if (j+1 < N && v[i][j] == '0')\n                adj[i][j].emplace_back(i, j+1, 'R');\n            // left\n            if (j-1 >= 0 && v[i][j-1] == '0')\n                adj[i][j].emplace_back(i, j-1, 'L');\n        }\n    }\n}\n\nvoid compute_dist0() {\n    dist0.assign(N, vector<int>(N, -1));\n    queue<pair<int,int>> q;\n    q.emplace(0, 0);\n    dist0[0][0] = 0;\n    while (!q.empty()) {\n        auto [i,j] = q.front(); q.pop();\n        for (auto [ni, nj, move] : adj[i][j]) {\n            if (dist0[ni][nj] == -1) {\n                dist0[ni][nj] = dist0[i][j] + 1;\n                q.emplace(ni, nj);\n            }\n        }\n    }\n}\n\n// returns the base route (greedy DFS) and updates last_visit, current position, and time\nstring generate_base_route(vector<vector<int>>& last_visit, int& t, pair<int,int>& cur) {\n    visited.assign(N, vector<bool>(N, false));\n    string route;\n    stack<pair<int,int>> st;\n    stack<char> move_stack;\n    st.emplace(0, 0);\n    visited[0][0] = true;\n    last_visit[0][0] = 0;\n    t = 0;\n    cur = {0,0};\n\n    while (!st.empty()) {\n        auto [i,j] = st.top();\n        // find the unvisited neighbor with highest d\n        int best_d = -1;\n        char best_move = '?';\n        int best_ni = -1, best_nj = -1;\n        for (auto [ni, nj, move] : adj[i][j]) {\n            if (!visited[ni][nj]) {\n                if (d[ni][nj] > best_d) {\n                    best_d = d[ni][nj];\n                    best_move = move;\n                    best_ni = ni;\n                    best_nj = nj;\n                }\n            }\n        }\n        if (best_move != '?') {\n            // move to the best neighbor\n            visited[best_ni][best_nj] = true;\n            route += best_move;\n            ++t;\n            last_visit[best_ni][best_nj] = t;\n            cur = {best_ni, best_nj};\n            move_stack.push(best_move);\n            st.emplace(best_ni, best_nj);\n        } else {\n            // backtrack\n            st.pop();\n            if (!move_stack.empty()) {\n                char move_back = get_opposite(move_stack.top());\n                move_stack.pop();\n                route += move_back;\n                ++t;\n                auto [pi, pj] = st.top();\n                last_visit[pi][pj] = t;\n                cur = {pi, pj};\n            }\n        }\n    }\n    return route;\n}\n\n// greedy phase: returns the additional moves\nstring greedy_phase(pair<int,int> cur, int t, vector<vector<int>>& last_visit) {\n    string extra;\n    while (t < MAX_MOVES) {\n        int remaining = MAX_MOVES - t;\n        int ci = cur.first, cj = cur.second;\n        // if we must go directly to (0,0)\n        if (dist0[ci][cj] == remaining) {\n            // find neighbor with dist0 = remaining-1\n            for (auto [ni, nj, move] : adj[ci][cj]) {\n                if (dist0[ni][nj] == remaining - 1) {\n                    extra += move;\n                    ++t;\n                    last_visit[ni][nj] = t;\n                    cur = {ni, nj};\n                    break;\n                }\n            }\n        } else {\n            // try two-step lookahead if we have at least 2 moves left\n            if (remaining >= 2) {\n                int best_total = -1;\n                char best_move1 = '?', best_move2 = '?';\n                int best_n1i = -1, best_n1j = -1;\n                int best_n2i = -1, best_n2j = -1;\n                for (auto [n1i, n1j, move1] : adj[ci][cj]) {\n                    if (dist0[n1i][n1j] <= remaining - 1) {\n                        int dirt1 = (t - last_visit[n1i][n1j]) * d[n1i][n1j];\n                        // for each possible second move from n1\n                        for (auto [n2i, n2j, move2] : adj[n1i][n1j]) {\n                            if (dist0[n2i][n2j] <= remaining - 2) {\n                                int dirt2 = (t + 1 - last_visit[n2i][n2j]) * d[n2i][n2j];\n                                int total = dirt1 + dirt2;\n                                if (total > best_total) {\n                                    best_total = total;\n                                    best_move1 = move1;\n                                    best_move2 = move2;\n                                    best_n1i = n1i;\n                                    best_n1j = n1j;\n                                    best_n2i = n2i;\n                                    best_n2j = n2j;\n                                }\n                            }\n                        }\n                    }\n                }\n                if (best_move1 != '?') {\n                    // execute the first move\n                    extra += best_move1;\n                    ++t;\n                    last_visit[best_n1i][best_n1j] = t;\n                    cur = {best_n1i, best_n1j};\n                    // execute the second move\n                    extra += best_move2;\n                    ++t;\n                    last_visit[best_n2i][best_n2j] = t;\n                    cur = {best_n2i, best_n2j};\n                    continue; // go to next iteration\n                }\n            }\n            // fallback to one-step greedy\n            int best_dirt = -1;\n            int best_dist0 = INT_MAX;\n            char best_move = '?';\n            int best_ni = -1, best_nj = -1;\n            for (auto [ni, nj, move] : adj[ci][cj]) {\n                if (dist0[ni][nj] <= remaining - 1) {\n                    int dirt = (t - last_visit[ni][nj]) * d[ni][nj];\n                    if (dirt > best_dirt || (dirt == best_dirt && dist0[ni][nj] < best_dist0)) {\n                        best_dirt = dirt;\n                        best_dist0 = dist0[ni][nj];\n                        best_move = move;\n                        best_ni = ni;\n                        best_nj = nj;\n                    }\n                }\n            }\n            if (best_move != '?') {\n                extra += best_move;\n                ++t;\n                last_visit[best_ni][best_nj] = t;\n                cur = {best_ni, best_nj};\n            } else {\n                // fallback: move to any neighbor that reduces dist0\n                for (auto [ni, nj, move] : adj[ci][cj]) {\n                    if (dist0[ni][nj] < dist0[ci][cj]) {\n                        extra += move;\n                        ++t;\n                        last_visit[ni][nj] = t;\n                        cur = {ni, nj};\n                        break;\n                    }\n                }\n            }\n        }\n    }\n    return extra;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    h.resize(N-1);\n    for (int i = 0; i < N-1; ++i) cin >> h[i];\n    v.resize(N);\n    for (int i = 0; i < N; ++i) cin >> v[i];\n    d.assign(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> d[i][j];\n\n    build_graph();\n    compute_dist0();\n\n    vector<vector<int>> last_visit(N, vector<int>(N, 0));\n    int t = 0;\n    pair<int,int> cur = {0,0};\n    string base_route = generate_base_route(last_visit, t, cur);\n\n    string extra_route = greedy_phase(cur, t, last_visit);\n\n    cout << base_route << extra_route << endl;\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int INF = 1e9;\n\nstruct Solver {\n    int N, M, start_idx;\n    vector<int> xs, ys;\n    vector<vector<int>> cells;\n    vector<string> patterns;\n    vector<vector<char>> ov;\n\n    Solver(int N, int M, int start_idx, const vector<string>& grid, const vector<string>& patterns)\n        : N(N), M(M), start_idx(start_idx), patterns(patterns) {\n        int total = N * N;\n        xs.resize(total);\n        ys.resize(total);\n        cells.resize(26);\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                int idx = i * N + j;\n                xs[idx] = i;\n                ys[idx] = j;\n                int ch = grid[i][j] - 'A';\n                cells[ch].push_back(idx);\n            }\n        }\n\n        ov.assign(M, vector<char>(M, 0));\n        for (int i = 0; i < M; ++i) {\n            for (int j = 0; j < M; ++j) {\n                if (i == j) continue;\n                const string &a = patterns[i], &b = patterns[j];\n                for (int k = 4; k >= 1; --k) {\n                    if (a.compare(5 - k, k, b, 0, k) == 0) {\n                        ov[i][j] = k;\n                        break;\n                    }\n                }\n            }\n        }\n    }\n\n    vector<int> greedy_order_from(int start) const {\n        vector<bool> used(M, false);\n        vector<int> order;\n        order.push_back(start);\n        used[start] = true;\n        for (int step = 1; step < M; ++step) {\n            int last = order.back();\n            int best_ov = -1, best_next = -1;\n            for (int j = 0; j < M; ++j) {\n                if (!used[j]) {\n                    int o = ov[last][j];\n                    if (o > best_ov) {\n                        best_ov = o;\n                        best_next = j;\n                    }\n                }\n            }\n            order.push_back(best_next);\n            used[best_next] = true;\n        }\n        return order;\n    }\n\n    vector<int> random_greedy_order_from(int start, mt19937& rng) const {\n        vector<bool> used(M, false);\n        vector<int> order;\n        order.push_back(start);\n        used[start] = true;\n        for (int step = 1; step < M; ++step) {\n            int last = order.back();\n            int best_ov = -1;\n            vector<int> candidates;\n            for (int j = 0; j < M; ++j) {\n                if (!used[j]) {\n                    int o = ov[last][j];\n                    if (o > best_ov) {\n                        best_ov = o;\n                        candidates.clear();\n                        candidates.push_back(j);\n                    } else if (o == best_ov) {\n                        candidates.push_back(j);\n                    }\n                }\n            }\n            uniform_int_distribution<int> dist(0, candidates.size() - 1);\n            int chosen = candidates[dist(rng)];\n            order.push_back(chosen);\n            used[chosen] = true;\n        }\n        return order;\n    }\n\n    pair<int, vector<int>> solve_order(const vector<int>& order) const {\n        string S;\n        S.reserve(5 * M);\n        S += patterns[order[0]];\n        for (size_t i = 1; i < order.size(); ++i) {\n            int prev = order[i - 1];\n            int cur = order[i];\n            int k = ov[prev][cur];\n            S += patterns[cur].substr(k);\n        }\n        int L = S.size();\n        int total_cells = N * N;\n\n        vector<int> dp_prev(total_cells, INF);\n        vector<int> dp_curr(total_cells, INF);\n        vector<short> prev_cell(L * total_cells, -1);\n\n        int first_ch = S[0] - 'A';\n        for (int v : cells[first_ch]) {\n            int d = abs(xs[start_idx] - xs[v]) + abs(ys[start_idx] - ys[v]);\n            dp_prev[v] = d + 1;\n            prev_cell[0 * total_cells + v] = -1;\n        }\n\n        for (int pos = 1; pos < L; ++pos) {\n            int cur_ch = S[pos] - 'A';\n            int prev_ch = S[pos - 1] - 'A';\n            const auto& prev_cells = cells[prev_ch];\n            const auto& cur_cells = cells[cur_ch];\n\n            fill(dp_curr.begin(), dp_curr.end(), INF);\n            for (int v : cur_cells) {\n                int best = INF;\n                short best_u = -1;\n                for (int u : prev_cells) {\n                    if (dp_prev[u] == INF) continue;\n                    int d = abs(xs[u] - xs[v]) + abs(ys[u] - ys[v]);\n                    int cand = dp_prev[u] + d;\n                    if (cand < best) {\n                        best = cand;\n                        best_u = u;\n                    }\n                }\n                dp_curr[v] = best + 1;\n                prev_cell[pos * total_cells + v] = best_u;\n            }\n            swap(dp_prev, dp_curr);\n        }\n\n        int last_ch = S[L - 1] - 'A';\n        int best_cost = INF, best_end = -1;\n        for (int v : cells[last_ch]) {\n            if (dp_prev[v] < best_cost) {\n                best_cost = dp_prev[v];\n                best_end = v;\n            }\n        }\n\n        vector<int> path(L);\n        int cur_cell = best_end;\n        for (int pos = L - 1; pos >= 0; --pos) {\n            path[pos] = cur_cell;\n            cur_cell = prev_cell[pos * total_cells + cur_cell];\n        }\n\n        return {best_cost, path};\n    }\n\n    vector<int> two_opt_improve(vector<int> order, int iterations, mt19937& rng) const {\n        int cur_cost = solve_order(order).first;\n        int n = order.size();\n        for (int iter = 0; iter < iterations; ++iter) {\n            int i = rng() % n;\n            int j = rng() % n;\n            if (i == j) continue;\n            if (i > j) swap(i, j);\n            // reverse segment [i, j]\n            reverse(order.begin() + i, order.begin() + j + 1);\n            int new_cost = solve_order(order).first;\n            if (new_cost < cur_cost) {\n                cur_cost = new_cost;\n            } else {\n                // revert\n                reverse(order.begin() + i, order.begin() + j + 1);\n            }\n        }\n        return order;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n    int si, sj;\n    cin >> si >> sj;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n    vector<string> patterns(M);\n    for (int k = 0; k < M; ++k) cin >> patterns[k];\n\n    Solver solver(N, M, si * N + sj, grid, patterns);\n\n    mt19937 rng(123456);\n    const int K = 10;  // Increased from 5 to 10\n\n    int best_cost = INF;\n    vector<int> best_order;\n\n    for (int start = 0; start < M; ++start) {\n        // Deterministic greedy\n        vector<int> order = solver.greedy_order_from(start);\n        auto [cost, path] = solver.solve_order(order);\n        if (cost < best_cost) {\n            best_cost = cost;\n            best_order = order;\n        }\n        reverse(order.begin(), order.end());\n        auto [cost_rev, path_rev] = solver.solve_order(order);\n        if (cost_rev < best_cost) {\n            best_cost = cost_rev;\n            best_order = order;\n        }\n\n        // Random greedy orders\n        for (int iter = 0; iter < K; ++iter) {\n            vector<int> rand_order = solver.random_greedy_order_from(start, rng);\n            auto [cost_rand, path_rand] = solver.solve_order(rand_order);\n            if (cost_rand < best_cost) {\n                best_cost = cost_rand;\n                best_order = rand_order;\n            }\n            reverse(rand_order.begin(), rand_order.end());\n            auto [cost_rand_rev, path_rand_rev] = solver.solve_order(rand_order);\n            if (cost_rand_rev < best_cost) {\n                best_cost = cost_rand_rev;\n                best_order = rand_order;\n            }\n        }\n    }\n\n    // Apply 2-opt local search to further improve the best order\n    mt19937 rng2(654321);  // Different seed for local search\n    best_order = solver.two_opt_improve(best_order, 2000, rng2);\n\n    auto [final_cost, final_path] = solver.solve_order(best_order);\n    for (int idx : final_path) {\n        int i = idx / N;\n        int j = idx % N;\n        cout << i << ' ' << j << '\\n';\n    }\n\n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <cmath>\n#include <numeric>\n#include <cstdint>\n#include <tuple>\n\nusing namespace std;\n\nstruct Placement {\n    vector<short> cells;          // indices of covered cells (0..N*N-1)\n    vector<uint8_t> contrib;      // contribution to each measurement\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cout.tie(nullptr);\n\n    int N, M;\n    double eps;\n    cin >> N >> M >> eps;\n    double alpha = 1.0 - 2.0 * eps;\n    double beta = eps;\n\n    // read shapes\n    vector<vector<pair<int, int>>> shape_cells(M);\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        shape_cells[k].resize(d);\n        for (int t = 0; t < d; ++t) {\n            cin >> shape_cells[k][t].first >> shape_cells[k][t].second;\n        }\n    }\n\n    // number of divine queries: enough for recovery but leave room for fallback drilling\n    int L = min(150, N * N - 10);\n    // random generator for subsets\n    mt19937 rng(123456);\n    uniform_real_distribution<double> prob(0.0, 1.0);\n\n    // generate random subsets and record which measurements contain each cell\n    vector<vector<int>> subsets(L);\n    vector<vector<int>> meas_including(N * N);\n    for (int l = 0; l < L; ++l) {\n        vector<int>& sub = subsets[l];\n        for (int idx = 0; idx < N * N; ++idx) {\n            if (prob(rng) < 0.5) {\n                sub.push_back(idx);\n                meas_including[idx].push_back(l);\n            }\n        }\n    }\n\n    // precompute all possible placements and their contributions\n    vector<vector<Placement>> placements(M);\n    for (int k = 0; k < M; ++k) {\n        const auto& cells = shape_cells[k];\n        int max_i = 0, max_j = 0;\n        for (auto& p : cells) {\n            max_i = max(max_i, p.first);\n            max_j = max(max_j, p.second);\n        }\n        int h = max_i + 1, w = max_j + 1;\n        for (int dx = 0; dx <= N - h; ++dx) {\n            for (int dy = 0; dy <= N - w; ++dy) {\n                Placement pl;\n                // compute cell indices\n                for (auto& p : cells) {\n                    int i = dx + p.first;\n                    int j = dy + p.second;\n                    pl.cells.push_back(i * N + j);\n                }\n                // compute contribution vector\n                pl.contrib.assign(L, 0);\n                for (int idx : pl.cells) {\n                    for (int l : meas_including[idx]) {\n                        pl.contrib[l]++;\n                    }\n                }\n                placements[k].push_back(move(pl));\n            }\n        }\n    }\n\n    // perform divine queries\n    vector<double> z_vals(L);\n    for (int l = 0; l < L; ++l) {\n        int k = subsets[l].size();\n        cout << \"q \" << k;\n        for (int idx : subsets[l]) {\n            int i = idx / N, j = idx % N;\n            cout << ' ' << i << ' ' << j;\n        }\n        cout << endl;\n        int y;\n        cin >> y;\n        z_vals[l] = (y - beta * k) / alpha;\n    }\n\n    // ----- Greedy OMP to obtain an initial assignment -----\n    vector<int> assignment(M, -1);\n    vector<double> residual = z_vals;\n    for (int iter = 0; iter < M; ++iter) {\n        double best_score = -1e100;\n        int best_shape = -1, best_place = -1;\n        for (int k = 0; k < M; ++k) {\n            if (assignment[k] != -1) continue;\n            const auto& plist = placements[k];\n            for (size_t p_idx = 0; p_idx < plist.size(); ++p_idx) {\n                const auto& p = plist[p_idx];\n                double dot = 0.0, norm2 = 0.0;\n                for (int l = 0; l < L; ++l) {\n                    double c = p.contrib[l];\n                    dot += residual[l] * c;\n                    norm2 += c * c;\n                }\n                if (norm2 == 0) continue;\n                double score = dot / sqrt(norm2);\n                if (score > best_score) {\n                    best_score = score;\n                    best_shape = k;\n                    best_place = p_idx;\n                }\n            }\n        }\n        // assign the best found\n        assignment[best_shape] = best_place;\n        const auto& p = placements[best_shape][best_place];\n        for (int l = 0; l < L; ++l) {\n            residual[l] -= p.contrib[l];\n        }\n    }\n\n    // ----- Simulated Annealing to refine the assignment -----\n    // current sums and error\n    vector<double> cur_sum(L, 0.0);\n    for (int k = 0; k < M; ++k) {\n        const auto& p = placements[k][assignment[k]];\n        for (int l = 0; l < L; ++l) cur_sum[l] += p.contrib[l];\n    }\n    double cur_err = 0.0;\n    for (int l = 0; l < L; ++l) {\n        double diff = z_vals[l] - cur_sum[l];\n        cur_err += diff * diff;\n    }\n\n    vector<int> best_assignment = assignment;\n    double best_err = cur_err;\n\n    const int SA_ITER = 50000;\n    const double INITIAL_TEMP = 1000.0;\n    const double COOLING = 0.9995;\n    double temp = INITIAL_TEMP;\n\n    mt19937 rng_sa(987654);\n    uniform_int_distribution<int> shape_dist(0, M - 1);\n    vector<uniform_int_distribution<int>> place_dist;\n    for (int k = 0; k < M; ++k) {\n        place_dist.emplace_back(0, placements[k].size() - 1);\n    }\n\n    for (int it = 0; it < SA_ITER; ++it) {\n        int k = shape_dist(rng_sa);\n        int old_idx = assignment[k];\n        int new_idx = place_dist[k](rng_sa);\n        if (new_idx == old_idx) continue;\n\n        const auto& p_old = placements[k][old_idx];\n        const auto& p_new = placements[k][new_idx];\n\n        double delta_err = 0.0;\n        for (int l = 0; l < L; ++l) {\n            double delta = (double)p_new.contrib[l] - (double)p_old.contrib[l];\n            double e_l = z_vals[l] - cur_sum[l];\n            delta_err += -2.0 * e_l * delta + delta * delta;\n        }\n\n        if (delta_err < 0 || uniform_real_distribution<double>(0, 1)(rng_sa) < exp(-delta_err / temp)) {\n            cur_err += delta_err;\n            for (int l = 0; l < L; ++l) {\n                cur_sum[l] += (p_new.contrib[l] - p_old.contrib[l]);\n            }\n            assignment[k] = new_idx;\n            if (cur_err < best_err) {\n                best_err = cur_err;\n                best_assignment = assignment;\n            }\n        }\n        temp *= COOLING;\n    }\n\n    // use the best assignment found\n    assignment = best_assignment;\n    // recompute current sums and error for this assignment\n    fill(cur_sum.begin(), cur_sum.end(), 0.0);\n    for (int k = 0; k < M; ++k) {\n        const auto& p = placements[k][assignment[k]];\n        for (int l = 0; l < L; ++l) cur_sum[l] += p.contrib[l];\n    }\n    cur_err = 0.0;\n    for (int l = 0; l < L; ++l) {\n        double diff = z_vals[l] - cur_sum[l];\n        cur_err += diff * diff;\n    }\n\n    // ----- Local hill climbing -----\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng_sa);\n        for (int k : order) {\n            int old_idx = assignment[k];\n            const auto& p_old = placements[k][old_idx];\n            for (size_t new_idx = 0; new_idx < placements[k].size(); ++new_idx) {\n                if (new_idx == static_cast<size_t>(old_idx)) continue;\n                const auto& p_new = placements[k][new_idx];\n                double delta_err = 0.0;\n                for (int l = 0; l < L; ++l) {\n                    double delta = (double)p_new.contrib[l] - (double)p_old.contrib[l];\n                    double e_l = z_vals[l] - cur_sum[l];\n                    delta_err += -2.0 * e_l * delta + delta * delta;\n                }\n                if (delta_err < -1e-9) {\n                    cur_err += delta_err;\n                    for (int l = 0; l < L; ++l) {\n                        double delta = (double)p_new.contrib[l] - (double)p_old.contrib[l];\n                        cur_sum[l] += delta;\n                    }\n                    assignment[k] = new_idx;\n                    improved = true;\n                    break; // go to next shape\n                }\n            }\n        }\n    }\n\n    // ----- Reconstruct the island from the assignment -----\n    vector<vector<int>> grid(N, vector<int>(N, 0));\n    for (int k = 0; k < M; ++k) {\n        const auto& p = placements[k][assignment[k]];\n        for (int idx : p.cells) {\n            int i = idx / N, j = idx % N;\n            grid[i][j]++;\n        }\n    }\n\n    // collect cells with positive oil reserves\n    vector<pair<int, int>> positive;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] > 0) {\n                positive.emplace_back(i, j);\n            }\n        }\n    }\n\n    // ----- First guess -----\n    cout << \"a \" << positive.size();\n    for (auto& p : positive) {\n        cout << ' ' << p.first << ' ' << p.second;\n    }\n    cout << endl;\n\n    int resp;\n    cin >> resp;\n    if (resp == 1) {\n        return 0;\n    }\n\n    // ----- Fallback: drill every cell -----\n    vector<bool> has_oil(N * N, false);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << \"q 1 \" << i << ' ' << j << endl;\n            int val;\n            cin >> val;\n            if (val > 0) {\n                has_oil[i * N + j] = true;\n            }\n        }\n    }\n\n    positive.clear();\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (has_oil[i * N + j]) {\n                positive.emplace_back(i, j);\n            }\n        }\n    }\n\n    cout << \"a \" << positive.size();\n    for (auto& p : positive) {\n        cout << ' ' << p.first << ' ' << p.second;\n    }\n    cout << endl;\n\n    cin >> resp; // should be 1\n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cstdint>\n\nusing namespace std;\nusing ll = long long;\n\nint W, D, N;\n\nll compute_shortage(const vector<int>& sorted_areas, const vector<int>& widths) {\n    ll cost = 0;\n    for (size_t i = 0; i < sorted_areas.size(); ++i) {\n        ll area = (ll)widths[i] * W;\n        if (sorted_areas[i] > area) {\n            cost += 100LL * (sorted_areas[i] - area);\n        }\n    }\n    return cost;\n}\n\nvector<int> compute_optimal_widths(const vector<int>& sorted_areas) {\n    vector<int> widths(N, 1);\n    int total = N;\n    for (int i = 0; i < N; ++i) {\n        int needed = (sorted_areas[i] + W - 1) / W;\n        int add = min(W - total, max(0, needed - 1));\n        widths[i] += add;\n        total += add;\n    }\n    if (total < W) {\n        widths[0] += (W - total);\n    }\n    return widths;\n}\n\nint compute_transition_cost(const vector<int>& widths1, const vector<int>& widths2) {\n    vector<int> cum1(N), cum2(N);\n    int sum1 = 0, sum2 = 0;\n    for (int i = 0; i < N; ++i) {\n        sum1 += widths1[i];\n        cum1[i] = sum1;\n        sum2 += widths2[i];\n        cum2[i] = sum2;\n    }\n    int move_count = 0;\n    for (int i = 0; i < N-1; ++i) {\n        if (cum1[i] != cum2[i]) {\n            move_count++;\n        }\n    }\n    return 2000 * move_count;\n}\n\nvector<int> improve_widths(const vector<int>& widths, const vector<int>& sorted_areas) {\n    vector<int> w = widths;\n    for (int step = 0; step < 10; ++step) {\n        bool improved = false;\n        for (int i = 0; i < N; ++i) {\n            for (int j = i+1; j < N; ++j) {\n                if (w[i] > w[j] && (ll)w[i] * W > sorted_areas[i] && (ll)w[j] * W < sorted_areas[j]) {\n                    if (w[i] - 1 >= w[j] + 1) {\n                        w[i]--;\n                        w[j]++;\n                        improved = true;\n                        break;\n                    }\n                }\n            }\n            if (improved) break;\n        }\n        if (!improved) break;\n    }\n    return w;\n}\n\nvoid output_rectangles(const vector<int>& widths, const vector<int>& orig_idx) {\n    vector<pair<int, int>> strip_lr(N);\n    int left = 0;\n    for (int i = 0; i < N; ++i) {\n        int right = left + widths[i];\n        strip_lr[i] = {left, right};\n        left = right;\n    }\n    vector<int> assign(N);\n    for (int i = 0; i < N; ++i) {\n        assign[orig_idx[i]] = i;\n    }\n    for (int k = 0; k < N; ++k) {\n        int strip_idx = assign[k];\n        auto [l, r] = strip_lr[strip_idx];\n        cout << \"0 \" << l << \" \" << W << \" \" << r << \"\\n\";\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    cin >> W >> D >> N;\n    \n    vector<vector<int>> a(D, vector<int>(N));\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            cin >> a[d][k];\n        }\n    }\n    \n    // day 0\n    vector<pair<int, int>> order(N);\n    for (int k = 0; k < N; ++k) {\n        order[k] = {a[0][k], k};\n    }\n    sort(order.begin(), order.end(), greater<pair<int, int>>());\n    vector<int> sorted_areas(N);\n    vector<int> orig_idx(N);\n    for (int i = 0; i < N; ++i) {\n        sorted_areas[i] = order[i].first;\n        orig_idx[i] = order[i].second;\n    }\n    \n    vector<int> current_widths = compute_optimal_widths(sorted_areas);\n    output_rectangles(current_widths, orig_idx);\n    \n    // subsequent days\n    for (int d = 1; d < D; ++d) {\n        // sort current day's areas\n        order.resize(N);\n        for (int k = 0; k < N; ++k) {\n            order[k] = {a[d][k], k};\n        }\n        sort(order.begin(), order.end(), greater<pair<int, int>>());\n        sorted_areas.resize(N);\n        orig_idx.resize(N);\n        for (int i = 0; i < N; ++i) {\n            sorted_areas[i] = order[i].first;\n            orig_idx[i] = order[i].second;\n        }\n        \n        // compute candidates\n        vector<int> greedy_widths = compute_optimal_widths(sorted_areas);\n        vector<int> local_widths = improve_widths(current_widths, sorted_areas);\n        \n        vector<vector<int>> candidates = {current_widths, greedy_widths, local_widths};\n        ll best_cost = 1e18;\n        vector<int> best_widths;\n        \n        for (const auto& cand : candidates) {\n            ll shortage = compute_shortage(sorted_areas, cand);\n            int trans_cost = compute_transition_cost(current_widths, cand);\n            ll total = shortage + trans_cost;\n            if (total < best_cost) {\n                best_cost = total;\n                best_widths = cand;\n            }\n        }\n        \n        output_rectangles(best_widths, orig_idx);\n        current_widths = best_widths;\n    }\n    \n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <array>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <cstdint>\n\nusing namespace std;\n\nconst int MOD = 998244353;\nconst int N = 9, M = 20, K = 81;\n\nstruct Operation {\n    int stamp, p, q;\n    vector<pair<int, int>> cells;\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m, k;\n    cin >> n >> m >> k;\n\n    vector<int64_t> cur(81);\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cin >> cur[i * 9 + j];\n        }\n    }\n\n    vector<array<array<int, 3>, 3>> stamps(m);\n    for (int s = 0; s < m; ++s) {\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                cin >> stamps[s][i][j];\n            }\n        }\n    }\n\n    vector<Operation> ops;\n    for (int s = 0; s < m; ++s) {\n        for (int p = 0; p <= n - 3; ++p) {\n            for (int q = 0; q <= n - 3; ++q) {\n                Operation op;\n                op.stamp = s;\n                op.p = p;\n                op.q = q;\n                for (int i = 0; i < 3; ++i) {\n                    for (int j = 0; j < 3; ++j) {\n                        int cell = (p + i) * 9 + (q + j);\n                        int val = stamps[s][i][j];\n                        op.cells.emplace_back(cell, val);\n                    }\n                }\n                ops.push_back(move(op));\n            }\n        }\n    }\n    const int num_ops = ops.size();\n\n    int64_t score = 0;\n    for (int i = 0; i < 81; ++i) score += cur[i] % MOD;\n\n    auto delta_add = [&](int id) -> int64_t {\n        int64_t d = 0;\n        for (auto [idx, val] : ops[id].cells) {\n            int64_t old_rem = cur[idx] % MOD;\n            int64_t new_val = cur[idx] + val;\n            int64_t new_rem = new_val % MOD;\n            d += new_rem - old_rem;\n        }\n        return d;\n    };\n\n    auto apply_add = [&](int id) {\n        for (auto [idx, val] : ops[id].cells) {\n            cur[idx] += val;\n        }\n    };\n\n    auto delta_remove = [&](int id) -> int64_t {\n        int64_t d = 0;\n        for (auto [idx, val] : ops[id].cells) {\n            int64_t old_rem = cur[idx] % MOD;\n            int64_t new_val = cur[idx] - val;\n            int64_t new_rem = new_val % MOD;\n            d += new_rem - old_rem;\n        }\n        return d;\n    };\n\n    auto apply_remove = [&](int id) {\n        for (auto [idx, val] : ops[id].cells) {\n            cur[idx] -= val;\n        }\n    };\n\n    // Greedy initial solution\n    vector<int> init_ops;\n    while (init_ops.size() < K) {\n        int best_id = -1;\n        int64_t best_delta = 0;\n        for (int id = 0; id < num_ops; ++id) {\n            int64_t d = delta_add(id);\n            if (d > best_delta) {\n                best_delta = d;\n                best_id = id;\n            }\n        }\n        if (best_delta <= 0) break;\n        apply_add(best_id);\n        init_ops.push_back(best_id);\n        score += best_delta;\n    }\n    \n    // Store initial state for restarts\n    vector<int64_t> init_cur = cur;\n    int64_t init_score = score;\n    \n    // Prepare for multi-restart SA\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> uni_real(0.0, 1.0);\n    \n    // Track best solution across restarts\n    vector<int> best_ops = init_ops;\n    int64_t best_score = init_score;\n    \n    const int num_restarts = 2;\n    const int iter_per_restart = 2'500'000;\n    const double T0 = 1e8;\n    \n    static int64_t contrib[81];\n    static vector<int> touched;\n    \n    for (int restart = 0; restart < num_restarts; ++restart) {\n        // Reset to initial greedy solution\n        cur = init_cur;\n        score = init_score;\n        vector<int> cur_ops = init_ops;\n        \n        // Reset contrib array\n        for (int i = 0; i < 81; ++i) contrib[i] = 0;\n        \n        double T = T0;\n        \n        // SA for this restart\n        for (int iter = 0; iter < iter_per_restart; ++iter) {\n            double r = uni_real(rng);\n            // Probabilities: 18% add, 18% remove, 64% replace\n            if (r < 0.18 && cur_ops.size() < K) {\n                // Add operation\n                int new_id = rng() % num_ops;\n                int64_t delta = delta_add(new_id);\n                if (delta > 0 || (delta <= 0 && exp(delta / T) > uni_real(rng))) {\n                    apply_add(new_id);\n                    cur_ops.push_back(new_id);\n                    score += delta;\n                }\n            } else if (r < 0.36 && !cur_ops.empty()) {\n                // Remove operation\n                int idx = rng() % cur_ops.size();\n                int old_id = cur_ops[idx];\n                int64_t delta = delta_remove(old_id);\n                if (delta > 0 || (delta <= 0 && exp(delta / T) > uni_real(rng))) {\n                    apply_remove(old_id);\n                    cur_ops[idx] = cur_ops.back();\n                    cur_ops.pop_back();\n                    score += delta;\n                }\n            } else if (!cur_ops.empty()) {\n                // Replace operation (64% chance)\n                int idx = rng() % cur_ops.size();\n                int old_id = cur_ops[idx];\n                int new_id = rng() % num_ops;\n                if (new_id == old_id) continue;\n\n                touched.clear();\n                for (auto [i, v] : ops[old_id].cells) {\n                    if (contrib[i] == 0) touched.push_back(i);\n                    contrib[i] -= v;\n                }\n                for (auto [i, v] : ops[new_id].cells) {\n                    if (contrib[i] == 0) touched.push_back(i);\n                    contrib[i] += v;\n                }\n\n                int64_t delta = 0;\n                for (int i : touched) {\n                    int64_t net = contrib[i];\n                    int64_t old_rem = cur[i] % MOD;\n                    int64_t new_val = cur[i] + net;\n                    int64_t new_rem = new_val % MOD;\n                    delta += new_rem - old_rem;\n                }\n\n                if (delta > 0 || (delta <= 0 && exp(delta / T) > uni_real(rng))) {\n                    for (int i : touched) {\n                        cur[i] += contrib[i];\n                    }\n                    cur_ops[idx] = new_id;\n                    score += delta;\n                }\n\n                for (int i : touched) {\n                    contrib[i] = 0;\n                }\n            }\n\n            // Linear cooling\n            T = T0 * (1.0 - (double)iter / iter_per_restart);\n        }\n        \n        // Update best solution if this restart improved\n        if (score > best_score) {\n            best_score = score;\n            best_ops = cur_ops;\n        }\n    }\n    \n    // Output best solution found\n    cout << best_ops.size() << '\\n';\n    for (int id : best_ops) {\n        cout << ops[id].stamp << ' ' << ops[id].p << ' ' << ops[id].q << '\\n';\n    }\n\n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <deque>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <climits>\n#include <cstdlib>\n#include <utility>\n\nusing namespace std;\n\nint main() {\n    const int N = 5;\n    int A[N][N];\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> A[i][j];\n\n    // queues of remaining containers for each receiving gate\n    deque<int> gate_rem[N];\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            gate_rem[i].push_back(A[i][j]);\n\n    int grid[N][N];\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            grid[i][j] = -1;          // -1 means empty\n\n    int hold = -1;                    // -1: not holding, otherwise container number\n    int posx = 0, posy = 0;           // position of the large crane\n\n    bool dispatched[25] = {false};\n    int next_exp[5];                  // next expected container for each row\n    for (int i = 0; i < N; ++i)\n        next_exp[i] = N * i;\n\n    pair<int, int> loc[25];           // location of container on the grid, (-1,-1) if not present\n    for (int i = 0; i < 25; ++i)\n        loc[i] = {-1, -1};\n\n    vector<string> ans(5);            // actions for the five cranes\n    int dispatched_cnt = 0;\n\n    const int INF = 1000000;\n\n    // helper lambdas\n    auto manhattan = [](int x1, int y1, int x2, int y2) {\n        return abs(x1 - x2) + abs(y1 - y2);\n    };\n\n    auto move_towards = [](int x, int y, int tx, int ty) -> char {\n        if (x < tx) return 'D';\n        if (x > tx) return 'U';\n        if (y < ty) return 'R';\n        if (y > ty) return 'L';\n        return '.';\n    };\n\n    auto find_buffer = [&](int x, int y, bool allow_active_gates) -> pair<int, int> {\n        int best_dist = INF;\n        pair<int, int> best = {-1, -1};\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N - 1; ++j) {   // columns 0..3 (col4 is dispatch)\n                if (grid[i][j] != -1) continue;\n                if (j == 0 && !allow_active_gates && !gate_rem[i].empty())\n                    continue;\n                int d = manhattan(x, y, i, j);\n                if (d < best_dist) {\n                    best_dist = d;\n                    best = {i, j};\n                }\n            }\n        }\n        return best;\n    };\n\n    auto estimated_store_distance = [&](int x, int y) -> int {\n        auto buf = find_buffer(x, y, false);\n        if (buf.first == -1) return INF;\n        return manhattan(x, y, buf.first, buf.second);\n    };\n\n    struct Candidate {\n        int cost;\n        int type;       // 0 = retrieve stored needed, 1 = pick up from gate\n        int b;          // container number\n        int px, py;     // pickup location\n        bool needed;    // for type 1: is it the next expected?\n    };\n\n    int turn = 0;\n    while (dispatched_cnt < N * N) {\n        ++turn;\n        if (turn > 10000) break;   // safety limit\n\n        // ---------- Step 1: place containers at receiving gates ----------\n        for (int i = 0; i < N; ++i) {\n            if (grid[i][0] == -1) {\n                // placement is blocked only if the large crane is at (i,0) and holding\n                if (!(posx == i && posy == 0 && hold != -1)) {\n                    if (!gate_rem[i].empty()) {\n                        int b = gate_rem[i].front();\n                        gate_rem[i].pop_front();\n                        grid[i][0] = b;\n                        loc[b] = {i, 0};\n                    }\n                }\n            }\n        }\n\n        // ---------- Step 2: decide action for the large crane ----------\n        char action;\n\n        if (hold != -1) {   // holding a container\n            int b = hold;\n            int r = b / N;\n            if (b == next_exp[r]) {   // should deliver\n                if (posx == r && posy == N - 1)\n                    action = 'Q';\n                else\n                    action = move_towards(posx, posy, r, N - 1);\n            } else {   // should store\n                // can we release here?\n                bool can_release_here = false;\n                if (posy != N - 1 && grid[posx][posy] == -1) {\n                    if (posy != 0 || gate_rem[posx].empty())\n                        can_release_here = true;\n                }\n                if (can_release_here) {\n                    action = 'Q';\n                } else {\n                    auto target = find_buffer(posx, posy, false);\n                    if (target.first == -1)   // no buffer -> fallback to deliver (causes inversion)\n                        target = {r, N - 1};\n                    action = move_towards(posx, posy, target.first, target.second);\n                }\n            }\n        } else {   // not holding\n            vector<Candidate> cand;\n\n            // retrieve stored needed containers\n            for (int r = 0; r < N; ++r) {\n                int b = next_exp[r];\n                if (b >= 0 && b < N * N && loc[b].first != -1) {\n                    int px = loc[b].first, py = loc[b].second;\n                    int d1 = manhattan(posx, posy, px, py);\n                    int d2 = manhattan(px, py, r, N - 1);\n                    int cost = d1 + d2 + 2;\n                    cand.push_back({cost, 0, b, px, py, true});\n                }\n            }\n\n            // pick up from gates\n            for (int i = 0; i < N; ++i) {\n                if (gate_rem[i].empty()) continue;\n                int head = gate_rem[i][0];\n                // only consider if the gate cell is empty or already contains the head\n                if (grid[i][0] != -1 && grid[i][0] != head) continue;\n                int px = i, py = 0;\n                int r = head / N;\n                bool needed = (head == next_exp[r]);\n                int d1 = manhattan(posx, posy, px, py);\n                int d2;\n                if (needed) {\n                    d2 = manhattan(px, py, r, N - 1);\n                } else {\n                    d2 = estimated_store_distance(px, py);\n                    if (d2 >= INF) d2 = 1000;   // large fallback\n                }\n                int cost = d1 + d2 + 2;\n                cand.push_back({cost, 1, head, px, py, needed});\n            }\n\n            if (cand.empty()) {\n                action = '.';\n            } else {\n                auto best = *min_element(cand.begin(), cand.end(),\n                    [](const Candidate& a, const Candidate& b) { return a.cost < b.cost; });\n                if (posx == best.px && posy == best.py)\n                    action = 'P';\n                else\n                    action = move_towards(posx, posy, best.px, best.py);\n            }\n        }\n\n        // execute the chosen action for crane 0\n        switch (action) {\n            case 'P':\n                hold = grid[posx][posy];\n                grid[posx][posy] = -1;\n                loc[hold] = {-1, -1};\n                break;\n            case 'Q':\n                grid[posx][posy] = hold;\n                loc[hold] = {posx, posy};\n                hold = -1;\n                break;\n            case 'U':\n                if (posx > 0) posx--;\n                break;\n            case 'D':\n                if (posx < N - 1) posx++;\n                break;\n            case 'L':\n                if (posy > 0) posy--;\n                break;\n            case 'R':\n                if (posy < N - 1) posy++;\n                break;\n            case '.':\n                break;\n            case 'B':\n                break;   // never used for crane 0\n        }\n\n        ans[0] += action;\n\n        // actions for the four small cranes (1..4)\n        for (int i = 1; i < N; ++i) {\n            if (turn == 1)\n                ans[i] += 'B';\n            else\n                ans[i] += '.';\n        }\n\n        // ---------- Step 3: dispatch containers at dispatch gates ----------\n        for (int i = 0; i < N; ++i) {\n            if (grid[i][N - 1] != -1) {\n                int b = grid[i][N - 1];\n                grid[i][N - 1] = -1;\n                dispatched[b] = true;\n                loc[b] = {-1, -1};\n                dispatched_cnt++;\n                // update next expected for this row\n                for (int c = N * i; c < N * (i + 1); ++c) {\n                    if (!dispatched[c]) {\n                        next_exp[i] = c;\n                        break;\n                    }\n                }\n            }\n        }\n\n        if (dispatched_cnt == N * N) break;\n    }\n\n    // output\n    for (int i = 0; i < N; ++i)\n        cout << ans[i] << endl;\n\n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <cassert>\n\nusing namespace std;\n\nstruct Square {\n    int x, y, h;\n};\n\ninline int manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\npair<long long, bool> evaluate(const vector<int>& perm, const vector<Square>& squares) {\n    long long total_steps = 0;\n    long long load_dist = 0;\n    int load = 0;\n    int cur_x = 0, cur_y = 0;\n    bool feasible = true;\n\n    for (int idx : perm) {\n        const Square& sq = squares[idx];\n        int d = manhattan(cur_x, cur_y, sq.x, sq.y);\n        total_steps += d;\n        load_dist += (long long)load * d;\n\n        load += sq.h;\n        if (load < 0) {\n            feasible = false;\n            break;\n        }\n\n        cur_x = sq.x;\n        cur_y = sq.y;\n    }\n\n    if (load != 0) feasible = false;\n\n    long long cost_without_base = 100 * total_steps + load_dist;\n    return {cost_without_base, feasible};\n}\n\nvector<int> greedy_permutation(const vector<Square>& squares, mt19937& rng) {\n    int M = squares.size();\n    vector<bool> used(M, false);\n    vector<int> perm;\n    int cur_x = 0, cur_y = 0;\n    int load = 0;\n    int remaining = M;\n\n    while (remaining > 0) {\n        vector<int> candidates;\n        int best_dist = 1e9;\n\n        for (int i = 0; i < M; ++i) {\n            if (used[i]) continue;\n            const Square& sq = squares[i];\n            bool feasible = false;\n            if (sq.h > 0) {\n                feasible = true;\n            } else {\n                if (load >= -sq.h) feasible = true;\n            }\n            if (!feasible) continue;\n            int d = manhattan(cur_x, cur_y, sq.x, sq.y);\n            if (d < best_dist) {\n                best_dist = d;\n                candidates.clear();\n                candidates.push_back(i);\n            } else if (d == best_dist) {\n                candidates.push_back(i);\n            }\n        }\n\n        assert(!candidates.empty());\n        uniform_int_distribution<int> dist(0, candidates.size()-1);\n        int best_idx = candidates[dist(rng)];\n\n        used[best_idx] = true;\n        perm.push_back(best_idx);\n        cur_x = squares[best_idx].x;\n        cur_y = squares[best_idx].y;\n        load += squares[best_idx].h;\n        --remaining;\n    }\n\n    return perm;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<vector<int>> h(N, vector<int>(N));\n    long long base = 0;\n    vector<Square> squares;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> h[i][j];\n            if (h[i][j] != 0) {\n                squares.push_back({i, j, h[i][j]});\n                base += abs(h[i][j]);\n            }\n        }\n    }\n\n    int M = squares.size();\n    if (M == 0) {\n        return 0;\n    }\n\n    random_device rd;\n    mt19937 rng(rd());\n    uniform_real_distribution<double> uni(0.0, 1.0);\n    uniform_int_distribution<int> rand_idx(0, M-1);\n\n    // SA parameters\n    const int MAX_ITER = 1000000;\n    const int RESTART_INTERVAL = 100000;\n    double start_temp = 10000.0;\n    double end_temp = 1e-5;\n    double cooling = exp(log(end_temp / start_temp) / MAX_ITER);\n\n    vector<int> best_perm;\n    long long best_cost = 1e18;\n\n    // initial solution\n    vector<int> cur_perm = greedy_permutation(squares, rng);\n    auto [init_cost, feasible_init] = evaluate(cur_perm, squares);\n    assert(feasible_init);\n    best_perm = cur_perm;\n    best_cost = init_cost;\n    long long cur_cost = init_cost;\n\n    for (int iter = 0; iter < MAX_ITER; ++iter) {\n        // periodic restart\n        if (iter % RESTART_INTERVAL == 0 && iter > 0) {\n            cur_perm = greedy_permutation(squares, rng);\n            auto [cost, feasible] = evaluate(cur_perm, squares);\n            if (feasible) {\n                cur_cost = cost;\n                if (cur_cost < best_cost) {\n                    best_perm = cur_perm;\n                    best_cost = cur_cost;\n                }\n            }\n        }\n\n        double T = start_temp * pow(cooling, iter);\n        vector<int> new_perm = cur_perm;\n        double move_type = uni(rng);\n\n        if (move_type < 0.33) {\n            // swap two random positions\n            int i = rand_idx(rng);\n            int j = rand_idx(rng);\n            if (i != j) swap(new_perm[i], new_perm[j]);\n        } else if (move_type < 0.66) {\n            // reverse a random segment\n            int i = rand_idx(rng);\n            int j = rand_idx(rng);\n            if (i > j) swap(i, j);\n            reverse(new_perm.begin() + i, new_perm.begin() + j + 1);\n        } else {\n            // move a random element to another random position\n            int i = rand_idx(rng);\n            int j = rand_idx(rng);\n            if (i != j) {\n                int val = new_perm[i];\n                new_perm.erase(new_perm.begin() + i);\n                if (j > i) --j;\n                new_perm.insert(new_perm.begin() + j, val);\n            }\n        }\n\n        auto [new_cost, feasible] = evaluate(new_perm, squares);\n        if (!feasible) continue;\n\n        if (new_cost < cur_cost || uni(rng) < exp((cur_cost - new_cost) / T)) {\n            cur_perm = new_perm;\n            cur_cost = new_cost;\n            if (cur_cost < best_cost) {\n                best_perm = cur_perm;\n                best_cost = cur_cost;\n            }\n        }\n    }\n\n    // 2-opt local search\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int i = 0; i < M; ++i) {\n            for (int j = i+1; j < M; ++j) {\n                vector<int> new_perm = best_perm;\n                reverse(new_perm.begin() + i, new_perm.begin() + j + 1);\n                auto [new_cost, feasible] = evaluate(new_perm, squares);\n                if (feasible && new_cost < best_cost) {\n                    best_perm = new_perm;\n                    best_cost = new_cost;\n                    improved = true;\n                }\n            }\n        }\n    }\n\n    // Output operations\n    int cur_x = 0, cur_y = 0, load = 0;\n    for (int idx : best_perm) {\n        const Square& sq = squares[idx];\n        while (cur_y < sq.y) { cout << \"R\\n\"; ++cur_y; }\n        while (cur_y > sq.y) { cout << \"L\\n\"; --cur_y; }\n        while (cur_x < sq.x) { cout << \"D\\n\"; ++cur_x; }\n        while (cur_x > sq.x) { cout << \"U\\n\"; --cur_x; }\n\n        if (sq.h > 0) {\n            cout << \"+\" << sq.h << \"\\n\";\n            load += sq.h;\n        } else {\n            cout << \"-\" << -sq.h << \"\\n\";\n            load += sq.h;\n        }\n    }\n\n    return 0;\n}","ahc035":"#include <cstdio>\n#include <vector>\n#include <array>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n#include <set>\n\nusing namespace std;\n\nconst int N = 6;\nconst int M = 15;\nconst int T = 10;\nconst int SEED_COUNT = 2 * N * (N - 1); // 60\n\nusing Seed = array<int, M>;\n\n// Complementarity score: sum of max values per attribute\nint complementarity(const Seed& a, const Seed& b) {\n    int res = 0;\n    for (int l = 0; l < M; ++l) {\n        res += max(a[l], b[l]);\n    }\n    return res;\n}\n\n// Select seeds with diversity and high potential\nvector<int> select_seeds(const vector<Seed>& seeds, const vector<int>& sums) {\n    vector<int> selected;\n    vector<bool> used(SEED_COUNT, false);\n    \n    // First, take top 10 by sum (high value seeds)\n    vector<int> by_sum(SEED_COUNT);\n    iota(by_sum.begin(), by_sum.end(), 0);\n    sort(by_sum.begin(), by_sum.end(), [&](int a, int b) { return sums[a] > sums[b]; });\n    \n    for (int i = 0; i < 10 && i < SEED_COUNT; ++i) {\n        selected.push_back(by_sum[i]);\n        used[by_sum[i]] = true;\n    }\n    \n    // Then add seeds that are complementary to existing ones\n    while (selected.size() < 36) {\n        int best_seed = -1;\n        int best_score = -1;\n        \n        for (int i = 0; i < SEED_COUNT; ++i) {\n            if (used[i]) continue;\n            \n            // Score: sum of complementarity with all selected seeds\n            int score = 0;\n            for (int s : selected) {\n                score += complementarity(seeds[i], seeds[s]);\n            }\n            score /= selected.size(); // Normalize by number of selected\n            \n            // Add a bonus for high individual sum\n            score += sums[i] / 10;\n            \n            if (score > best_score) {\n                best_score = score;\n                best_seed = i;\n            }\n        }\n        \n        if (best_seed != -1) {\n            selected.push_back(best_seed);\n            used[best_seed] = true;\n        } else {\n            break;\n        }\n    }\n    \n    // If we still need more, add by highest sum\n    if (selected.size() < 36) {\n        for (int i = 0; i < SEED_COUNT && selected.size() < 36; ++i) {\n            if (!used[i]) {\n                selected.push_back(i);\n                used[i] = true;\n            }\n        }\n    }\n    \n    return selected;\n}\n\n// Place seeds to maximize good pairings\nvoid place_seeds(const vector<Seed>& seeds, const vector<int>& sums, \n                 const vector<int>& selected, vector<vector<int>>& grid) {\n    // We'll use a greedy approach considering complementarity\n    vector<bool> used(SEED_COUNT, false);\n    for (int s : selected) used[s] = true;\n    \n    // Start with the highest sum seed in the center\n    vector<int> selected_copy = selected;\n    sort(selected_copy.begin(), selected_copy.end(), [&](int a, int b) { \n        return sums[a] > sums[b]; \n    });\n    \n    // Place highest sum seeds in interior cells first\n    vector<pair<int, int>> interior_cells;\n    vector<pair<int, int>> border_cells;\n    \n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            bool is_interior = (i > 0 && i < N-1 && j > 0 && j < N-1);\n            if (is_interior) {\n                interior_cells.push_back({i, j});\n            } else {\n                border_cells.push_back({i, j});\n            }\n        }\n    }\n    \n    // Place top seeds in interior\n    for (int i = 0; i < interior_cells.size() && i < selected_copy.size(); ++i) {\n        auto [r, c] = interior_cells[i];\n        grid[r][c] = selected_copy[i];\n    }\n    \n    // Fill remaining cells with remaining seeds\n    vector<int> remaining_seeds;\n    for (int s : selected_copy) {\n        bool placed = false;\n        for (int i = 0; i < N && !placed; ++i) {\n            for (int j = 0; j < N && !placed; ++j) {\n                if (grid[i][j] == s) {\n                    placed = true;\n                }\n            }\n        }\n        if (!placed) {\n            remaining_seeds.push_back(s);\n        }\n    }\n    \n    // Place border seeds\n    for (int i = 0; i < border_cells.size() && !remaining_seeds.empty(); ++i) {\n        auto [r, c] = border_cells[i];\n        grid[r][c] = remaining_seeds.back();\n        remaining_seeds.pop_back();\n    }\n    \n    // Fill any remaining empty cells\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] == -1 && !remaining_seeds.empty()) {\n                grid[i][j] = remaining_seeds.back();\n                remaining_seeds.pop_back();\n            }\n        }\n    }\n    \n    // Now optimize placement by swapping to increase complementarity\n    for (int iter = 0; iter < 100; ++iter) {\n        bool improved = false;\n        \n        for (int i1 = 0; i1 < N; ++i1) {\n            for (int j1 = 0; j1 < N; ++j1) {\n                for (int i2 = 0; i2 < N; ++i2) {\n                    for (int j2 = 0; j2 < N; ++j2) {\n                        if (i1 == i2 && j1 == j2) continue;\n                        \n                        // Calculate current complementarity for neighbors of both cells\n                        auto get_neighbors = [&](int i, int j) {\n                            vector<pair<int, int>> neighbors;\n                            if (i > 0) neighbors.push_back({i-1, j});\n                            if (i < N-1) neighbors.push_back({i+1, j});\n                            if (j > 0) neighbors.push_back({i, j-1});\n                            if (j < N-1) neighbors.push_back({i, j+1});\n                            return neighbors;\n                        };\n                        \n                        auto neighbors1 = get_neighbors(i1, j1);\n                        auto neighbors2 = get_neighbors(i2, j2);\n                        \n                        int current_score = 0;\n                        for (auto [ni, nj] : neighbors1) {\n                            current_score += complementarity(seeds[grid[i1][j1]], seeds[grid[ni][nj]]);\n                        }\n                        for (auto [ni, nj] : neighbors2) {\n                            current_score += complementarity(seeds[grid[i2][j2]], seeds[grid[ni][nj]]);\n                        }\n                        \n                        // Try swapping\n                        swap(grid[i1][j1], grid[i2][j2]);\n                        \n                        int new_score = 0;\n                        for (auto [ni, nj] : neighbors1) {\n                            new_score += complementarity(seeds[grid[i1][j1]], seeds[grid[ni][nj]]);\n                        }\n                        for (auto [ni, nj] : neighbors2) {\n                            new_score += complementarity(seeds[grid[i2][j2]], seeds[grid[ni][nj]]);\n                        }\n                        \n                        if (new_score > current_score) {\n                            improved = true;\n                        } else {\n                            swap(grid[i1][j1], grid[i2][j2]);\n                        }\n                    }\n                }\n            }\n        }\n        \n        if (!improved) break;\n    }\n}\n\nint main() {\n    vector<Seed> seeds(SEED_COUNT);\n    vector<int> sums(SEED_COUNT);\n    \n    // Read initial seeds\n    for (int i = 0; i < SEED_COUNT; ++i) {\n        for (int j = 0; j < M; ++j) {\n            scanf(\"%d\", &seeds[i][j]);\n        }\n        sums[i] = accumulate(seeds[i].begin(), seeds[i].end(), 0);\n    }\n    \n    for (int t = 0; t < T; ++t) {\n        // Select seeds\n        vector<int> selected = select_seeds(seeds, sums);\n        \n        // Place seeds\n        vector<vector<int>> grid(N, vector<int>(N, -1));\n        place_seeds(seeds, sums, selected, grid);\n        \n        // Output the grid\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                printf(\"%d\", grid[i][j]);\n                if (j < N - 1) printf(\" \");\n                else printf(\"\\n\");\n            }\n        }\n        fflush(stdout);\n        \n        // Read new seeds\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            for (int j = 0; j < M; ++j) {\n                scanf(\"%d\", &seeds[i][j]);\n            }\n            sums[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\nusing namespace std;\n\nstruct Point {\n    int x, y;\n    Point(int x = 0, int y = 0) : x(x), y(y) {}\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, V;\n    cin >> N >> M >> V;\n    \n    vector<string> s_grid(N), t_grid(N);\n    for (int i = 0; i < N; ++i) cin >> s_grid[i];\n    for (int i = 0; i < N; ++i) cin >> t_grid[i];\n    \n    // Find pickups and dropoffs\n    vector<Point> pickups, dropoffs;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (s_grid[i][j] == '1' && t_grid[i][j] == '0') {\n                pickups.push_back(Point(i, j));\n            }\n            if (s_grid[i][j] == '0' && t_grid[i][j] == '1') {\n                dropoffs.push_back(Point(i, j));\n            }\n        }\n    }\n    \n    // Design arm: single vertex (root = fingertip)\n    cout << \"1\\n\";\n    cout << \"0 0\\n\";\n    \n    // Current root position\n    int rx = 0, ry = 0;\n    \n    // Generate operations\n    vector<string> turns;\n    \n    for (size_t i = 0; i < pickups.size(); ++i) {\n        // Move to pickup\n        while (rx != pickups[i].x) {\n            if (rx < pickups[i].x) {\n                turns.push_back(\"D.\");\n                rx++;\n            } else {\n                turns.push_back(\"U.\");\n                rx--;\n            }\n        }\n        while (ry != pickups[i].y) {\n            if (ry < pickups[i].y) {\n                turns.push_back(\"R.\");\n                ry++;\n            } else {\n                turns.push_back(\"L.\");\n                ry--;\n            }\n        }\n        \n        // Grab\n        turns.push_back(\".P\");\n        \n        // Move to dropoff\n        while (rx != dropoffs[i].x) {\n            if (rx < dropoffs[i].x) {\n                turns.push_back(\"D.\");\n                rx++;\n            } else {\n                turns.push_back(\"U.\");\n                rx--;\n            }\n        }\n        while (ry != dropoffs[i].y) {\n            if (ry < dropoffs[i].y) {\n                turns.push_back(\"R.\");\n                ry++;\n            } else {\n                turns.push_back(\"L.\");\n                ry--;\n            }\n        }\n        \n        // Release\n        turns.push_back(\".P\");\n    }\n    \n    // Output turns\n    for (const string& turn : turns) {\n        cout << turn << \"\\n\";\n    }\n    \n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <cmath>\n#include <unordered_map>\n#include <climits>\n\nusing namespace std;\n\nstruct Point {\n    int x, y, w;\n};\n\n// 2D Fenwick Tree for point counting\nclass Fenwick2D {\n    int n, m;\n    vector<vector<int>> tree;\n    \npublic:\n    Fenwick2D(int n, int m) : n(n), m(m), tree(n + 1, vector<int>(m + 1, 0)) {}\n    \n    void update(int x, int y, int delta) {\n        for (int i = x + 1; i <= n; i += i & -i)\n            for (int j = y + 1; j <= m; j += j & -j)\n                tree[i][j] += delta;\n    }\n    \n    int query(int x, int y) const {\n        int sum = 0;\n        for (int i = x + 1; i > 0; i -= i & -i)\n            for (int j = y + 1; j > 0; j -= j & -j)\n                sum += tree[i][j];\n        return sum;\n    }\n    \n    int query(int x1, int y1, int x2, int y2) const {\n        if (x1 > x2 || y1 > y2) return 0;\n        return query(x2, y2) - query(x1-1, y2) - query(x2, y1-1) + query(x1-1, y1-1);\n    }\n};\n\n// Improved K-means clustering with multiple initializations\nvector<pair<int, int>> cluster_points(const vector<Point>& points, int k, mt19937& rng) {\n    int n = points.size();\n    if (n == 0) return {};\n    \n    // Try multiple initializations and keep the best\n    vector<pair<int, int>> best_centroids;\n    int best_inertia = INT_MAX;\n    \n    for (int init = 0; init < 5; ++init) {\n        vector<pair<int, int>> centroids(k);\n        \n        // K-means++ initialization\n        uniform_int_distribution<int> dist(0, n-1);\n        centroids[0] = {points[dist(rng)].x, points[dist(rng)].y};\n        \n        for (int i = 1; i < k; ++i) {\n            // Calculate distances to nearest centroid\n            vector<double> distances(n);\n            double total = 0;\n            for (int j = 0; j < n; ++j) {\n                double min_dist = 1e9;\n                for (int c = 0; c < i; ++c) {\n                    double dx = points[j].x - centroids[c].first;\n                    double dy = points[j].y - centroids[c].second;\n                    double d = dx*dx + dy*dy;\n                    min_dist = min(min_dist, d);\n                }\n                distances[j] = min_dist;\n                total += min_dist;\n            }\n            \n            // Choose next centroid with probability proportional to distance\n            uniform_real_distribution<double> real_dist(0, total);\n            double r = real_dist(rng);\n            double sum = 0;\n            for (int j = 0; j < n; ++j) {\n                sum += distances[j];\n                if (sum >= r) {\n                    centroids[i] = {points[j].x, points[j].y};\n                    break;\n                }\n            }\n        }\n        \n        // Run K-means\n        for (int iter = 0; iter < 10; ++iter) {\n            vector<int> counts(k, 0);\n            vector<long long> sum_x(k, 0), sum_y(k, 0);\n            \n            for (const auto& p : points) {\n                int best = 0;\n                long long best_dist = LLONG_MAX;\n                for (int i = 0; i < k; ++i) {\n                    long long dx = p.x - centroids[i].first;\n                    long long dy = p.y - centroids[i].second;\n                    long long d = dx*dx + dy*dy;\n                    if (d < best_dist) {\n                        best_dist = d;\n                        best = i;\n                    }\n                }\n                counts[best]++;\n                sum_x[best] += p.x;\n                sum_y[best] += p.y;\n            }\n            \n            for (int i = 0; i < k; ++i) {\n                if (counts[i] > 0) {\n                    centroids[i].first = sum_x[i] / counts[i];\n                    centroids[i].second = sum_y[i] / counts[i];\n                }\n            }\n        }\n        \n        // Calculate inertia\n        int inertia = 0;\n        for (const auto& p : points) {\n            int min_dist = INT_MAX;\n            for (const auto& c : centroids) {\n                int d = abs(p.x - c.first) + abs(p.y - c.second);\n                min_dist = min(min_dist, d);\n            }\n            inertia += min_dist;\n        }\n        \n        if (inertia < best_inertia) {\n            best_inertia = inertia;\n            best_centroids = centroids;\n        }\n    }\n    \n    return best_centroids;\n}\n\n// Function to evaluate a rectangle\nint evaluate_rect(const Fenwick2D& fenw, const vector<int>& xs, const vector<int>& ys, \n                  int l, int r, int b, int t) {\n    int l_idx = lower_bound(xs.begin(), xs.end(), l) - xs.begin();\n    int r_idx = upper_bound(xs.begin(), xs.end(), r) - xs.begin() - 1;\n    int b_idx = lower_bound(ys.begin(), ys.end(), b) - ys.begin();\n    int t_idx = upper_bound(ys.begin(), ys.end(), t) - ys.begin() - 1;\n    \n    if (l_idx > r_idx || b_idx > t_idx) return -1000000;\n    return fenw.query(l_idx, b_idx, r_idx, t_idx);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    cin >> N;\n    \n    vector<Point> mackerels(N), sardines(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> mackerels[i].x >> mackerels[i].y;\n        mackerels[i].w = 1;\n    }\n    for (int i = 0; i < N; ++i) {\n        cin >> sardines[i].x >> sardines[i].y;\n        sardines[i].w = -1;\n    }\n    \n    // Combine all points\n    vector<Point> all_points;\n    all_points.reserve(2 * N);\n    all_points.insert(all_points.end(), mackerels.begin(), mackerels.end());\n    all_points.insert(all_points.end(), sardines.begin(), sardines.end());\n    \n    // Compress coordinates\n    vector<int> xs, ys;\n    for (const auto& p : all_points) {\n        xs.push_back(p.x);\n        ys.push_back(p.y);\n    }\n    sort(xs.begin(), xs.end());\n    xs.erase(unique(xs.begin(), xs.end()), xs.end());\n    sort(ys.begin(), ys.end());\n    ys.erase(unique(ys.begin(), ys.end()), ys.end());\n    \n    int X = xs.size(), Y = ys.size();\n    \n    // Build Fenwick tree\n    Fenwick2D fenw(X, Y);\n    for (const auto& p : all_points) {\n        int xi = lower_bound(xs.begin(), xs.end(), p.x) - xs.begin();\n        int yi = lower_bound(ys.begin(), ys.end(), p.y) - ys.begin();\n        fenw.update(xi, yi, p.w);\n    }\n    \n    // Cluster mackerels to find promising regions\n    random_device rd;\n    mt19937 rng(rd());\n    \n    // Try different numbers of clusters\n    vector<pair<int, int>> all_centroids;\n    for (int k : {10, 15, 20}) {\n        auto centroids = cluster_points(mackerels, k, rng);\n        all_centroids.insert(all_centroids.end(), centroids.begin(), centroids.end());\n    }\n    \n    // Candidate rectangles\n    vector<tuple<int, int, int, int>> candidates;\n    \n    // Add bounding box of all mackerels\n    int min_x = 100000, max_x = 0, min_y = 100000, max_y = 0;\n    for (const auto& p : mackerels) {\n        min_x = min(min_x, p.x);\n        max_x = max(max_x, p.x);\n        min_y = min(min_y, p.y);\n        max_y = max(max_y, p.y);\n    }\n    candidates.emplace_back(min_x, max_x, min_y, max_y);\n    \n    // Add rectangles around cluster centers\n    uniform_int_distribution<int> size_dist(1000, 20000);\n    for (const auto& center : all_centroids) {\n        int cx = center.first, cy = center.second;\n        for (int size : {3000, 6000, 10000, 15000}) {\n            int left = max(0, cx - size);\n            int right = min(100000, cx + size);\n            int bottom = max(0, cy - size);\n            int top = min(100000, cy + size);\n            candidates.emplace_back(left, right, bottom, top);\n        }\n    }\n    \n    // Add rectangles based on point pairs (sampling)\n    uniform_int_distribution<int> point_dist(0, N-1);\n    for (int i = 0; i < 300; ++i) {\n        int idx1 = point_dist(rng);\n        int idx2 = point_dist(rng);\n        int left = min(mackerels[idx1].x, mackerels[idx2].x);\n        int right = max(mackerels[idx1].x, mackerels[idx2].x);\n        int bottom = min(mackerels[idx1].y, mackerels[idx2].y);\n        int top = max(mackerels[idx1].y, mackerels[idx2].y);\n        \n        // Expand a bit\n        int expand = size_dist(rng) / 2;\n        left = max(0, left - expand);\n        right = min(100000, right + expand);\n        bottom = max(0, bottom - expand);\n        top = min(100000, top + expand);\n        \n        candidates.emplace_back(left, right, bottom, top);\n    }\n    \n    // Add rectangles that avoid sardine-dense areas\n    // Find sardine-dense regions by clustering sardines\n    auto sardine_centroids = cluster_points(sardines, 5, rng);\n    for (const auto& sc : sardine_centroids) {\n        // Create rectangle that excludes this sardine cluster\n        int sx = sc.first, sy = sc.second;\n        int avoid_size = 5000;\n        \n        // Try rectangles that avoid this area\n        for (int dx : {-1, 1}) {\n            for (int dy : {-1, 1}) {\n                int left = (dx == -1) ? 0 : min(100000, sx + avoid_size);\n                int right = (dx == -1) ? max(0, sx - avoid_size) : 100000;\n                int bottom = (dy == -1) ? 0 : min(100000, sy + avoid_size);\n                int top = (dy == -1) ? max(0, sy - avoid_size) : 100000;\n                \n                if (left < right && bottom < top) {\n                    candidates.emplace_back(left, right, bottom, top);\n                }\n            }\n        }\n    }\n    \n    // Evaluate candidates and keep top 20 for local optimization\n    vector<pair<int, tuple<int, int, int, int>>> scored_candidates;\n    for (const auto& rect : candidates) {\n        auto [l, r, b, t] = rect;\n        if (l >= r || b >= t) continue;\n        \n        int score = evaluate_rect(fenw, xs, ys, l, r, b, t);\n        scored_candidates.emplace_back(score, rect);\n    }\n    \n    // Sort by score descending\n    sort(scored_candidates.begin(), scored_candidates.end(), \n         [](const auto& a, const auto& b) { return a.first > b.first; });\n    \n    // Keep top 20 for local optimization\n    vector<tuple<int, int, int, int>> top_candidates;\n    for (int i = 0; i < min(20, (int)scored_candidates.size()); ++i) {\n        top_candidates.push_back(scored_candidates[i].second);\n    }\n    \n    // Local optimization on top candidates\n    int best_score = -1000000;\n    tuple<int, int, int, int> best_rect;\n    \n    for (auto rect : top_candidates) {\n        auto [L, R, B, T] = rect;\n        int current_score = evaluate_rect(fenw, xs, ys, L, R, B, T);\n        \n        // Local optimization: try to adjust boundaries to point coordinates\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            \n            // Try moving left boundary\n            for (int newL : {L - 1000, L - 500, L - 200, L + 200, L + 500}) {\n                if (newL >= 0 && newL < R) {\n                    int score = evaluate_rect(fenw, xs, ys, newL, R, B, T);\n                    if (score > current_score) {\n                        current_score = score;\n                        L = newL;\n                        improved = true;\n                    }\n                }\n            }\n            \n            // Try moving right boundary\n            for (int newR : {R - 1000, R - 500, R - 200, R + 200, R + 500}) {\n                if (newR > L && newR <= 100000) {\n                    int score = evaluate_rect(fenw, xs, ys, L, newR, B, T);\n                    if (score > current_score) {\n                        current_score = score;\n                        R = newR;\n                        improved = true;\n                    }\n                }\n            }\n            \n            // Try moving bottom boundary\n            for (int newB : {B - 1000, B - 500, B - 200, B + 200, B + 500}) {\n                if (newB >= 0 && newB < T) {\n                    int score = evaluate_rect(fenw, xs, ys, L, R, newB, T);\n                    if (score > current_score) {\n                        current_score = score;\n                        B = newB;\n                        improved = true;\n                    }\n                }\n            }\n            \n            // Try moving top boundary\n            for (int newT : {T - 1000, T - 500, T - 200, T + 200, T + 500}) {\n                if (newT > B && newT <= 100000) {\n                    int score = evaluate_rect(fenw, xs, ys, L, R, B, newT);\n                    if (score > current_score) {\n                        current_score = score;\n                        T = newT;\n                        improved = true;\n                    }\n                }\n            }\n        }\n        \n        if (current_score > best_score) {\n            best_score = current_score;\n            best_rect = {L, R, B, T};\n        }\n    }\n    \n    // Output the best rectangle\n    auto [outL, outR, outB, outT] = best_rect;\n    cout << \"4\\n\";\n    cout << outL << \" \" << outB << \"\\n\";\n    cout << outR << \" \" << outB << \"\\n\";\n    cout << outR << \" \" << outT << \"\\n\";\n    cout << outL << \" \" << outT << \"\\n\";\n    \n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <tuple>\n#include <cmath>\n\nusing namespace std;\n\nstruct Rectangle {\n    int x, y, w, h;\n    int right() const { return x + w; }\n    int bottom() const { return y + h; }\n};\n\nint compute_y0(int x0, int width, const vector<int>& placed_indices, const Rectangle rect_of_index[]) {\n    int y0 = 0;\n    for (int idx : placed_indices) {\n        const Rectangle& R = rect_of_index[idx];\n        if (x0 < R.right() && x0 + width > R.x) {\n            y0 = max(y0, R.bottom());\n        }\n    }\n    return y0;\n}\n\nint compute_x0(int y0, int height, const vector<int>& placed_indices, const Rectangle rect_of_index[]) {\n    int x0 = 0;\n    for (int idx : placed_indices) {\n        const Rectangle& R = rect_of_index[idx];\n        if (y0 < R.bottom() && y0 + height > R.y) {\n            x0 = max(x0, R.right());\n        }\n    }\n    return x0;\n}\n\nstruct Candidate {\n    int r;\n    char d;\n    int b;\n    int newW, newH;\n    double score;\n};\n\nvoid solve_turn(int turn, const vector<int>& w, const vector<int>& h, int N, mt19937& rng) {\n    // Strategy: Use different approaches for different turns\n    int strategy = turn % 4;\n    \n    vector<int> placed_indices;\n    Rectangle rect_of_index[N];\n    bool is_placed[N] = {false};\n    int W = 0, H = 0;\n    \n    vector<tuple<int, int, char, int>> ops;\n    \n    uniform_real_distribution<double> dist_real(0.0, 1.0);\n    uniform_int_distribution<int> dist_binary(0, 1);\n    \n    for (int i = 0; i < N; ++i) {\n        // Different strategies for different turns\n        double p_skip;\n        int attempts;\n        double threshold_factor;\n        \n        switch (strategy) {\n            case 0: // Aggressive placement\n                p_skip = 0.1;\n                attempts = 15;\n                threshold_factor = 1.2;\n                break;\n            case 1: // Conservative placement\n                p_skip = 0.3;\n                attempts = 10;\n                threshold_factor = 0.8;\n                break;\n            case 2: // Balanced placement\n                p_skip = 0.2;\n                attempts = 20;\n                threshold_factor = 1.0;\n                break;\n            case 3: // Exploration focus\n                p_skip = 0.15;\n                attempts = 25;\n                threshold_factor = 1.1;\n                break;\n        }\n        \n        if (dist_real(rng) < p_skip) continue;\n        \n        // Try multiple placements and keep the best\n        vector<Candidate> candidates;\n        \n        for (int attempt = 0; attempt < attempts; ++attempt) {\n            // Choose rotation and direction\n            int r = dist_binary(rng);\n            char d = (dist_binary(rng) == 0) ? 'U' : 'L';\n            int width = (r == 0) ? w[i] : h[i];\n            int height = (r == 0) ? h[i] : w[i];\n            \n            // Choose reference\n            vector<int> b_candidates = {-1};\n            for (int idx : placed_indices) b_candidates.push_back(idx);\n            uniform_int_distribution<int> dist_b(0, b_candidates.size() - 1);\n            int b = b_candidates[dist_b(rng)];\n            \n            int x0, y0;\n            if (d == 'U') {\n                x0 = (b == -1) ? 0 : rect_of_index[b].right();\n                y0 = compute_y0(x0, width, placed_indices, rect_of_index);\n            } else {\n                y0 = (b == -1) ? 0 : rect_of_index[b].bottom();\n                x0 = compute_x0(y0, height, placed_indices, rect_of_index);\n            }\n            \n            int newW = max(W, x0 + width);\n            int newH = max(H, y0 + height);\n            \n            // Score considers W+H and aspect ratio balance\n            double aspect_penalty = abs(newW - newH) * 0.1;\n            double score = newW + newH + aspect_penalty;\n            \n            candidates.push_back({r, d, b, newW, newH, score});\n        }\n        \n        // Sort candidates by score\n        sort(candidates.begin(), candidates.end(), \n             [](const Candidate& a, const Candidate& b) { return a.score < b.score; });\n        \n        // Choose the best candidate that satisfies placement condition\n        bool placed = false;\n        for (const auto& cand : candidates) {\n            if (cand.newW + cand.newH <= W + H + threshold_factor * (w[i] + h[i])) {\n                // Place this rectangle\n                int width = (cand.r == 0) ? w[i] : h[i];\n                int height = (cand.r == 0) ? h[i] : w[i];\n                int x0, y0;\n                \n                if (cand.d == 'U') {\n                    x0 = (cand.b == -1) ? 0 : rect_of_index[cand.b].right();\n                    y0 = compute_y0(x0, width, placed_indices, rect_of_index);\n                } else {\n                    y0 = (cand.b == -1) ? 0 : rect_of_index[cand.b].bottom();\n                    x0 = compute_x0(y0, height, placed_indices, rect_of_index);\n                }\n                \n                rect_of_index[i] = {x0, y0, width, height};\n                is_placed[i] = true;\n                placed_indices.push_back(i);\n                W = cand.newW;\n                H = cand.newH;\n                ops.emplace_back(i, cand.r, cand.d, cand.b);\n                placed = true;\n                break;\n            }\n        }\n        \n        // If no candidate satisfies condition, skip this rectangle\n    }\n    \n    // Output operations\n    cout << ops.size() << '\\n';\n    for (auto [p, r, d, b] : ops) {\n        cout << p << ' ' << r << ' ' << d << ' ' << b << '\\n';\n    }\n    cout.flush();\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, T, sigma;\n    cin >> N >> T >> sigma;\n    vector<int> w(N), h(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> w[i] >> h[i];\n    }\n    \n    random_device rd;\n    mt19937 rng(rd());\n    \n    for (int t = 0; t < T; ++t) {\n        solve_turn(t, w, h, N, rng);\n        int Wp, Hp;\n        cin >> Wp >> Hp;\n    }\n    \n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <random>\n#include <cmath>\n#include <numeric>\n#include <chrono>\nusing namespace std;\n\nint N, H;\nvector<vector<int>> adj;\nvector<int> A;\n\n// Check if changing vertex v to newd is feasible (without modifying state)\nbool can_change(int v, int newd, const vector<int>& depth) {\n    // check v itself if newd > 0\n    if (newd > 0) {\n        bool has = false;\n        for (int u : adj[v]) {\n            if (depth[u] == newd - 1) {\n                has = true;\n                break;\n            }\n        }\n        if (!has) return false;\n    }\n    // check all neighbours\n    for (int u : adj[v]) {\n        if (depth[u] == 0) continue; // root has no constraint\n        bool has = false;\n        for (int w : adj[u]) {\n            int d_w = (w == v) ? newd : depth[w];\n            if (d_w == depth[u] - 1) {\n                has = true;\n                break;\n            }\n        }\n        if (!has) return false;\n    }\n    return true;\n}\n\n// Try to raise vertex v to target depth, recursively raising neighbors if needed\n// Returns true if successful\nbool raise_to(vector<int>& depth, int v, int target, vector<bool>& visited) {\n    if (depth[v] >= target) return true;\n    if (target > H) return false;\n    \n    // If we can directly raise to target, do it\n    if (can_change(v, target, depth)) {\n        depth[v] = target;\n        return true;\n    }\n    \n    // Otherwise, we need to raise neighbors to target-1 first\n    visited[v] = true;\n    for (int u : adj[v]) {\n        if (visited[u]) continue;\n        if (depth[u] < target - 1) { // neighbor needs to be raised\n            if (raise_to(depth, u, target - 1, visited)) {\n                // After raising u, check if v can now be raised to target\n                if (can_change(v, target, depth)) {\n                    depth[v] = target;\n                    visited[v] = false;\n                    return true;\n                }\n            }\n        }\n    }\n    visited[v] = false;\n    return false;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    cin >> N >> M >> H;\n    A.resize(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n    adj.resize(N);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n    // read coordinates (unused)\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // ---------- 1. Compute H-neighborhoods ----------\n    vector<vector<int>> cover(N);\n    for (int v = 0; v < N; ++v) {\n        vector<int> dist(N, -1);\n        queue<int> q;\n        dist[v] = 0;\n        q.push(v);\n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            if (dist[u] > H) continue;\n            cover[v].push_back(u);\n            if (dist[u] == H) continue;\n            for (int w : adj[u]) {\n                if (dist[w] == -1) {\n                    dist[w] = dist[u] + 1;\n                    q.push(w);\n                }\n            }\n        }\n    }\n\n    // ---------- 2. Greedy set cover to choose roots ----------\n    vector<bool> covered(N, false);\n    vector<int> roots;\n    int remaining = N;\n    while (remaining > 0) {\n        int best_v = -1, best_cnt = -1;\n        for (int v = 0; v < N; ++v) {\n            int cnt = 0;\n            for (int u : cover[v]) if (!covered[u]) cnt++;\n            if (cnt > best_cnt || (cnt == best_cnt && (best_v == -1 || A[v] < A[best_v]))) {\n                best_cnt = cnt;\n                best_v = v;\n            }\n        }\n        roots.push_back(best_v);\n        for (int u : cover[best_v]) if (!covered[u]) {\n            covered[u] = true;\n            --remaining;\n        }\n    }\n\n    // ---------- 3. Multi-source BFS to get initial depths ----------\n    vector<int> depth(N, -1);\n    queue<int> q;\n    for (int r : roots) {\n        depth[r] = 0;\n        q.push(r);\n    }\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (int v : adj[u]) {\n            if (depth[v] == -1) {\n                depth[v] = depth[u] + 1;\n                q.push(v);\n            }\n        }\n    }\n    long long cur_obj = 0;\n    for (int v = 0; v < N; ++v) cur_obj += depth[v] * A[v];\n\n    // ---------- 4. Simulated Annealing ----------\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> rand_v(0, N-1);\n    uniform_int_distribution<int> rand_d(0, H);\n    uniform_real_distribution<double> rand_float(0.0, 1.0);\n\n    const int ITER = 2000000; // good balance\n    double temp = 1000.0;\n    const double cooling = 0.999995; // proven effective\n\n    for (int iter = 0; iter < ITER; ++iter) {\n        int v = rand_v(rng);\n        int oldd = depth[v];\n        int newd = rand_d(rng);\n        if (newd == oldd) continue;\n        int delta = (newd - oldd) * A[v];\n\n        // feasibility check\n        if (!can_change(v, newd, depth)) continue;\n\n        // SA acceptance\n        if (delta >= 0 || rand_float(rng) < exp(delta / temp)) {\n            depth[v] = newd;\n            cur_obj += delta;\n        }\n        temp *= cooling;\n    }\n\n    // ---------- 5. Greedy improvement with recursive raising ----------\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    vector<bool> visited(N, false);\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int v : order) {\n            if (depth[v] == H) continue;\n            int target = H; // try to raise to maximum\n            if (raise_to(depth, v, target, visited)) {\n                // Compute new objective\n                long long new_obj = 0;\n                for (int i = 0; i < N; ++i) new_obj += depth[i] * A[i];\n                if (new_obj > cur_obj) {\n                    cur_obj = new_obj;\n                    improved = true;\n                }\n            }\n        }\n    }\n\n    // ---------- 6. Multiple random sweeps ----------\n    for (int sweep = 0; sweep < 3; ++sweep) {\n        vector<int> rand_order(N);\n        iota(rand_order.begin(), rand_order.end(), 0);\n        shuffle(rand_order.begin(), rand_order.end(), rng);\n        for (int v : rand_order) {\n            while (depth[v] < H) {\n                int newd = depth[v] + 1;\n                if (can_change(v, newd, depth)) {\n                    depth[v] = newd;\n                    cur_obj += A[v];\n                } else {\n                    break;\n                }\n            }\n        }\n    }\n\n    // ---------- 7. Build parent pointers ----------\n    vector<int> parent(N, -1);\n    for (int v = 0; v < N; ++v) {\n        if (depth[v] == 0) continue;\n        for (int u : adj[v]) {\n            if (depth[u] == depth[v] - 1) {\n                parent[v] = u;\n                break;\n            }\n        }\n    }\n\n    // ---------- 8. Output ----------\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << parent[i];\n    }\n    cout << endl;\n\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 20;\nconst int TOP_K = 10;\nconst int TOP_L = 5;\n\nstruct Op {\n    int type; // 0:U,1:D,2:L,3:R\n    int idx;  // column for U/D, row for L/R\n    int k;    // number of shifts\n};\n\nstruct Candidate {\n    int i, j, dir;\n    int cost, count;\n    double ratio;\n};\n\n// Find the best operation on a given grid (without modifying it)\nCandidate best_op(const vector<vector<char>>& grid) {\n    int n = grid.size();\n    Candidate best = {-1, -1, -1, 0, 0, -1.0};\n    \n    auto is_safe = [&](int i, int j, int dir) -> bool {\n        if (dir == 0) { // up\n            for (int r = 0; r < i; ++r) {\n                if (grid[r][j] == 'o') return false;\n            }\n            return true;\n        } else if (dir == 1) { // down\n            for (int r = i+1; r < n; ++r) {\n                if (grid[r][j] == 'o') return false;\n            }\n            return true;\n        } else if (dir == 2) { // left\n            for (int c = 0; c < j; ++c) {\n                if (grid[i][c] == 'o') return false;\n            }\n            return true;\n        } else { // right\n            for (int c = j+1; c < n; ++c) {\n                if (grid[i][c] == 'o') return false;\n            }\n            return true;\n        }\n    };\n    \n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (grid[i][j] != 'x') continue;\n            for (int dir = 0; dir < 4; ++dir) {\n                if (!is_safe(i, j, dir)) continue;\n                int cost;\n                if (dir == 0) cost = i + 1;\n                else if (dir == 1) cost = n - i;\n                else if (dir == 2) cost = j + 1;\n                else cost = n - j;\n                \n                int count = 0;\n                if (dir == 0) { // up\n                    for (int r = 0; r <= i; ++r) {\n                        if (grid[r][j] == 'x') count++;\n                    }\n                } else if (dir == 1) { // down\n                    for (int r = i; r < n; ++r) {\n                        if (grid[r][j] == 'x') count++;\n                    }\n                } else if (dir == 2) { // left\n                    for (int c = 0; c <= j; ++c) {\n                        if (grid[i][c] == 'x') count++;\n                    }\n                } else { // right\n                    for (int c = j; c < n; ++c) {\n                        if (grid[i][c] == 'x') count++;\n                    }\n                }\n                \n                double ratio = static_cast<double>(count) / cost;\n                if (ratio > best.ratio || (ratio == best.ratio && cost < best.cost)) {\n                    best = {i, j, dir, cost, count, ratio};\n                }\n            }\n        }\n    }\n    return best;\n}\n\n// Apply an operation to a grid and return the new grid\nvector<vector<char>> apply_op(const vector<vector<char>>& grid, const Candidate& op) {\n    int n = grid.size();\n    vector<vector<char>> new_grid = grid;\n    if (op.dir == 0) { // up\n        for (int r = 0; r <= op.i; ++r) new_grid[r][op.j] = '.';\n    } else if (op.dir == 1) { // down\n        for (int r = op.i; r < n; ++r) new_grid[r][op.j] = '.';\n    } else if (op.dir == 2) { // left\n        for (int c = 0; c <= op.j; ++c) new_grid[op.i][c] = '.';\n    } else { // right\n        for (int c = op.j; c < n; ++c) new_grid[op.i][c] = '.';\n    }\n    return new_grid;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    int n;\n    cin >> n;\n    vector<string> board(n);\n    for (int i = 0; i < n; ++i) {\n        cin >> board[i];\n    }\n    \n    vector<vector<char>> grid(n, vector<char>(n));\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            grid[i][j] = board[i][j];\n        }\n    }\n    \n    vector<Op> ops;\n    \n    while (true) {\n        bool any_oni = false;\n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                if (grid[i][j] == 'x') {\n                    any_oni = true;\n                    break;\n                }\n            }\n            if (any_oni) break;\n        }\n        if (!any_oni) break;\n        \n        // Collect all possible operations with their ratios\n        vector<Candidate> candidates;\n        auto is_safe = [&](int i, int j, int dir) -> bool {\n            if (dir == 0) { // up\n                for (int r = 0; r < i; ++r) {\n                    if (grid[r][j] == 'o') return false;\n                }\n                return true;\n            } else if (dir == 1) { // down\n                for (int r = i+1; r < n; ++r) {\n                    if (grid[r][j] == 'o') return false;\n                }\n                return true;\n            } else if (dir == 2) { // left\n                for (int c = 0; c < j; ++c) {\n                    if (grid[i][c] == 'o') return false;\n                }\n                return true;\n            } else { // right\n                for (int c = j+1; c < n; ++c) {\n                    if (grid[i][c] == 'o') return false;\n                }\n                return true;\n            }\n        };\n        \n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                if (grid[i][j] != 'x') continue;\n                for (int dir = 0; dir < 4; ++dir) {\n                    if (!is_safe(i, j, dir)) continue;\n                    int cost;\n                    if (dir == 0) cost = i + 1;\n                    else if (dir == 1) cost = n - i;\n                    else if (dir == 2) cost = j + 1;\n                    else cost = n - j;\n                    \n                    int count = 0;\n                    if (dir == 0) { // up\n                        for (int r = 0; r <= i; ++r) {\n                            if (grid[r][j] == 'x') count++;\n                        }\n                    } else if (dir == 1) { // down\n                        for (int r = i; r < n; ++r) {\n                            if (grid[r][j] == 'x') count++;\n                        }\n                    } else if (dir == 2) { // left\n                        for (int c = 0; c <= j; ++c) {\n                            if (grid[i][c] == 'x') count++;\n                        }\n                    } else { // right\n                        for (int c = j; c < n; ++c) {\n                            if (grid[i][c] == 'x') count++;\n                        }\n                    }\n                    \n                    double ratio = static_cast<double>(count) / cost;\n                    candidates.push_back({i, j, dir, cost, count, ratio});\n                }\n            }\n        }\n        \n        // Sort by ratio descending, then by cost ascending\n        sort(candidates.begin(), candidates.end(), [](const Candidate& a, const Candidate& b) {\n            if (a.ratio != b.ratio) return a.ratio > b.ratio;\n            return a.cost < b.cost;\n        });\n        \n        // Keep only top TOP_K candidates\n        if (candidates.size() > TOP_K) {\n            candidates.resize(TOP_K);\n        }\n        \n        double best_combined_ratio = -1.0;\n        Candidate best_first = {-1, -1, -1, 0, 0, -1.0};\n        \n        for (const auto& first : candidates) {\n            // Apply first operation\n            vector<vector<char>> grid1 = apply_op(grid, first);\n            \n            // Find best second operation on grid1\n            Candidate second = best_op(grid1);\n            if (second.count == 0) {\n                // No more Oni after first operation\n                double combined_ratio = static_cast<double>(first.count) / first.cost;\n                if (combined_ratio > best_combined_ratio || \n                    (combined_ratio == best_combined_ratio && first.cost < best_first.cost)) {\n                    best_combined_ratio = combined_ratio;\n                    best_first = first;\n                }\n                continue;\n            }\n            \n            // Apply second operation\n            vector<vector<char>> grid2 = apply_op(grid1, second);\n            \n            // Find best third operation on grid2\n            Candidate third = best_op(grid2);\n            double combined_ratio;\n            if (third.count == 0) {\n                combined_ratio = static_cast<double>(first.count + second.count) / (first.cost + second.cost);\n            } else {\n                combined_ratio = static_cast<double>(first.count + second.count + third.count) / \n                                 (first.cost + second.cost + third.cost);\n            }\n            \n            if (combined_ratio > best_combined_ratio || \n                (combined_ratio == best_combined_ratio && first.cost < best_first.cost)) {\n                best_combined_ratio = combined_ratio;\n                best_first = first;\n            }\n        }\n        \n        // Apply the chosen first operation\n        if (best_first.dir == 0) { // up\n            int k = best_first.i + 1;\n            ops.push_back({0, best_first.j, k});\n            for (int r = 0; r <= best_first.i; ++r) grid[r][best_first.j] = '.';\n        } else if (best_first.dir == 1) { // down\n            int k = n - best_first.i;\n            ops.push_back({1, best_first.j, k});\n            for (int r = best_first.i; r < n; ++r) grid[r][best_first.j] = '.';\n        } else if (best_first.dir == 2) { // left\n            int k = best_first.j + 1;\n            ops.push_back({2, best_first.i, k});\n            for (int c = 0; c <= best_first.j; ++c) grid[best_first.i][c] = '.';\n        } else { // right\n            int k = n - best_first.j;\n            ops.push_back({3, best_first.i, k});\n            for (int c = best_first.j; c < n; ++c) grid[best_first.i][c] = '.';\n        }\n    }\n    \n    // Merge operations\n    unordered_map<int, int> up_ops;   // column -> max k\n    unordered_map<int, int> down_ops; // column -> max k\n    unordered_map<int, int> left_ops; // row -> max k\n    unordered_map<int, int> right_ops; // row -> max k\n    \n    for (const auto& op : ops) {\n        if (op.type == 0) { // U\n            if (up_ops.find(op.idx) == up_ops.end() || op.k > up_ops[op.idx]) {\n                up_ops[op.idx] = op.k;\n            }\n        } else if (op.type == 1) { // D\n            if (down_ops.find(op.idx) == down_ops.end() || op.k > down_ops[op.idx]) {\n                down_ops[op.idx] = op.k;\n            }\n        } else if (op.type == 2) { // L\n            if (left_ops.find(op.idx) == left_ops.end() || op.k > left_ops[op.idx]) {\n                left_ops[op.idx] = op.k;\n            }\n        } else { // R\n            if (right_ops.find(op.idx) == right_ops.end() || op.k > right_ops[op.idx]) {\n                right_ops[op.idx] = op.k;\n            }\n        }\n    }\n    \n    // Output merged operations\n    for (const auto& [col, k] : up_ops) {\n        for (int t = 0; t < k; ++t) cout << \"U \" << col << \"\\n\";\n        for (int t = 0; t < k; ++t) cout << \"D \" << col << \"\\n\";\n    }\n    for (const auto& [col, k] : down_ops) {\n        for (int t = 0; t < k; ++t) cout << \"D \" << col << \"\\n\";\n        for (int t = 0; t < k; ++t) cout << \"U \" << col << \"\\n\";\n    }\n    for (const auto& [row, k] : left_ops) {\n        for (int t = 0; t < k; ++t) cout << \"L \" << row << \"\\n\";\n        for (int t = 0; t < k; ++t) cout << \"R \" << row << \"\\n\";\n    }\n    for (const auto& [row, k] : right_ops) {\n        for (int t = 0; t < k; ++t) cout << \"R \" << row << \"\\n\";\n        for (int t = 0; t < k; ++t) cout << \"L \" << row << \"\\n\";\n    }\n    \n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, L;\n    cin >> N >> L;\n    vector<int> T(N);\n    for (int i = 0; i < N; ++i) cin >> T[i];\n\n    // Fast random generator\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    // ---------- Flow-based initialization (previous best) ----------\n    vector<int> a(N), b(N);\n    vector<int> need(N);\n    need[0] = max(0, T[0] - 1);\n    for (int i = 1; i < N; ++i) need[i] = T[i];\n\n    // Create supplies: (weight, employee, type)\n    vector<tuple<int, int, int>> supplies;\n    for (int i = 0; i < N; ++i) {\n        int odd = (T[i] + 1) / 2;\n        int even = T[i] / 2;\n        supplies.emplace_back(odd, i, 0); // type 0 for a_i\n        supplies.emplace_back(even, i, 1); // type 1 for b_i\n    }\n    // Sort by weight descending\n    sort(supplies.begin(), supplies.end(),\n         [](const auto& x, const auto& y) { return get<0>(x) > get<0>(y); });\n\n    // Priority queue for demands\n    priority_queue<pair<int, int>> pq;\n    for (int j = 0; j < N; ++j) {\n        if (need[j] > 0) pq.emplace(need[j], j);\n    }\n\n    // Assign edges greedily\n    for (const auto& [weight, i, type] : supplies) {\n        if (pq.empty()) break;\n        auto [rem, j] = pq.top();\n        pq.pop();\n        if (type == 0) a[i] = j;\n        else b[i] = j;\n        rem -= weight;\n        if (rem > 0) pq.emplace(rem, j);\n    }\n\n    // ---------- Build transition table ----------\n    array<array<int, 2>, 100> nxt;\n    for (int i = 0; i < N; ++i) {\n        nxt[i][0] = b[i];\n        nxt[i][1] = a[i];\n    }\n\n    // ---------- Simulation function ----------\n    auto simulate = [&]() {\n        int cnt[100] = {0};\n        cnt[0] = 1;\n        int cur = 0;\n        int steps = L - 1;\n        while (steps--) {\n            int parity = cnt[cur] & 1;\n            int next_emp = nxt[cur][parity];\n            ++cnt[next_emp];\n            cur = next_emp;\n        }\n        int error = 0;\n        for (int i = 0; i < N; ++i) {\n            error += abs(cnt[i] - T[i]);\n        }\n        return error;\n    };\n\n    int cur_error = simulate();\n    int best_error = cur_error;\n    vector<int> best_a = a, best_b = b;\n\n    // ---------- Simulated Annealing ----------\n    double temp = 1000.0;\n    const double cooling = 0.998;\n    auto start_time = chrono::steady_clock::now();\n    const double time_limit = 1.6; // Strict limit for SA\n    uniform_real_distribution<double> dist(0.0, 1.0);\n\n    int iter = 0;\n    int no_improve = 0;\n    while (true) {\n        // Check time every 64 iterations\n        if ((iter & 63) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > time_limit) break;\n        }\n        ++iter;\n\n        // Choose random edge\n        int i = rng() % N;\n        int type = rng() % 2;\n        int old_val = (type == 0) ? a[i] : b[i];\n        int new_val = rng() % N;\n        if (new_val == old_val) continue;\n\n        // Apply change\n        if (type == 0) {\n            a[i] = new_val;\n            nxt[i][1] = new_val;\n        } else {\n            b[i] = new_val;\n            nxt[i][0] = new_val;\n        }\n\n        int new_error = simulate();\n        int delta = new_error - cur_error;\n\n        bool accept = false;\n        if (delta < 0) {\n            accept = true;\n        } else {\n            double prob = exp(-delta / temp);\n            if (dist(rng) < prob) accept = true;\n        }\n\n        if (accept) {\n            cur_error = new_error;\n            if (cur_error < best_error) {\n                best_error = cur_error;\n                best_a = a;\n                best_b = b;\n                no_improve = 0;\n                if (best_error == 0) break;\n            } else {\n                ++no_improve;\n            }\n        } else {\n            // Revert\n            if (type == 0) {\n                a[i] = old_val;\n                nxt[i][1] = old_val;\n            } else {\n                b[i] = old_val;\n                nxt[i][0] = old_val;\n            }\n            ++no_improve;\n        }\n\n        // If stuck, do a small perturbation\n        if (no_improve > 500) {\n            // Reset to best and perturb 3 edges\n            a = best_a;\n            b = best_b;\n            for (int i = 0; i < N; ++i) {\n                nxt[i][0] = b[i];\n                nxt[i][1] = a[i];\n            }\n            \n            for (int k = 0; k < 3; ++k) {\n                int j = rng() % N;\n                int t = rng() % 2;\n                int old = (t == 0) ? a[j] : b[j];\n                int nv = rng() % N;\n                if (t == 0) {\n                    a[j] = nv;\n                    nxt[j][1] = nv;\n                } else {\n                    b[j] = nv;\n                    nxt[j][0] = nv;\n                }\n            }\n            cur_error = simulate();\n            no_improve = 0;\n        }\n\n        // Cool down\n        temp *= cooling;\n    }\n\n    // ---------- Quick local search if time remains ----------\n    auto now = chrono::steady_clock::now();\n    double elapsed = chrono::duration<double>(now - start_time).count();\n    if (elapsed < 1.9) {\n        // Reset to best solution\n        a = best_a;\n        b = best_b;\n        for (int i = 0; i < N; ++i) {\n            nxt[i][0] = b[i];\n            nxt[i][1] = a[i];\n        }\n        cur_error = simulate();\n        \n        // Try a few random improvements\n        for (int attempt = 0; attempt < 100; ++attempt) {\n            int i = rng() % N;\n            int type = rng() % 2;\n            int old_val = (type == 0) ? a[i] : b[i];\n            int new_val = rng() % N;\n            if (new_val == old_val) continue;\n            \n            if (type == 0) {\n                a[i] = new_val;\n                nxt[i][1] = new_val;\n            } else {\n                b[i] = new_val;\n                nxt[i][0] = new_val;\n            }\n            \n            int new_error = simulate();\n            if (new_error < cur_error) {\n                cur_error = new_error;\n                if (cur_error < best_error) {\n                    best_error = cur_error;\n                    best_a = a;\n                    best_b = b;\n                }\n            } else {\n                // Revert\n                if (type == 0) {\n                    a[i] = old_val;\n                    nxt[i][1] = old_val;\n                } else {\n                    b[i] = old_val;\n                    nxt[i][0] = old_val;\n                }\n            }\n        }\n    }\n\n    // ---------- Output ----------\n    for (int i = 0; i < N; ++i) {\n        cout << best_a[i] << \" \" << best_b[i] << \"\\n\";\n    }\n\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\n#include <boost/geometry.hpp>\n#include <boost/geometry/index/rtree.hpp>\n\nnamespace bg = boost::geometry;\nnamespace bgi = boost::geometry::index;\n\nusing point = bg::model::point<double, 2, bg::cs::cartesian>;\nusing box = bg::model::box<point>;\nusing value = std::pair<box, int>;\n\n// Hilbert value computation for ordering\ninline uint32_t hilbertOrder(int x, int y, int iterations = 10) {\n    uint32_t d = 0;\n    for (int s = 1 << (iterations - 1); s > 0; s >>= 1) {\n        bool rx = (x & s) > 0;\n        bool ry = (y & s) > 0;\n        d = (d << 2) | ((rx ? 1 : 0) * 3) ^ (ry ? 1 : 0);\n        if (!ry) {\n            if (rx) {\n                x = (1 << iterations) - 1 - x;\n                y = (1 << iterations) - 1 - y;\n            }\n            std::swap(x, y);\n        }\n    }\n    return d;\n}\n\nint main() {\n    std::ios::sync_with_stdio(false);\n    std::cin.tie(nullptr);\n\n    int N, M, Q, L, W;\n    std::cin >> N >> M >> Q >> L >> W;\n\n    std::vector<int> G(M);\n    for (int i = 0; i < M; ++i) {\n        std::cin >> G[i];\n    }\n\n    std::vector<int> lx(N), rx(N), ly(N), ry(N);\n    std::vector<double> cx(N), cy(N);\n    std::vector<box> boxes(N);\n    \n    for (int i = 0; i < N; ++i) {\n        std::cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n        cx[i] = (lx[i] + rx[i]) / 2.0;\n        cy[i] = (ly[i] + ry[i]) / 2.0;\n        boxes[i] = box(point(lx[i], ly[i]), point(rx[i], ry[i]));\n    }\n\n    // Create R-tree for spatial queries\n    bgi::rtree<value, bgi::quadratic<16>> rtree;\n    for (int i = 0; i < N; ++i) {\n        rtree.insert(std::make_pair(boxes[i], i));\n    }\n\n    // Order cities by Hilbert curve for better spatial locality\n    std::vector<int> order(N);\n    std::iota(order.begin(), order.end(), 0);\n    std::sort(order.begin(), order.end(), [&](int i, int j) {\n        // Scale coordinates to [0, 2^20) for Hilbert curve\n        int xi = static_cast<int>((cx[i] / 10000.0) * (1 << 20));\n        int yi = static_cast<int>((cy[i] / 10000.0) * (1 << 20));\n        int xj = static_cast<int>((cx[j] / 10000.0) * (1 << 20));\n        int yj = static_cast<int>((cy[j] / 10000.0) * (1 << 20));\n        return hilbertOrder(xi, yi) < hilbertOrder(xj, yj);\n    });\n\n    // Cluster cities into groups using a balanced approach\n    std::vector<std::vector<int>> groups(M);\n    std::vector<bool> used(N, false);\n    \n    for (int k = 0; k < M; ++k) {\n        if (groups[k].size() == G[k]) continue;\n        \n        // Find the city with smallest uncertainty that hasn't been assigned\n        int start = -1;\n        double min_area = 1e18;\n        for (int i : order) {\n            if (!used[i]) {\n                double area = (rx[i] - lx[i]) * (ry[i] - ly[i]);\n                if (area < min_area) {\n                    min_area = area;\n                    start = i;\n                }\n            }\n        }\n        \n        // If no unassigned city, break (shouldn't happen)\n        if (start == -1) break;\n        \n        // Use BFS to collect nearby cities for this group\n        std::queue<int> q;\n        q.push(start);\n        used[start] = true;\n        groups[k].push_back(start);\n        \n        while (!q.empty() && groups[k].size() < G[k]) {\n            int curr = q.front();\n            q.pop();\n            \n            // Query R-tree for nearest cities\n            std::vector<value> results;\n            point center(cx[curr], cy[curr]);\n            rtree.query(bgi::nearest(center, 10), std::back_inserter(results));\n            \n            for (const auto& [box, idx] : results) {\n                if (!used[idx] && groups[k].size() < G[k]) {\n                    used[idx] = true;\n                    groups[k].push_back(idx);\n                    q.push(idx);\n                }\n            }\n        }\n        \n        // If we still need more cities, add the closest available\n        while (groups[k].size() < G[k]) {\n            double min_dist = 1e18;\n            int best = -1;\n            for (int i = 0; i < N; ++i) {\n                if (!used[i]) {\n                    double dx = cx[groups[k][0]] - cx[i];\n                    double dy = cy[groups[k][0]] - cy[i];\n                    double dist = dx*dx + dy*dy;\n                    if (dist < min_dist) {\n                        min_dist = dist;\n                        best = i;\n                    }\n                }\n            }\n            if (best != -1) {\n                used[best] = true;\n                groups[k].push_back(best);\n            } else {\n                break; // Shouldn't happen if sum G_i = N\n            }\n        }\n    }\n\n    std::vector<std::vector<std::pair<int, int>>> group_edges(M);\n    int query_count = 0;\n\n    // First pass: Use basic sliding window queries\n    for (int k = 0; k < M; ++k) {\n        const auto& cities = groups[k];\n        int g = cities.size();\n        if (g == 1) continue;\n\n        if (g <= L) {\n            std::cout << \"? \" << g;\n            for (int city : cities) std::cout << \" \" << city;\n            std::cout << std::endl;\n            std::cout.flush();\n            \n            for (int i = 0; i < g - 1; ++i) {\n                int a, b;\n                std::cin >> a >> b;\n                group_edges[k].emplace_back(a, b);\n            }\n            query_count++;\n        } else {\n            int step = L - 1;\n            int windows = (g - 1 + step - 1) / step;\n            for (int w = 0; w < windows; ++w) {\n                int start = w * step;\n                int end = std::min(start + L, g);\n                int sz = end - start;\n                \n                std::cout << \"? \" << sz;\n                for (int i = start; i < end; ++i) {\n                    std::cout << \" \" << cities[i];\n                }\n                std::cout << std::endl;\n                std::cout.flush();\n                \n                for (int i = 0; i < sz - 1; ++i) {\n                    int a, b;\n                    std::cin >> a >> b;\n                    group_edges[k].emplace_back(a, b);\n                }\n                query_count++;\n            }\n        }\n    }\n\n    // Second pass: Use remaining queries to improve largest groups\n    int remaining_queries = Q - query_count;\n    if (remaining_queries > 0) {\n        // Sort groups by size descending\n        std::vector<int> group_indices(M);\n        std::iota(group_indices.begin(), group_indices.end(), 0);\n        std::sort(group_indices.begin(), group_indices.end(), \n                 [&](int a, int b) { return groups[a].size() > groups[b].size(); });\n        \n        for (int k : group_indices) {\n            if (remaining_queries <= 0) break;\n            \n            const auto& cities = groups[k];\n            int g = cities.size();\n            if (g <= L) continue; // Already optimal\n            \n            // Add extra overlapping windows for this group\n            int extra_windows = std::min(remaining_queries, (g - L) / 2 + 1);\n            for (int w = 0; w < extra_windows; ++w) {\n                int start = w * 2; // Step of 2 for more overlap\n                if (start + L > g) break;\n                \n                std::cout << \"? \" << L;\n                for (int i = start; i < start + L; ++i) {\n                    std::cout << \" \" << cities[i];\n                }\n                std::cout << std::endl;\n                std::cout.flush();\n                \n                for (int i = 0; i < L - 1; ++i) {\n                    int a, b;\n                    std::cin >> a >> b;\n                    group_edges[k].emplace_back(a, b);\n                }\n                remaining_queries--;\n            }\n            \n            // Run Kruskal on collected edges using lower-bound distances\n            if (group_edges[k].size() > g - 1) {\n                // Build adjacency list with lower-bound distances\n                std::vector<std::tuple<double, int, int>> edges_with_weights;\n                for (const auto& [a, b] : group_edges[k]) {\n                    // Compute lower-bound distance between rectangles\n                    double dx = std::max({0.0, \n                                        static_cast<double>(lx[a] - rx[b]),\n                                        static_cast<double>(lx[b] - rx[a])});\n                    double dy = std::max({0.0, \n                                        static_cast<double>(ly[a] - ry[b]),\n                                        static_cast<double>(ly[b] - ry[a])});\n                    double lb_dist = std::sqrt(dx*dx + dy*dy);\n                    edges_with_weights.emplace_back(lb_dist, a, b);\n                }\n                \n                // Kruskal's algorithm\n                std::sort(edges_with_weights.begin(), edges_with_weights.end());\n                std::vector<int> parent(N);\n                std::iota(parent.begin(), parent.end(), 0);\n                \n                auto find = [&](int x) {\n                    while (parent[x] != x) {\n                        parent[x] = parent[parent[x]];\n                        x = parent[x];\n                    }\n                    return x;\n                };\n                \n                group_edges[k].clear();\n                for (const auto& [w, a, b] : edges_with_weights) {\n                    int ra = find(a), rb = find(b);\n                    if (ra != rb) {\n                        parent[ra] = rb;\n                        group_edges[k].emplace_back(a, b);\n                        if (group_edges[k].size() == g - 1) break;\n                    }\n                }\n            }\n        }\n    }\n\n    // Output answer\n    std::cout << \"!\" << std::endl;\n    for (int k = 0; k < M; ++k) {\n        // Output cities in the group\n        for (size_t i = 0; i < groups[k].size(); ++i) {\n            if (i > 0) std::cout << \" \";\n            std::cout << groups[k][i];\n        }\n        std::cout << std::endl;\n        \n        // Output edges\n        for (const auto& [a, b] : group_edges[k]) {\n            std::cout << a << \" \" << b << std::endl;\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n    vector<pair<int, int>> pts(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> pts[i].first >> pts[i].second;\n    }\n\n    vector<string> actions;\n\n    for (int i = 0; i < M - 1; ++i) {\n        int r1 = pts[i].first, c1 = pts[i].second;\n        int r2 = pts[i + 1].first, c2 = pts[i + 1].second;\n\n        // ----- compute costs of the nine possible plans -----\n        int direct = abs(r1 - r2) + abs(c1 - c2);\n\n        int costU = (r1 > 0 ? 1 : 0) + abs(c1 - c2) + r2;\n        int costD = (r1 < N - 1 ? 1 : 0) + abs(c1 - c2) + (N - 1 - r2);\n        int costL = (c1 > 0 ? 1 : 0) + abs(r1 - r2) + c2;\n        int costR = (c1 < N - 1 ? 1 : 0) + abs(r1 - r2) + (N - 1 - c2);\n\n        // Corner plans\n        int costTL = (r1 > 0 ? 1 : 0) + (c1 > 0 ? 1 : 0) + r2 + c2;\n        int costTR = (r1 > 0 ? 1 : 0) + (c1 < N - 1 ? 1 : 0) + r2 + (N - 1 - c2);\n        int costBL = (r1 < N - 1 ? 1 : 0) + (c1 > 0 ? 1 : 0) + (N - 1 - r2) + c2;\n        int costBR = (r1 < N - 1 ? 1 : 0) + (c1 < N - 1 ? 1 : 0) + (N - 1 - r2) + (N - 1 - c2);\n\n        // ----- choose the cheapest plan -----\n        int best = direct;\n        int option = 0; // 0:direct, 1:up, 2:down, 3:left, 4:right, 5:TL, 6:TR, 7:BL, 8:BR\n        if (costU < best) { best = costU; option = 1; }\n        if (costD < best) { best = costD; option = 2; }\n        if (costL < best) { best = costL; option = 3; }\n        if (costR < best) { best = costR; option = 4; }\n        if (costTL < best) { best = costTL; option = 5; }\n        if (costTR < best) { best = costTR; option = 6; }\n        if (costBL < best) { best = costBL; option = 7; }\n        if (costBR < best) { best = costBR; option = 8; }\n\n        // ----- generate the actions for the chosen plan -----\n        switch (option) {\n            case 0: // direct moves\n                if (r2 > r1) {\n                    for (int k = 0; k < r2 - r1; ++k) actions.push_back(\"M D\");\n                } else if (r2 < r1) {\n                    for (int k = 0; k < r1 - r2; ++k) actions.push_back(\"M U\");\n                }\n                if (c2 > c1) {\n                    for (int k = 0; k < c2 - c1; ++k) actions.push_back(\"M R\");\n                } else if (c2 < c1) {\n                    for (int k = 0; k < c1 - c2; ++k) actions.push_back(\"M L\");\n                }\n                break;\n\n            case 1: // Up\n                if (r1 > 0) actions.push_back(\"S U\");\n                if (c2 > c1) {\n                    for (int k = 0; k < c2 - c1; ++k) actions.push_back(\"M R\");\n                } else if (c2 < c1) {\n                    for (int k = 0; k < c1 - c2; ++k) actions.push_back(\"M L\");\n                }\n                if (r2 > 0) {\n                    for (int k = 0; k < r2; ++k) actions.push_back(\"M D\");\n                }\n                break;\n\n            case 2: // Down\n                if (r1 < N - 1) actions.push_back(\"S D\");\n                if (c2 > c1) {\n                    for (int k = 0; k < c2 - c1; ++k) actions.push_back(\"M R\");\n                } else if (c2 < c1) {\n                    for (int k = 0; k < c1 - c2; ++k) actions.push_back(\"M L\");\n                }\n                if (r2 < N - 1) {\n                    int steps = N - 1 - r2;\n                    for (int k = 0; k < steps; ++k) actions.push_back(\"M U\");\n                }\n                break;\n\n            case 3: // Left\n                if (c1 > 0) actions.push_back(\"S L\");\n                if (r2 > r1) {\n                    for (int k = 0; k < r2 - r1; ++k) actions.push_back(\"M D\");\n                } else if (r2 < r1) {\n                    for (int k = 0; k < r1 - r2; ++k) actions.push_back(\"M U\");\n                }\n                if (c2 > 0) {\n                    for (int k = 0; k < c2; ++k) actions.push_back(\"M R\");\n                }\n                break;\n\n            case 4: // Right\n                if (c1 < N - 1) actions.push_back(\"S R\");\n                if (r2 > r1) {\n                    for (int k = 0; k < r2 - r1; ++k) actions.push_back(\"M D\");\n                } else if (r2 < r1) {\n                    for (int k = 0; k < r1 - r2; ++k) actions.push_back(\"M U\");\n                }\n                if (c2 < N - 1) {\n                    int steps = N - 1 - c2;\n                    for (int k = 0; k < steps; ++k) actions.push_back(\"M L\");\n                }\n                break;\n\n            case 5: // Top-left corner\n                if (r1 > 0) actions.push_back(\"S U\");\n                if (c1 > 0) actions.push_back(\"S L\");\n                // now at (0,0)\n                if (c2 > 0) {\n                    for (int k = 0; k < c2; ++k) actions.push_back(\"M R\");\n                }\n                if (r2 > 0) {\n                    for (int k = 0; k < r2; ++k) actions.push_back(\"M D\");\n                }\n                break;\n\n            case 6: // Top-right corner\n                if (r1 > 0) actions.push_back(\"S U\");\n                if (c1 < N - 1) actions.push_back(\"S R\");\n                // now at (0,N-1)\n                if (r2 > 0) {\n                    for (int k = 0; k < r2; ++k) actions.push_back(\"M D\");\n                }\n                if (c2 < N - 1) {\n                    int steps = N - 1 - c2;\n                    for (int k = 0; k < steps; ++k) actions.push_back(\"M L\");\n                }\n                break;\n\n            case 7: // Bottom-left corner\n                if (r1 < N - 1) actions.push_back(\"S D\");\n                if (c1 > 0) actions.push_back(\"S L\");\n                // now at (N-1,0)\n                if (r2 < N - 1) {\n                    int steps = N - 1 - r2;\n                    for (int k = 0; k < steps; ++k) actions.push_back(\"M U\");\n                }\n                if (c2 > 0) {\n                    for (int k = 0; k < c2; ++k) actions.push_back(\"M R\");\n                }\n                break;\n\n            case 8: // Bottom-right corner\n                if (r1 < N - 1) actions.push_back(\"S D\");\n                if (c1 < N - 1) actions.push_back(\"S R\");\n                // now at (N-1,N-1)\n                if (r2 < N - 1) {\n                    int steps = N - 1 - r2;\n                    for (int k = 0; k < steps; ++k) actions.push_back(\"M U\");\n                }\n                if (c2 < N - 1) {\n                    int steps = N - 1 - c2;\n                    for (int k = 0; k < steps; ++k) actions.push_back(\"M L\");\n                }\n                break;\n        }\n    }\n\n    // ----- output all actions -----\n    for (const string& act : actions) {\n        cout << act << '\\n';\n    }\n\n    return 0;\n}"},"16":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\n\nstruct Company {\n    int x, y, r;\n};\n\nstruct Node {\n    int x1, y1, x2, y2;\n    vector<int> ids;\n    int cut_type;   // 0: leaf, 1: vertical, 2: horizontal\n    int cut_pos;\n    Node *left, *right;\n    ll total_r;\n    Node() : left(nullptr), right(nullptr) {}\n};\n\nint n;\nvector<Company> comps;\nvector<int> a, b, c, d;\n\nNode* build(int x1, int y1, int x2, int y2, vector<int>& ids) {\n    Node* node = new Node();\n    node->x1 = x1; node->y1 = y1; node->x2 = x2; node->y2 = y2;\n    node->ids = ids;\n\n    if (ids.size() == 1) {\n        node->cut_type = 0;\n        node->total_r = comps[ids[0]].r;\n        return node;\n    }\n\n    ll total_r = 0;\n    ll total_r2 = 0;\n    for (int i : ids) {\n        total_r += comps[i].r;\n        total_r2 += (ll)comps[i].r * comps[i].r;\n    }\n    node->total_r = total_r;\n\n    int min_x = 10000, max_x = 0, min_y = 10000, max_y = 0;\n    for (int i : ids) {\n        min_x = min(min_x, comps[i].x);\n        max_x = max(max_x, comps[i].x);\n        min_y = min(min_y, comps[i].y);\n        max_y = max(max_y, comps[i].y);\n    }\n\n    ll best_cost = LLONG_MAX;\n    int best_type = -1;\n    int best_pos = -1;\n\n    // Vertical cuts\n    if (max_x > min_x) {\n        for (int X = x1 + 1; X < x2; ++X) {\n            if (X <= min_x || X > max_x) continue;\n            ll left_sum = 0, left_sum2 = 0;\n            int left_count = 0;\n            for (int i : ids) {\n                if (comps[i].x < X) {\n                    left_sum += comps[i].r;\n                    left_sum2 += (ll)comps[i].r * comps[i].r;\n                    left_count++;\n                }\n            }\n            if (left_count == 0 || left_count == ids.size()) continue;\n            \n            ll left_area = (ll)(X - x1) * (y2 - y1);\n            ll right_sum = total_r - left_sum;\n            ll right_sum2 = total_r2 - left_sum2;\n            int right_count = ids.size() - left_count;\n            ll right_area = (ll)(x2 - X) * (y2 - y1);\n            \n            // Absolute area cost\n            ll area_cost = abs(left_area - left_sum) + abs(right_area - right_sum);\n            \n            // Count balancing cost\n            ll count_cost = abs(left_count - right_count);\n            \n            // Variance cost with optimal weight 1e-6\n            double left_variance = 0.0, right_variance = 0.0;\n            if (left_count > 0) {\n                double mean_left = (double)left_sum / left_count;\n                left_variance = left_sum2 - 2 * mean_left * left_sum + left_count * mean_left * mean_left;\n            }\n            if (right_count > 0) {\n                double mean_right = (double)right_sum / right_count;\n                right_variance = right_sum2 - 2 * mean_right * right_sum + right_count * mean_right * mean_right;\n            }\n            double variance_cost = (left_variance + right_variance) * 1e-6;\n            \n            // Desired sum balance cost (encourages equal total desired area in children)\n            ll sum_diff_cost = abs(left_sum - right_sum) / 1000; // weight ~0.001\n            \n            // Total cost\n            ll cost = area_cost + count_cost * (total_r / 1000) + (ll)variance_cost + sum_diff_cost;\n            \n            if (cost < best_cost) {\n                best_cost = cost;\n                best_type = 1;\n                best_pos = X;\n            }\n        }\n    }\n\n    // Horizontal cuts\n    if (max_y > min_y) {\n        for (int Y = y1 + 1; Y < y2; ++Y) {\n            if (Y <= min_y || Y > max_y) continue;\n            ll bottom_sum = 0, bottom_sum2 = 0;\n            int bottom_count = 0;\n            for (int i : ids) {\n                if (comps[i].y < Y) {\n                    bottom_sum += comps[i].r;\n                    bottom_sum2 += (ll)comps[i].r * comps[i].r;\n                    bottom_count++;\n                }\n            }\n            if (bottom_count == 0 || bottom_count == ids.size()) continue;\n            \n            ll bottom_area = (ll)(x2 - x1) * (Y - y1);\n            ll top_sum = total_r - bottom_sum;\n            ll top_sum2 = total_r2 - bottom_sum2;\n            int top_count = ids.size() - bottom_count;\n            ll top_area = (ll)(x2 - x1) * (y2 - Y);\n            \n            ll area_cost = abs(bottom_area - bottom_sum) + abs(top_area - top_sum);\n            ll count_cost = abs(bottom_count - top_count);\n            \n            double bottom_variance = 0.0, top_variance = 0.0;\n            if (bottom_count > 0) {\n                double mean_bottom = (double)bottom_sum / bottom_count;\n                bottom_variance = bottom_sum2 - 2 * mean_bottom * bottom_sum + bottom_count * mean_bottom * mean_bottom;\n            }\n            if (top_count > 0) {\n                double mean_top = (double)top_sum / top_count;\n                top_variance = top_sum2 - 2 * mean_top * top_sum + top_count * mean_top * mean_top;\n            }\n            double variance_cost = (bottom_variance + top_variance) * 1e-6;\n            \n            ll sum_diff_cost = abs(bottom_sum - top_sum) / 1000;\n            \n            ll cost = area_cost + count_cost * (total_r / 1000) + (ll)variance_cost + sum_diff_cost;\n            \n            if (cost < best_cost) {\n                best_cost = cost;\n                best_type = 2;\n                best_pos = Y;\n            }\n        }\n    }\n\n    // Fallback if no valid cut found\n    if (best_type == -1) {\n        if (max_x > min_x) {\n            best_type = 1;\n            best_pos = (min_x + max_x + 1) / 2;\n            best_pos = max(x1 + 1, min(x2 - 1, best_pos));\n        } else {\n            best_type = 2;\n            best_pos = (min_y + max_y + 1) / 2;\n            best_pos = max(y1 + 1, min(y2 - 1, best_pos));\n        }\n    }\n\n    if (best_type == 1) {\n        vector<int> left_ids, right_ids;\n        for (int i : ids) {\n            if (comps[i].x < best_pos) left_ids.push_back(i);\n            else right_ids.push_back(i);\n        }\n        node->cut_type = 1;\n        node->cut_pos = best_pos;\n        node->left = build(x1, y1, best_pos, y2, left_ids);\n        node->right = build(best_pos, y1, x2, y2, right_ids);\n    } else {\n        vector<int> bottom_ids, top_ids;\n        for (int i : ids) {\n            if (comps[i].y < best_pos) bottom_ids.push_back(i);\n            else top_ids.push_back(i);\n        }\n        node->cut_type = 2;\n        node->cut_pos = best_pos;\n        node->left = build(x1, y1, x2, best_pos, bottom_ids);\n        node->right = build(x1, best_pos, x2, y2, top_ids);\n    }\n\n    return node;\n}\n\ndouble compute_score(Node* node) {\n    if (node->cut_type == 0) {\n        int i = node->ids[0];\n        ll area = (ll)(node->x2 - node->x1) * (node->y2 - node->y1);\n        ll ri = comps[i].r;\n        double ratio = min(area, ri) / (double)max(area, ri);\n        return 1.0 - (1.0 - ratio) * (1.0 - ratio);\n    }\n    return compute_score(node->left) + compute_score(node->right);\n}\n\nvoid collect(Node* node) {\n    if (node->cut_type == 0) {\n        int i = node->ids[0];\n        a[i] = node->x1;\n        b[i] = node->y1;\n        c[i] = node->x2;\n        d[i] = node->y2;\n        return;\n    }\n    collect(node->left);\n    collect(node->right);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n;\n    comps.resize(n);\n    for (int i = 0; i < n; ++i)\n        cin >> comps[i].x >> comps[i].y >> comps[i].r;\n\n    a.resize(n); b.resize(n); c.resize(n); d.resize(n);\n\n    vector<int> ids(n);\n    iota(ids.begin(), ids.end(), 0);\n    \n    vector<vector<int>> orderings;\n    \n    // Original order\n    orderings.push_back(ids);\n    \n    // Three random shuffles\n    for (int i = 0; i < 3; ++i) {\n        vector<int> shuffled = ids;\n        shuffle(shuffled.begin(), shuffled.end(), mt19937(random_device{}()));\n        orderings.push_back(shuffled);\n    }\n    \n    // Sort by x\n    vector<int> by_x = ids;\n    sort(by_x.begin(), by_x.end(), [&](int i, int j) {\n        return comps[i].x < comps[j].x;\n    });\n    orderings.push_back(by_x);\n    \n    // Sort by y\n    vector<int> by_y = ids;\n    sort(by_y.begin(), by_y.end(), [&](int i, int j) {\n        return comps[i].y < comps[j].y;\n    });\n    orderings.push_back(by_y);\n    \n    // Sort by r\n    vector<int> by_r = ids;\n    sort(by_r.begin(), by_r.end(), [&](int i, int j) {\n        return comps[i].r < comps[j].r;\n    });\n    orderings.push_back(by_r);\n    \n    // Sort by x+y\n    vector<int> by_sum = ids;\n    sort(by_sum.begin(), by_sum.end(), [&](int i, int j) {\n        return comps[i].x + comps[i].y < comps[j].x + comps[j].y;\n    });\n    orderings.push_back(by_sum);\n    \n    Node* best_root = nullptr;\n    double best_score = -1.0;\n    \n    for (auto& order : orderings) {\n        Node* root = build(0, 0, 10000, 10000, order);\n        double score = compute_score(root);\n        \n        if (score > best_score) {\n            best_score = score;\n            best_root = root;\n        }\n    }\n\n    collect(best_root);\n\n    for (int i = 0; i < n; ++i)\n        cout << a[i] << ' ' << b[i] << ' ' << c[i] << ' ' << d[i] << '\\n';\n\n    return 0;\n}","ahc002":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <cassert>\n#include <tuple>\n#include <set>\n\nusing namespace std;\n\nconst int N = 50;\nconst int dr[4] = {-1, 1, 0, 0};\nconst int dc[4] = {0, 0, -1, 1};\nconst char dir_char[4] = {'U', 'D', 'L', 'R'};\n\nstruct Neighbor {\n    int r, c;\n    char dir;\n};\n\n// Get valid neighbors from (r,c) given visited tiles.\nvector<Neighbor> get_neighbors(int r, int c, const vector<char>& visited,\n                               const vector<vector<int>>& tile_id) {\n    vector<Neighbor> res;\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) {\n            int tile = tile_id[nr][nc];\n            if (!visited[tile]) {\n                res.push_back({nr, nc, dir_char[d]});\n            }\n        }\n    }\n    return res;\n}\n\n// Count unvisited neighbors for a tile\nint count_unvisited_neighbors(const pair<int,int>& square,\n                              const vector<char>& visited,\n                              const vector<vector<int>>& tile_id) {\n    int count = 0;\n    set<int> neighboring_tiles;\n    for (int d = 0; d < 4; ++d) {\n        int nr = square.first + dr[d], nc = square.second + dc[d];\n        if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n            int tile = tile_id[nr][nc];\n            if (!visited[tile] && neighboring_tiles.find(tile) == neighboring_tiles.end()) {\n                count++;\n                neighboring_tiles.insert(tile);\n            }\n        }\n    }\n    return count;\n}\n\n// Heuristic score for a square with adjustable connectivity weight\ndouble heuristic_score(int r, int c, const vector<char>& visited,\n                      const vector<vector<int>>& p,\n                      const vector<vector<int>>& tile_id,\n                      double conn_weight = 2.0) {\n    double score = p[r][c];\n    int conn = count_unvisited_neighbors({r, c}, visited, tile_id);\n    score += conn_weight * conn;\n    return score;\n}\n\n// Greedy extension with heuristic\nvoid extend_greedy(vector<pair<int,int>>& path, vector<int>& tiles,\n                   vector<char>& visited, int& score,\n                   const vector<vector<int>>& p,\n                   const vector<vector<int>>& tile_id,\n                   mt19937& rng, int max_steps = 1000, double conn_weight = 2.0) {\n    int steps = 0;\n    while (steps < max_steps) {\n        if (path.empty()) break;\n        int r = path.back().first, c = path.back().second;\n        auto candidates = get_neighbors(r, c, visited, tile_id);\n        if (candidates.empty()) break;\n        \n        // Score each candidate using heuristic\n        vector<pair<double, int>> candidate_scores;\n        for (size_t i = 0; i < candidates.size(); ++i) {\n            const auto& cand = candidates[i];\n            double score_val = heuristic_score(cand.r, cand.c, visited, p, tile_id, conn_weight);\n            candidate_scores.emplace_back(score_val, i);\n        }\n        \n        // Choose with probability proportional to score\n        vector<double> weights;\n        for (const auto& cs : candidate_scores) {\n            weights.push_back(exp(cs.first / 20.0));\n        }\n        discrete_distribution<int> dist(weights.begin(), weights.end());\n        int idx = dist(rng);\n        \n        const auto& cand = candidates[idx];\n        path.push_back({cand.r, cand.c});\n        tiles.push_back(tile_id[cand.r][cand.c]);\n        visited[tile_id[cand.r][cand.c]] = 1;\n        score += p[cand.r][cand.c];\n        steps++;\n    }\n}\n\n// Try to reverse a segment of the path\nbool try_reverse_segment(vector<pair<int,int>>& path, vector<int>& tiles,\n                         vector<char>& visited, int& score,\n                         const vector<vector<int>>& p,\n                         const vector<vector<int>>& tile_id,\n                         mt19937& rng) {\n    if (path.size() < 4) return false;\n    \n    uniform_int_distribution<int> len_dist(2, min(15, (int)path.size() - 2));\n    int seg_len = len_dist(rng);\n    uniform_int_distribution<int> start_dist(1, (int)path.size() - seg_len - 1);\n    int start_idx = start_dist(rng);\n    \n    // Check if reversing this segment maintains validity\n    bool valid = true;\n    for (int i = 0; i < seg_len; ++i) {\n        int idx1 = start_idx + i;\n        int idx2 = start_idx + seg_len - 1 - i;\n        \n        // Check connections to neighbors (if not at ends)\n        if (idx1 > 0) {\n            const auto& prev = path[idx1 - 1];\n            if (abs(prev.first - path[idx2].first) + \n                abs(prev.second - path[idx2].second) != 1) {\n                valid = false;\n                break;\n            }\n        }\n        if (idx1 < (int)path.size() - 1) {\n            const auto& next = path[idx1 + 1];\n            if (abs(next.first - path[idx2].first) + \n                abs(next.second - path[idx2].second) != 1) {\n                valid = false;\n                break;\n            }\n        }\n    }\n    \n    if (!valid) return false;\n    \n    // Apply reversal\n    for (int i = 0; i < seg_len / 2; ++i) {\n        int idx1 = start_idx + i;\n        int idx2 = start_idx + seg_len - 1 - i;\n        swap(path[idx1], path[idx2]);\n        swap(tiles[idx1], tiles[idx2]);\n    }\n    \n    // Recalculate score\n    score = 0;\n    for (size_t i = 0; i < path.size(); ++i) {\n        score += p[path[i].first][path[i].second];\n    }\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Read input.\n    int si, sj;\n    cin >> si >> sj;\n    vector<vector<int>> tile_id(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> tile_id[i][j];\n    vector<vector<int>> 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    // Determine number of tiles.\n    int M = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            M = max(M, tile_id[i][j] + 1);\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    // Generate multiple initial paths with different strategies\n    vector<pair<int,int>> best_path;\n    int best_score = -1;\n    \n    for (int trial = 0; trial < 6; ++trial) {\n        vector<pair<int,int>> cur_path;\n        vector<int> cur_tiles;\n        vector<char> cur_visited(M, 0);\n        int cur_score = 0;\n\n        cur_path.emplace_back(si, sj);\n        cur_tiles.push_back(tile_id[si][sj]);\n        cur_visited[tile_id[si][sj]] = 1;\n        cur_score += p[si][sj];\n        \n        if (trial == 0) {\n            // Balanced heuristic (weight 2.0)\n            extend_greedy(cur_path, cur_tiles, cur_visited, cur_score, p, tile_id, rng, 1000, 2.0);\n        } else if (trial == 1) {\n            // Random walk for some steps, then greedy\n            uniform_int_distribution<int> walk_dist(40, 120);\n            int walk_length = walk_dist(rng);\n            for (int step = 0; step < walk_length; ++step) {\n                auto candidates = get_neighbors(cur_path.back().first, cur_path.back().second,\n                                               cur_visited, tile_id);\n                if (candidates.empty()) break;\n                \n                uniform_int_distribution<int> cand_dist(0, candidates.size() - 1);\n                int idx = cand_dist(rng);\n                const auto& cand = candidates[idx];\n                cur_path.push_back({cand.r, cand.c});\n                cur_tiles.push_back(tile_id[cand.r][cand.c]);\n                cur_visited[tile_id[cand.r][cand.c]] = 1;\n                cur_score += p[cand.r][cand.c];\n            }\n            // Then extend greedily with balanced heuristic\n            extend_greedy(cur_path, cur_tiles, cur_visited, cur_score, p, tile_id, rng, 1000, 2.0);\n        } else if (trial == 2) {\n            // High connectivity heuristic (weight 3.0)\n            extend_greedy(cur_path, cur_tiles, cur_visited, cur_score, p, tile_id, rng, 1000, 3.0);\n        } else if (trial == 3) {\n            // Value-first with connectivity consideration\n            while (true) {\n                auto candidates = get_neighbors(cur_path.back().first, cur_path.back().second,\n                                               cur_visited, tile_id);\n                if (candidates.empty()) break;\n                \n                // Choose candidate with best heuristic score (weight 2.5)\n                vector<pair<double, int>> cand_scores;\n                for (size_t i = 0; i < candidates.size(); ++i) {\n                    const auto& cand = candidates[i];\n                    double score_val = heuristic_score(cand.r, cand.c, cur_visited, p, tile_id, 2.5);\n                    cand_scores.emplace_back(score_val, i);\n                }\n                sort(cand_scores.begin(), cand_scores.end(), greater<pair<double, int>>());\n                int idx = cand_scores[0].second;\n                const auto& cand = candidates[idx];\n                cur_path.push_back({cand.r, cand.c});\n                cur_tiles.push_back(tile_id[cand.r][cand.c]);\n                cur_visited[tile_id[cand.r][cand.c]] = 1;\n                cur_score += p[cand.r][cand.c];\n            }\n        } else if (trial == 4) {\n            // Pure value-first (no connectivity weight)\n            while (true) {\n                auto candidates = get_neighbors(cur_path.back().first, cur_path.back().second,\n                                               cur_visited, tile_id);\n                if (candidates.empty()) break;\n                \n                // Choose candidate with highest p\n                auto best_it = max_element(candidates.begin(), candidates.end(),\n                                          [&](const Neighbor& a, const Neighbor& b) {\n                                              return p[a.r][a.c] < p[b.r][b.c];\n                                          });\n                const auto& cand = *best_it;\n                cur_path.push_back({cand.r, cand.c});\n                cur_tiles.push_back(tile_id[cand.r][cand.c]);\n                cur_visited[tile_id[cand.r][cand.c]] = 1;\n                cur_score += p[cand.r][cand.c];\n            }\n        } else {\n            // Connectivity-first (maximize unvisited neighbors)\n            while (true) {\n                auto candidates = get_neighbors(cur_path.back().first, cur_path.back().second,\n                                               cur_visited, tile_id);\n                if (candidates.empty()) break;\n                \n                // Choose candidate with most unvisited neighbors\n                vector<pair<int, int>> conn_scores;\n                for (size_t i = 0; i < candidates.size(); ++i) {\n                    const auto& cand = candidates[i];\n                    int conn = count_unvisited_neighbors({cand.r, cand.c}, cur_visited, tile_id);\n                    conn_scores.emplace_back(conn, i);\n                }\n                sort(conn_scores.begin(), conn_scores.end(), greater<pair<int, int>>());\n                int idx = conn_scores[0].second;\n                const auto& cand = candidates[idx];\n                cur_path.push_back({cand.r, cand.c});\n                cur_tiles.push_back(tile_id[cand.r][cand.c]);\n                cur_visited[tile_id[cand.r][cand.c]] = 1;\n                cur_score += p[cand.r][cand.c];\n            }\n        }\n        \n        if (cur_score > best_score) {\n            best_score = cur_score;\n            best_path = cur_path;\n        }\n    }\n\n    vector<pair<int,int>> cur_path = best_path;\n    vector<int> cur_tiles;\n    vector<char> cur_visited(M, 0);\n    int cur_score = 0;\n    \n    // Rebuild tiles and visited from path\n    for (const auto& sq : cur_path) {\n        cur_tiles.push_back(tile_id[sq.first][sq.second]);\n        cur_visited[tile_id[sq.first][sq.second]] = 1;\n        cur_score += p[sq.first][sq.second];\n    }\n\n    vector<pair<int,int>> best_path_final = cur_path;\n    int best_score_final = cur_score;\n\n    // Simulated annealing parameters\n    const int ITER = 300000;\n    const double T_start = 350.0;\n    const double T_min = 1e-3;\n    double T = T_start;\n    double cooling_rate = pow(T_min / T_start, 1.0 / ITER);\n    \n    uniform_real_distribution<double> real_dist(0.0, 1.0);\n    auto start_time = chrono::steady_clock::now();\n    const chrono::milliseconds time_limit(1900); // 1.9 seconds\n    \n    int restart_count = 0;\n    const int RESTART_THRESHOLD = 20000;\n    int iterations_without_improvement = 0;\n\n    for (int iter = 0; iter < ITER; ++iter) {\n        // Time check\n        if (iter % 1000 == 0) {\n            auto now = chrono::steady_clock::now();\n            if (chrono::duration_cast<chrono::milliseconds>(now - start_time) > time_limit)\n                break;\n        }\n        \n        // Temperature restart if stuck\n        if (iterations_without_improvement > RESTART_THRESHOLD && restart_count < 5) {\n            cur_path = best_path_final;\n            cur_tiles.clear();\n            cur_visited.assign(M, 0);\n            cur_score = 0;\n            for (const auto& sq : cur_path) {\n                cur_tiles.push_back(tile_id[sq.first][sq.second]);\n                cur_visited[tile_id[sq.first][sq.second]] = 1;\n                cur_score += p[sq.first][sq.second];\n            }\n            T = T_start * pow(0.6, restart_count);\n            restart_count++;\n            iterations_without_improvement = 0;\n            continue;\n        }\n\n        // Copy current state\n        vector<pair<int,int>> new_path = cur_path;\n        vector<int> new_tiles = cur_tiles;\n        vector<char> new_visited = cur_visited;\n        int new_score = cur_score;\n\n        double op = real_dist(rng);\n        if (op < 0.25) {\n            // Extend: add one move at the end\n            if (!new_path.empty()) {\n                int r = new_path.back().first, c = new_path.back().second;\n                auto candidates = get_neighbors(r, c, new_visited, tile_id);\n                if (!candidates.empty()) {\n                    // Choose candidate with best heuristic score (weight 2.0)\n                    vector<pair<double, int>> cand_scores;\n                    for (size_t i = 0; i < candidates.size(); ++i) {\n                        const auto& cand = candidates[i];\n                        double score_val = heuristic_score(cand.r, cand.c, new_visited, p, tile_id, 2.0);\n                        cand_scores.emplace_back(score_val, i);\n                    }\n                    sort(cand_scores.begin(), cand_scores.end(), greater<pair<double, int>>());\n                    // With some probability choose best, otherwise random\n                    uniform_int_distribution<int> pick_dist(0, min(2, (int)cand_scores.size() - 1));\n                    int pick_idx = pick_dist(rng);\n                    int cand_idx = cand_scores[pick_idx].second;\n                    \n                    auto& cand = candidates[cand_idx];\n                    new_path.push_back({cand.r, cand.c});\n                    new_tiles.push_back(tile_id[cand.r][cand.c]);\n                    new_visited[tile_id[cand.r][cand.c]] = 1;\n                    new_score += p[cand.r][cand.c];\n                }\n            }\n        } else if (op < 0.4) {\n            // Shrink: remove last move\n            if (new_path.size() > 1) {\n                auto last = new_path.back();\n                int tile = new_tiles.back();\n                new_path.pop_back();\n                new_tiles.pop_back();\n                new_visited[tile] = 0;\n                new_score -= p[last.first][last.second];\n            }\n        } else if (op < 0.7) {\n            // Modify: truncate at random index, change next move with heuristic, then extend\n            if (new_path.size() <= 1) {\n                // Fallback to extend\n                if (!new_path.empty()) {\n                    int r = new_path.back().first, c = new_path.back().second;\n                    auto candidates = get_neighbors(r, c, new_visited, tile_id);\n                    if (!candidates.empty()) {\n                        uniform_int_distribution<int> dist(0, candidates.size() - 1);\n                        int idx = dist(rng);\n                        auto& cand = candidates[idx];\n                        new_path.push_back({cand.r, cand.c});\n                        new_tiles.push_back(tile_id[cand.r][cand.c]);\n                        new_visited[tile_id[cand.r][cand.c]] = 1;\n                        new_score += p[cand.r][cand.c];\n                    }\n                }\n            } else {\n                int L = new_path.size();\n                uniform_int_distribution<int> idx_dist(1, L - 1);\n                int k = idx_dist(rng);\n                \n                // Remove squares from index k onward\n                for (int i = k; i < L; ++i) {\n                    int tile = new_tiles[i];\n                    new_visited[tile] = 0;\n                    new_score -= p[new_path[i].first][new_path[i].second];\n                }\n                new_path.resize(k);\n                new_tiles.resize(k);\n                \n                // Choose a new move from the square at index k-1 using heuristic\n                int r_prev = new_path.back().first, c_prev = new_path.back().second;\n                auto candidates = get_neighbors(r_prev, c_prev, new_visited, tile_id);\n                if (!candidates.empty()) {\n                    // Evaluate candidates with heuristic (weight 2.5)\n                    vector<pair<double, int>> cand_scores;\n                    for (size_t i = 0; i < candidates.size(); ++i) {\n                        const auto& cand = candidates[i];\n                        double score_val = heuristic_score(cand.r, cand.c, new_visited, p, tile_id, 2.5);\n                        cand_scores.emplace_back(score_val, i);\n                    }\n                    sort(cand_scores.begin(), cand_scores.end(), greater<pair<double, int>>());\n                    \n                    // Choose among top candidates with some randomness\n                    uniform_int_distribution<int> pick_dist(0, min(2, (int)cand_scores.size() - 1));\n                    int pick_idx = pick_dist(rng);\n                    int cand_idx = cand_scores[pick_idx].second;\n                    \n                    auto& cand = candidates[cand_idx];\n                    new_path.push_back({cand.r, cand.c});\n                    new_tiles.push_back(tile_id[cand.r][cand.c]);\n                    new_visited[tile_id[cand.r][cand.c]] = 1;\n                    new_score += p[cand.r][cand.c];\n                    \n                    // Extend with heuristic (weight 2.0) - longer extension\n                    extend_greedy(new_path, new_tiles, new_visited, new_score, p, tile_id, rng, 200, 2.0);\n                }\n            }\n        } else {\n            // Try to reverse a segment\n            if (try_reverse_segment(new_path, new_tiles, new_visited, new_score, p, tile_id, rng)) {\n                // Success\n            } else {\n                // If reversal fails, do a simple extend\n                if (!new_path.empty()) {\n                    int r = new_path.back().first, c = new_path.back().second;\n                    auto candidates = get_neighbors(r, c, new_visited, tile_id);\n                    if (!candidates.empty()) {\n                        uniform_int_distribution<int> dist(0, candidates.size() - 1);\n                        int idx = dist(rng);\n                        auto& cand = candidates[idx];\n                        new_path.push_back({cand.r, cand.c});\n                        new_tiles.push_back(tile_id[cand.r][cand.c]);\n                        new_visited[tile_id[cand.r][cand.c]] = 1;\n                        new_score += p[cand.r][cand.c];\n                    }\n                }\n            }\n        }\n\n        // Metropolis criterion\n        int delta = new_score - cur_score;\n        bool accept = false;\n        if (delta > 0) {\n            accept = true;\n        } else {\n            double prob = exp(delta / T);\n            if (real_dist(rng) < prob) accept = true;\n        }\n\n        if (accept) {\n            cur_path = std::move(new_path);\n            cur_tiles = std::move(new_tiles);\n            cur_visited = std::move(new_visited);\n            cur_score = new_score;\n            if (cur_score > best_score_final) {\n                best_score_final = cur_score;\n                best_path_final = cur_path;\n                iterations_without_improvement = 0;\n            } else {\n                iterations_without_improvement++;\n            }\n        } else {\n            iterations_without_improvement++;\n        }\n\n        // Cooling\n        T *= cooling_rate;\n    }\n\n    // Simple post-optimization: extend from the end\n    vector<pair<int,int>> final_path = best_path_final;\n    vector<int> final_tiles;\n    vector<char> final_visited(M, 0);\n    for (const auto& sq : final_path) {\n        final_tiles.push_back(tile_id[sq.first][sq.second]);\n        final_visited[tile_id[sq.first][sq.second]] = 1;\n    }\n    int final_score = best_score_final;\n    \n    // Try extending from the end with different heuristics\n    extend_greedy(final_path, final_tiles, final_visited, final_score, p, tile_id, rng, 600, 2.0);\n    extend_greedy(final_path, final_tiles, final_visited, final_score, p, tile_id, rng, 400, 3.0);\n    \n    if (final_score > best_score_final) {\n        best_score_final = final_score;\n        best_path_final = final_path;\n    }\n\n    // Convert best_path to move string\n    string moves;\n    for (size_t i = 1; i < best_path_final.size(); ++i) {\n        int dr = best_path_final[i].first - best_path_final[i-1].first;\n        int dc = best_path_final[i].second - best_path_final[i-1].second;\n        if (dr == -1 && dc == 0) moves += 'U';\n        else if (dr == 1 && dc == 0) moves += 'D';\n        else if (dr == 0 && dc == -1) moves += 'L';\n        else if (dr == 0 && dc == 1) moves += 'R';\n        else assert(false);\n    }\n\n    cout << moves << endl;\n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <string>\n\nusing namespace std;\n\nconst int N = 30;\n\ndouble h_est[N][N-1];\ndouble v_est[N-1][N];\nint h_count[N][N-1] = {0};\nint v_count[N-1][N] = {0};\n\nstruct Node {\n    int i, j;\n    bool operator==(const Node& other) const { return i == other.i && j == other.j; }\n    bool operator!=(const Node& other) const { return !(*this == other); }\n};\n\nusing PQElement = pair<double, Node>;\n\nstruct Compare {\n    bool operator()(const PQElement& a, const PQElement& b) const {\n        return a.first > b.first;\n    }\n};\n\ndouble getEdgeEstimate(int i, int j, int ni, int nj) {\n    if (i == ni) {\n        if (nj == j+1) return h_est[i][j];\n        else if (nj == j-1) return h_est[i][j-1];\n    } else if (j == nj) {\n        if (ni == i+1) return v_est[i][j];\n        else if (ni == i-1) return v_est[i-1][j];\n    }\n    return 0.0;\n}\n\nvoid updateEdge(int i, int j, int ni, int nj, double factor, double global_lr) {\n    if (i == ni) {\n        if (nj == j+1) {\n            h_count[i][j]++;\n            double lr = global_lr / (1.0 + sqrt(h_count[i][j]));\n            h_est[i][j] *= (1.0 + lr * (factor - 1.0));\n            if (h_est[i][j] < 1000.0) h_est[i][j] = 1000.0;\n            if (h_est[i][j] > 9000.0) h_est[i][j] = 9000.0;\n            \n            // Row regularization: pull toward row average (1% weight)\n            double sum = 0.0;\n            for (int jj = 0; jj < N-1; ++jj) sum += h_est[i][jj];\n            double avg = sum / (N-1);\n            h_est[i][j] = 0.99 * h_est[i][j] + 0.01 * avg;\n            \n        } else if (nj == j-1) {\n            h_count[i][j-1]++;\n            double lr = global_lr / (1.0 + sqrt(h_count[i][j-1]));\n            h_est[i][j-1] *= (1.0 + lr * (factor - 1.0));\n            if (h_est[i][j-1] < 1000.0) h_est[i][j-1] = 1000.0;\n            if (h_est[i][j-1] > 9000.0) h_est[i][j-1] = 9000.0;\n            \n            // Row regularization\n            double sum = 0.0;\n            for (int jj = 0; jj < N-1; ++jj) sum += h_est[i][jj];\n            double avg = sum / (N-1);\n            h_est[i][j-1] = 0.99 * h_est[i][j-1] + 0.01 * avg;\n        }\n    } else if (j == nj) {\n        if (ni == i+1) {\n            v_count[i][j]++;\n            double lr = global_lr / (1.0 + sqrt(v_count[i][j]));\n            v_est[i][j] *= (1.0 + lr * (factor - 1.0));\n            if (v_est[i][j] < 1000.0) v_est[i][j] = 1000.0;\n            if (v_est[i][j] > 9000.0) v_est[i][j] = 9000.0;\n            \n            // Column regularization: pull toward column average (1% weight)\n            double sum = 0.0;\n            for (int ii = 0; ii < N-1; ++ii) sum += v_est[ii][j];\n            double avg = sum / (N-1);\n            v_est[i][j] = 0.99 * v_est[i][j] + 0.01 * avg;\n            \n        } else if (ni == i-1) {\n            v_count[i-1][j]++;\n            double lr = global_lr / (1.0 + sqrt(v_count[i-1][j]));\n            v_est[i-1][j] *= (1.0 + lr * (factor - 1.0));\n            if (v_est[i-1][j] < 1000.0) v_est[i-1][j] = 1000.0;\n            if (v_est[i-1][j] > 9000.0) v_est[i-1][j] = 9000.0;\n            \n            // Column regularization\n            double sum = 0.0;\n            for (int ii = 0; ii < N-1; ++ii) sum += v_est[ii][j];\n            double avg = sum / (N-1);\n            v_est[i-1][j] = 0.99 * v_est[i-1][j] + 0.01 * avg;\n        }\n    }\n}\n\nvoid updateEstimates(const vector<Node>& path, int obs, int k) {\n    int path_length = path.size() - 1;\n    if (path_length == 0) return;\n    \n    double pred = 0.0;\n    for (int idx = 0; idx < path_length; idx++) {\n        auto& from = path[idx];\n        auto& to = path[idx+1];\n        pred += getEdgeEstimate(from.i, from.j, to.i, to.j);\n    }\n    \n    double factor = obs / pred;\n    // Even slower decay for longer learning\n    double global_lr = 0.5 * pow(0.9998, k);\n    \n    for (int idx = 0; idx < path_length; idx++) {\n        auto& from = path[idx];\n        auto& to = path[idx+1];\n        updateEdge(from.i, from.j, to.i, to.j, factor, global_lr);\n    }\n}\n\npair<string, vector<Node>> computePath(int si, int sj, int ti, int tj) {\n    // Early termination if start equals target\n    if (si == ti && sj == tj) {\n        return {\"\", {{si, sj}}};\n    }\n    \n    vector<vector<double>> dist(N, vector<double>(N, 1e18));\n    vector<vector<Node>> prev(N, vector<Node>(N, {-1,-1}));\n    dist[si][sj] = 0.0;\n    priority_queue<PQElement, vector<PQElement>, Compare> pq;\n    pq.push({0.0, {si, sj}});\n    \n    while (!pq.empty()) {\n        auto [d, node] = pq.top(); pq.pop();\n        if (d > dist[node.i][node.j]) continue;\n        if (node.i == ti && node.j == tj) break;\n        \n        // right\n        if (node.j+1 < N) {\n            double w = h_est[node.i][node.j];\n            if (dist[node.i][node.j] + w < dist[node.i][node.j+1]) {\n                dist[node.i][node.j+1] = dist[node.i][node.j] + w;\n                prev[node.i][node.j+1] = {node.i, node.j};\n                pq.push({dist[node.i][node.j+1], {node.i, node.j+1}});\n            }\n        }\n        // left\n        if (node.j-1 >= 0) {\n            double w = h_est[node.i][node.j-1];\n            if (dist[node.i][node.j] + w < dist[node.i][node.j-1]) {\n                dist[node.i][node.j-1] = dist[node.i][node.j] + w;\n                prev[node.i][node.j-1] = {node.i, node.j};\n                pq.push({dist[node.i][node.j-1], {node.i, node.j-1}});\n            }\n        }\n        // down\n        if (node.i+1 < N) {\n            double w = v_est[node.i][node.j];\n            if (dist[node.i][node.j] + w < dist[node.i+1][node.j]) {\n                dist[node.i+1][node.j] = dist[node.i][node.j] + w;\n                prev[node.i+1][node.j] = {node.i, node.j};\n                pq.push({dist[node.i+1][node.j], {node.i+1, node.j}});\n            }\n        }\n        // up\n        if (node.i-1 >= 0) {\n            double w = v_est[node.i-1][node.j];\n            if (dist[node.i][node.j] + w < dist[node.i-1][node.j]) {\n                dist[node.i-1][node.j] = dist[node.i][node.j] + w;\n                prev[node.i-1][node.j] = {node.i, node.j};\n                pq.push({dist[node.i-1][node.j], {node.i-1, node.j}});\n            }\n        }\n    }\n    \n    // reconstruct path\n    vector<Node> path_nodes;\n    Node cur = {ti, tj};\n    while (cur.i != si || cur.j != sj) {\n        path_nodes.push_back(cur);\n        cur = prev[cur.i][cur.j];\n    }\n    path_nodes.push_back({si, sj});\n    reverse(path_nodes.begin(), path_nodes.end());\n    \n    // convert to string\n    string path_str;\n    for (size_t idx = 0; idx < path_nodes.size()-1; idx++) {\n        auto& from = path_nodes[idx];\n        auto& to = path_nodes[idx+1];\n        if (to.i == from.i && to.j == from.j+1) path_str += 'R';\n        else if (to.i == from.i && to.j == from.j-1) path_str += 'L';\n        else if (to.i == from.i+1 && to.j == from.j) path_str += 'D';\n        else if (to.i == from.i-1 && to.j == from.j) path_str += 'U';\n    }\n    return {path_str, path_nodes};\n}\n\nint main() {\n    // Initialize estimates to midpoint of range\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N-1; ++j)\n            h_est[i][j] = 5000.0;\n    for (int i = 0; i < N-1; ++i)\n        for (int j = 0; j < N; ++j)\n            v_est[i][j] = 5000.0;\n\n    for (int k = 0; k < 1000; ++k) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n        \n        auto [path_str, path_nodes] = computePath(si, sj, ti, tj);\n        \n        cout << path_str << endl;\n        cout.flush();\n        \n        int obs;\n        cin >> obs;\n        \n        updateEstimates(path_nodes, obs, k);\n    }\n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <cmath>\n#include <numeric>\n#include <chrono>\n#include <cassert>\n#include <unordered_map>\n\nusing namespace std;\n\nint N = 20;\nconst int ALPHABET = 8;\nconst char ALPHABET_CHARS[] = \"ABCDEFGH\";\n\nstruct Placement {\n    int str_idx;\n    int row, col;\n    int dir;\n    int len;\n};\n\nvector<string> strings;\nvector<Placement> placements;\nvector<vector<int>> placements_by_str;\nvector<vector<pair<int, char>>> cell_lists;\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\nvoid generate_placements() {\n    int M = strings.size();\n    placements_by_str.resize(M);\n    placements.clear();\n    placements.reserve(M * 800);\n    \n    for (int s = 0; s < M; ++s) {\n        int len = strings[s].size();\n        for (int dir = 0; dir < 2; ++dir) {\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    placements.push_back({s, r, c, dir, len});\n                    placements_by_str[s].push_back(placements.size() - 1);\n                }\n            }\n        }\n    }\n}\n\nvoid build_cell_lists() {\n    cell_lists.assign(N * N, {});\n    for (int pid = 0; pid < (int)placements.size(); ++pid) {\n        const Placement& p = placements[pid];\n        for (int off = 0; off < p.len; ++off) {\n            int r, c;\n            if (p.dir == 0) {\n                r = p.row;\n                c = (p.col + off) % N;\n            } else {\n                r = (p.row + off) % N;\n                c = p.col;\n            }\n            int cell = r * N + c;\n            char req = strings[p.str_idx][off];\n            cell_lists[cell].emplace_back(pid, req);\n        }\n    }\n}\n\nbool is_subsequence(const vector<vector<char>>& mat, const string& s) {\n    int len = s.size();\n    // Optimized check with early termination\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            bool ok = true;\n            for (int p = 0; p < len; ++p) {\n                if (mat[i][(j + p) % N] != s[p]) {\n                    ok = false;\n                    break;\n                }\n            }\n            if (ok) return true;\n        }\n    }\n    for (int j = 0; j < N; ++j) {\n        for (int i = 0; i < N; ++i) {\n            bool ok = true;\n            for (int p = 0; p < len; ++p) {\n                if (mat[(i + p) % N][j] != s[p]) {\n                    ok = false;\n                    break;\n                }\n            }\n            if (ok) return true;\n        }\n    }\n    return false;\n}\n\nint evaluate(const vector<vector<char>>& mat) {\n    int cnt = 0;\n    for (const string& s : strings) {\n        if (is_subsequence(mat, s)) ++cnt;\n    }\n    return cnt;\n}\n\n// Enhanced greedy with better ordering\nvector<vector<char>> greedy(int seed) {\n    mt19937 gen(seed);\n    vector<vector<char>> mat(N, vector<char>(N, '.'));\n    int M = strings.size();\n    \n    // Order strings by length (longer first) and uniqueness\n    vector<pair<pair<int, int>, int>> order_with_info(M);\n    for (int i = 0; i < M; ++i) {\n        // Use negative length for descending order, and random tie-breaker\n        order_with_info[i] = {{-strings[i].size(), gen()}, i};\n    }\n    sort(order_with_info.begin(), order_with_info.end());\n    \n    vector<int> order(M);\n    for (int i = 0; i < M; ++i) order[i] = order_with_info[i].second;\n    \n    for (int idx : order) {\n        const string& s = strings[idx];\n        int len = s.size();\n        vector<int> plist = placements_by_str[idx];\n        shuffle(plist.begin(), plist.end(), gen);\n        \n        int attempts = min(100, (int)plist.size());\n        bool placed = false;\n        \n        for (int i = 0; i < attempts && !placed; ++i) {\n            int pid = plist[i];\n            const Placement& p = placements[pid];\n            \n            bool compatible = true;\n            for (int off = 0; off < len; ++off) {\n                int r, c;\n                if (p.dir == 0) {\n                    r = p.row;\n                    c = (p.col + off) % N;\n                } else {\n                    r = (p.row + off) % N;\n                    c = p.col;\n                }\n                if (mat[r][c] != '.' && mat[r][c] != s[off]) {\n                    compatible = false;\n                    break;\n                }\n            }\n            \n            if (compatible) {\n                for (int off = 0; off < len; ++off) {\n                    int r, c;\n                    if (p.dir == 0) {\n                        r = p.row;\n                        c = (p.col + off) % N;\n                    } else {\n                        r = (p.row + off) % N;\n                        c = p.col;\n                    }\n                    if (mat[r][c] == '.') {\n                        mat[r][c] = s[off];\n                    }\n                }\n                placed = true;\n            }\n        }\n    }\n    \n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (mat[i][j] == '.')\n                mat[i][j] = 'A';\n    \n    return mat;\n}\n\n// Advanced voting with string uniqueness weighting\nvector<vector<char>> build_by_voting_advanced() {\n    vector<vector<char>> mat(N, vector<char>(N, '.'));\n    \n    // Calculate string uniqueness (frequency of each string)\n    unordered_map<string, int> string_freq;\n    for (const auto& s : strings) {\n        string_freq[s]++;\n    }\n    \n    // Multiple passes with different weightings\n    for (int pass = 0; pass < 3; ++pass) {\n        vector<vector<vector<int>>> counts(N, vector<vector<int>>(N, vector<int>(ALPHABET, 0)));\n        \n        for (size_t pid = 0; pid < placements.size(); ++pid) {\n            const Placement& p = placements[pid];\n            double weight = 1.0;\n            \n            // Weight by string length\n            weight *= (1.0 + p.len * 0.1);\n            \n            // Weight by string uniqueness (less frequent = more weight)\n            double uniqueness = 1.0 / string_freq[strings[p.str_idx]];\n            weight *= (0.5 + uniqueness);\n            \n            for (int off = 0; off < p.len; ++off) {\n                int r, c;\n                if (p.dir == 0) {\n                    r = p.row;\n                    c = (p.col + off) % N;\n                } else {\n                    r = (p.row + off) % N;\n                    c = p.col;\n                }\n                char req = strings[p.str_idx][off];\n                int idx = req - 'A';\n                if (idx >= 0 && idx < ALPHABET) {\n                    counts[r][c][idx] += static_cast<int>(weight * 10);\n                }\n            }\n        }\n        \n        // Assign characters\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (mat[i][j] == '.') {\n                    int best_idx = 0;\n                    for (int k = 1; k < ALPHABET; ++k) {\n                        if (counts[i][j][k] > counts[i][j][best_idx]) {\n                            best_idx = k;\n                        }\n                    }\n                    mat[i][j] = ALPHABET_CHARS[best_idx];\n                }\n            }\n        }\n    }\n    \n    return mat;\n}\n\n// Adaptive simulated annealing\nvector<vector<char>> simulated_annealing(vector<vector<char>> mat, int max_iter = 25000) {\n    int M = strings.size();\n    int P = placements.size();\n    \n    vector<int> placement_match_count(P, 0);\n    vector<int> string_sat_count(M, 0);\n    int global_c = 0;\n    \n    for (int pid = 0; pid < P; ++pid) {\n        const Placement& p = placements[pid];\n        int cnt = 0;\n        for (int off = 0; off < p.len; ++off) {\n            int r, c;\n            if (p.dir == 0) {\n                r = p.row;\n                c = (p.col + off) % N;\n            } else {\n                r = (p.row + off) % N;\n                c = p.col;\n            }\n            if (mat[r][c] == strings[p.str_idx][off]) ++cnt;\n        }\n        placement_match_count[pid] = cnt;\n        if (cnt == p.len) {\n            ++string_sat_count[p.str_idx];\n        }\n    }\n    \n    for (int s = 0; s < M; ++s)\n        if (string_sat_count[s] > 0) ++global_c;\n    \n    double T = 10.0;\n    double cooling = pow(0.001 / T, 1.0 / max_iter);\n    uniform_int_distribution<int> cell_dist(0, N*N - 1);\n    uniform_int_distribution<int> char_dist(0, ALPHABET - 1);\n    uniform_real_distribution<double> prob_dist(0.0, 1.0);\n    \n    for (int iter = 0; iter < max_iter; ++iter) {\n        int cell = cell_dist(rng);\n        char old_char = mat[cell / N][cell % N];\n        char new_char = ALPHABET_CHARS[char_dist(rng)];\n        if (new_char == old_char) continue;\n        \n        int delta_c = 0;\n        vector<pair<int, int>> changed_placements;\n        vector<pair<int, int>> changed_strings;\n        \n        for (const auto& [pid, req] : cell_lists[cell]) {\n            int cur_cnt = placement_match_count[pid];\n            int new_cnt = cur_cnt;\n            if (old_char == req) --new_cnt;\n            if (new_char == req) ++new_cnt;\n            if (new_cnt == cur_cnt) continue;\n            \n            int len = placements[pid].len;\n            bool was_sat = (cur_cnt == len);\n            bool now_sat = (new_cnt == len);\n            \n            changed_placements.emplace_back(pid, cur_cnt);\n            placement_match_count[pid] = new_cnt;\n            \n            if (was_sat != now_sat) {\n                int str_idx = placements[pid].str_idx;\n                int delta = now_sat ? 1 : -1;\n                changed_strings.emplace_back(str_idx, delta);\n                string_sat_count[str_idx] += delta;\n                if (delta == 1 && string_sat_count[str_idx] == 1) ++delta_c;\n                if (delta == -1 && string_sat_count[str_idx] == 0) --delta_c;\n            }\n        }\n        \n        bool accept = false;\n        if (delta_c >= 0) {\n            accept = true;\n        } else {\n            double prob = exp(delta_c / T);\n            if (prob_dist(rng) < prob) accept = true;\n        }\n        \n        if (accept) {\n            mat[cell / N][cell % N] = new_char;\n            global_c += delta_c;\n            if (global_c == M) break;\n        } else {\n            for (auto& [pid, old_cnt] : changed_placements) {\n                placement_match_count[pid] = old_cnt;\n            }\n            for (auto& [str_idx, delta] : changed_strings) {\n                string_sat_count[str_idx] -= delta;\n            }\n        }\n        \n        T *= cooling;\n    }\n    \n    return mat;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int M;\n    cin >> N >> M;\n    strings.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> strings[i];\n    }\n    \n    generate_placements();\n    build_cell_lists();\n    \n    // Strategy 1: Multiple greedy attempts (increased to 5)\n    vector<vector<char>> best_mat;\n    int best_c = -1;\n    const int GREEDY_TRIES = 5;\n    \n    for (int t = 0; t < GREEDY_TRIES; ++t) {\n        auto mat = greedy(rng());\n        int c = evaluate(mat);\n        if (c > best_c) {\n            best_c = c;\n            best_mat = mat;\n        }\n        if (best_c == M) break;\n    }\n    \n    // Strategy 2: Advanced voting with uniqueness weighting\n    if (best_c < M) {\n        auto mat = build_by_voting_advanced();\n        int c = evaluate(mat);\n        if (c > best_c) {\n            best_c = c;\n            best_mat = mat;\n        }\n    }\n    \n    // Strategy 3: Multiple voting with randomization (increased to 3 trials)\n    if (best_c < M) {\n        for (int trial = 0; trial < 3; ++trial) {\n            auto mat = build_by_voting_advanced();\n            uniform_int_distribution<int> cell_dist(0, N*N - 1);\n            uniform_int_distribution<int> char_dist(0, ALPHABET - 1);\n            \n            // Add controlled randomization (more changes for later trials)\n            int changes = 20 + trial * 5;\n            for (int i = 0; i < changes; ++i) {\n                int cell = cell_dist(rng);\n                mat[cell / N][cell % N] = ALPHABET_CHARS[char_dist(rng)];\n            }\n            \n            int c = evaluate(mat);\n            if (c > best_c) {\n                best_c = c;\n                best_mat = mat;\n            }\n            if (best_c == M) break;\n        }\n    }\n    \n    // Strategy 4: SA with adaptive iterations\n    if (best_c > 0 && best_c < M) {\n        int sa_iters = 25000;\n        // More iterations for very low scores\n        if (best_c < M * 0.05) sa_iters = 40000;\n        else if (best_c < M * 0.15) sa_iters = 35000;\n        best_mat = simulated_annealing(best_mat, sa_iters);\n        best_c = evaluate(best_mat);\n    }\n    \n    // Strategy 5: Fallback for zero-score cases\n    if (best_c == 0) {\n        // Try multiple fallback attempts with increasing aggression\n        for (int trial = 0; trial < 2; ++trial) {\n            auto mat = build_by_voting_advanced();\n            uniform_int_distribution<int> cell_dist(0, N*N - 1);\n            uniform_int_distribution<int> char_dist(0, ALPHABET - 1);\n            \n            // Heavy randomization (more for second trial)\n            int changes = 20 + trial * 10;\n            for (int i = 0; i < changes; ++i) {\n                int cell = cell_dist(rng);\n                mat[cell / N][cell % N] = ALPHABET_CHARS[char_dist(rng)];\n            }\n            \n            int sa_iters = 25000 + trial * 5000;\n            mat = simulated_annealing(mat, sa_iters);\n            int c = evaluate(mat);\n            if (c > best_c) {\n                best_c = c;\n                best_mat = mat;\n            }\n            if (best_c > 0) break;\n        }\n    }\n    \n    // Output\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << best_mat[i][j];\n        }\n        cout << '\\n';\n    }\n    \n    return 0;\n}","ahc005":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <utility>\n\nusing namespace std;\n\nconst int INF = 1e9;\nconst int dr[4] = {-1, 1, 0, 0};\nconst int dc[4] = {0, 0, -1, 1};\nconst char dir_char[4] = {'U', 'D', 'L', 'R'};\n\n// Function to run greedy algorithm and return points sequence and total cost\npair<vector<int>, int> run_greedy_points(int N, const vector<string>& grid, \n                                        const vector<vector<int>>& idx,\n                                        const vector<int>& row, const vector<int>& col, \n                                        const vector<int>& w, int V,\n                                        const vector<int>& seg_id, \n                                        const vector<vector<int>>& seg_nodes,\n                                        int seg_cnt, int start_idx, int start_seg) {\n    vector<bool> seg_visited(seg_cnt, false);\n    seg_visited[start_seg] = true;\n    int remaining = seg_cnt - 1;\n    vector<int> points; // sequence of visited points\n    points.push_back(start_idx);\n    int cur = start_idx;\n    int total_cost = 0;\n\n    // Dijkstra from a source, filling dist and pred\n    auto dijkstra = [&](int src, vector<int>& dist, vector<int>& pred) {\n        dist.assign(V, INF);\n        pred.assign(V, -1);\n        dist[src] = 0;\n        using P = pair<int, int>;\n        priority_queue<P, vector<P>, greater<P>> pq;\n        pq.emplace(0, src);\n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop();\n            if (d != dist[u]) continue;\n            int r = row[u], c = col[u];\n            for (int k = 0; k < 4; ++k) {\n                int nr = r + dr[k];\n                int nc = c + dc[k];\n                if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n                int v = idx[nr][nc];\n                if (v == -1) continue;\n                int nd = d + w[v];\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    pred[v] = u;\n                    pq.emplace(nd, v);\n                }\n            }\n        }\n    };\n\n    // main loop: visit all segments\n    while (remaining > 0) {\n        vector<int> dist(V), pred(V);\n        dijkstra(cur, dist, pred);\n\n        // find the closest unvisited segment and its closest square\n        int best_seg = -1, best_node = -1, best_dist = INF;\n        for (int s = 0; s < seg_cnt; ++s) {\n            if (seg_visited[s]) continue;\n            int min_d = INF, node = -1;\n            for (int v : seg_nodes[s]) {\n                if (dist[v] < min_d) {\n                    min_d = dist[v];\n                    node = v;\n                }\n            }\n            if (min_d < best_dist) {\n                best_dist = min_d;\n                best_seg = s;\n                best_node = node;\n            }\n        }\n\n        // reconstruct the path from cur to best_node\n        vector<int> path;\n        for (int v = best_node; v != cur; v = pred[v]) {\n            path.push_back(v);\n        }\n        path.push_back(cur);\n        reverse(path.begin(), path.end());   // now path[0] = cur, path[last] = best_node\n\n        // walk along the path, accumulate cost and mark segments\n        for (size_t i = 0; i + 1 < path.size(); ++i) {\n            int to = path[i+1];\n            total_cost += w[to];\n            int s = seg_id[to];\n            if (!seg_visited[s]) {\n                seg_visited[s] = true;\n                --remaining;\n                points.push_back(to); // record the point where we first visit the segment\n            }\n        }\n        cur = best_node;\n    }\n\n    // return to the start square\n    if (cur != start_idx) {\n        vector<int> dist(V), pred(V);\n        dijkstra(cur, dist, pred);\n        vector<int> path;\n        for (int v = start_idx; v != cur; v = pred[v]) {\n            path.push_back(v);\n        }\n        path.push_back(cur);\n        reverse(path.begin(), path.end());\n        for (size_t i = 0; i + 1 < path.size(); ++i) {\n            int to = path[i+1];\n            total_cost += w[to];\n        }\n    }\n    points.push_back(start_idx); // end at start\n\n    return {points, total_cost};\n}\n\n// Function to compute distance matrix between points\nvector<vector<int>> compute_distance_matrix(const vector<int>& points, \n                                           int N, const vector<string>& grid,\n                                           const vector<vector<int>>& idx,\n                                           const vector<int>& row, const vector<int>& col,\n                                           const vector<int>& w, int V) {\n    int M = points.size();\n    vector<vector<int>> dist_mat(M, vector<int>(M, INF));\n    \n    // Dijkstra from each point\n    for (int i = 0; i < M; ++i) {\n        int src = points[i];\n        vector<int> dist(V, INF);\n        vector<int> pred(V, -1);\n        dist[src] = 0;\n        using P = pair<int, int>;\n        priority_queue<P, vector<P>, greater<P>> pq;\n        pq.emplace(0, src);\n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop();\n            if (d != dist[u]) continue;\n            int r = row[u], c = col[u];\n            for (int k = 0; k < 4; ++k) {\n                int nr = r + dr[k];\n                int nc = c + dc[k];\n                if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n                int v = idx[nr][nc];\n                if (v == -1) continue;\n                int nd = d + w[v];\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    pred[v] = u;\n                    pq.emplace(nd, v);\n                }\n            }\n        }\n        // Fill distances to other points\n        for (int j = 0; j < M; ++j) {\n            dist_mat[i][j] = dist[points[j]];\n        }\n    }\n    return dist_mat;\n}\n\n// Function to apply 2-opt optimization on points sequence\npair<vector<int>, int> apply_2opt(const vector<int>& points, \n                                 const vector<vector<int>>& dist_mat) {\n    int M = points.size();\n    if (M <= 3) return {points, 0}; // nothing to optimize\n    \n    // We'll optimize the inner sequence (indices 1 to M-2)\n    vector<int> order(M-2); // indices of inner points\n    for (int i = 0; i < M-2; ++i) order[i] = i+1;\n    \n    // Compute initial total distance\n    auto total_dist = [&](const vector<int>& ord) {\n        int sum = dist_mat[0][ord[0]]; // start to first\n        for (size_t i = 0; i + 1 < ord.size(); ++i) {\n            sum += dist_mat[ord[i]][ord[i+1]];\n        }\n        sum += dist_mat[ord.back()][M-1]; // last to start\n        return sum;\n    };\n    \n    int best_total = total_dist(order);\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (size_t i = 0; i < order.size(); ++i) {\n            for (size_t j = i+1; j < order.size(); ++j) {\n                // reverse the segment between i and j\n                vector<int> new_order = order;\n                reverse(new_order.begin() + i, new_order.begin() + j + 1);\n                int new_total = total_dist(new_order);\n                if (new_total < best_total) {\n                    best_total = new_total;\n                    order = new_order;\n                    improved = true;\n                }\n            }\n        }\n    }\n    \n    // Reconstruct full points sequence\n    vector<int> new_points;\n    new_points.push_back(points[0]); // start\n    for (int idx : order) new_points.push_back(points[idx]);\n    new_points.push_back(points[M-1]); // end (start again)\n    \n    return {new_points, best_total};\n}\n\n// Function to reconstruct moves from optimized points sequence\nstring reconstruct_moves(const vector<int>& points, \n                        int N, const vector<string>& grid,\n                        const vector<vector<int>>& idx,\n                        const vector<int>& row, const vector<int>& col,\n                        const vector<int>& w, int V) {\n    string moves;\n    int M = points.size();\n    \n    for (int i = 0; i + 1 < M; ++i) {\n        int from = points[i];\n        int to = points[i+1];\n        \n        // Run Dijkstra from 'from' to get path to 'to'\n        vector<int> dist(V, INF);\n        vector<int> pred(V, -1);\n        dist[from] = 0;\n        using P = pair<int, int>;\n        priority_queue<P, vector<P>, greater<P>> pq;\n        pq.emplace(0, from);\n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop();\n            if (d != dist[u]) continue;\n            if (u == to) break; // we found the target\n            int r = row[u], c = col[u];\n            for (int k = 0; k < 4; ++k) {\n                int nr = r + dr[k];\n                int nc = c + dc[k];\n                if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n                int v = idx[nr][nc];\n                if (v == -1) continue;\n                int nd = d + w[v];\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    pred[v] = u;\n                    pq.emplace(nd, v);\n                }\n            }\n        }\n        \n        // Reconstruct path from 'from' to 'to'\n        vector<int> path;\n        for (int v = to; v != from; v = pred[v]) {\n            path.push_back(v);\n        }\n        path.push_back(from);\n        reverse(path.begin(), path.end());\n        \n        // Add moves for this segment\n        for (size_t j = 0; j + 1 < path.size(); ++j) {\n            int a = path[j];\n            int b = path[j+1];\n            int dr = row[b] - row[a];\n            int dc = col[b] - col[a];\n            char move;\n            if (dr == -1) move = 'U';\n            else if (dr == 1) move = 'D';\n            else if (dc == -1) move = 'L';\n            else if (dc == 1) move = 'R';\n            moves += move;\n        }\n    }\n    return moves;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, si, sj;\n    cin >> N >> si >> sj;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> grid[i];\n    }\n\n    // assign indices to road squares\n    vector<vector<int>> idx(N, vector<int>(N, -1));\n    vector<int> row, col, w;\n    int V = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != '#') {\n                idx[i][j] = V;\n                row.push_back(i);\n                col.push_back(j);\n                w.push_back(grid[i][j] - '0');\n                ++V;\n            }\n        }\n    }\n\n    // compute horizontal segments\n    vector<int> seg_id_h(V, -1);\n    vector<vector<int>> seg_nodes_h;\n    int h_cnt = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != '#' && seg_id_h[idx[i][j]] == -1) {\n                int sid = h_cnt++;\n                seg_nodes_h.push_back({});\n                int jj = j;\n                while (jj < N && grid[i][jj] != '#') {\n                    int id = idx[i][jj];\n                    seg_id_h[id] = sid;\n                    seg_nodes_h[sid].push_back(id);\n                    ++jj;\n                }\n            }\n        }\n    }\n\n    // compute vertical segments\n    vector<int> seg_id_v(V, -1);\n    vector<vector<int>> seg_nodes_v;\n    int v_cnt = 0;\n    for (int j = 0; j < N; ++j) {\n        for (int i = 0; i < N; ++i) {\n            if (grid[i][j] != '#' && seg_id_v[idx[i][j]] == -1) {\n                int sid = v_cnt++;\n                seg_nodes_v.push_back({});\n                int ii = i;\n                while (ii < N && grid[ii][j] != '#') {\n                    int id = idx[ii][j];\n                    seg_id_v[id] = sid;\n                    seg_nodes_v[sid].push_back(id);\n                    ++ii;\n                }\n            }\n        }\n    }\n\n    int start_idx = idx[si][sj];\n    int start_seg_h = seg_id_h[start_idx];\n    int start_seg_v = seg_id_v[start_idx];\n\n    // Try both orientations\n    auto [points_h, cost_h] = run_greedy_points(N, grid, idx, row, col, w, V, \n                                               seg_id_h, seg_nodes_h, h_cnt, \n                                               start_idx, start_seg_h);\n    auto [points_v, cost_v] = run_greedy_points(N, grid, idx, row, col, w, V, \n                                               seg_id_v, seg_nodes_v, v_cnt, \n                                               start_idx, start_seg_v);\n\n    // Choose the orientation with lower cost\n    vector<int> points;\n    if (cost_h <= cost_v) {\n        points = points_h;\n    } else {\n        points = points_v;\n    }\n\n    // Apply 2-opt optimization\n    auto dist_mat = compute_distance_matrix(points, N, grid, idx, row, col, w, V);\n    auto [optimized_points, optimized_cost] = apply_2opt(points, dist_mat);\n\n    // Reconstruct moves from optimized points\n    string moves = reconstruct_moves(optimized_points, N, grid, idx, row, col, w, V);\n\n    cout << moves << '\\n';\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto seed = chrono::system_clock::now().time_since_epoch().count();\n    mt19937 rng(seed);\n    \n    int N, M, K, R;\n    cin >> N >> M >> K >> R;\n    \n    vector<vector<int>> d(N, vector<int>(K));\n    vector<double> task_difficulty(N, 0.0);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < K; ++j) {\n            cin >> d[i][j];\n            task_difficulty[i] += d[i][j];\n        }\n    }\n    \n    vector<vector<int>> succ(N), pred(N);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        succ[u].push_back(v);\n        pred[v].push_back(u);\n    }\n    \n    // Compute task depths and out-degree\n    vector<int> depth(N, 0);\n    vector<int> out_degree(N, 0);\n    for (int i = 0; i < N; ++i) {\n        out_degree[i] = succ[i].size();\n    }\n    for (int i = N-1; i >= 0; --i) {\n        if (succ[i].empty()) {\n            depth[i] = 1;\n        } else {\n            int max_depth = 0;\n            for (int next : succ[i]) {\n                max_depth = max(max_depth, depth[next]);\n            }\n            depth[i] = max_depth + 1;\n        }\n    }\n    \n    // Initialize skill estimates for members\n    // Start with average of task requirements divided by 2\n    vector<vector<double>> skill_est(M, vector<double>(K, 0.0));\n    for (int k = 0; k < K; ++k) {\n        double sum = 0;\n        for (int i = 0; i < N; ++i) {\n            sum += d[i][k];\n        }\n        double avg = sum / N;\n        for (int j = 0; j < M; ++j) {\n            skill_est[j][k] = avg * 0.8;  // Start with 80% of average requirement\n        }\n    }\n    \n    // Track member performance for adaptive learning\n    vector<int> member_tasks_done(M, 0);\n    vector<double> member_avg_time(M, 0.0);\n    \n    // Task and member states\n    vector<int> task_status(N, -1);  // -1: pending, 0: in progress, 1: completed\n    vector<int> task_start_day(N, -1);\n    vector<int> prereq_rem(N, 0);\n    for (int i = 0; i < N; ++i) {\n        prereq_rem[i] = pred[i].size();\n    }\n    \n    vector<int> member_task(M, -1);\n    vector<int> member_last_used(M, 0);\n    \n    int day = 0;\n    while (true) {\n        ++day;\n        if (day > 2000) break;\n        \n        // Process completions from previous day\n        if (day > 1) {\n            int n;\n            cin >> n;\n            if (n == -1) break;\n            \n            for (int i = 0; i < n; ++i) {\n                int f;\n                cin >> f;\n                --f;\n                int task_idx = member_task[f];\n                if (task_idx == -1) continue;\n                \n                task_status[task_idx] = 1;\n                int t_obs = (day - 1) - task_start_day[task_idx] + 1;\n                \n                // Update member statistics\n                member_tasks_done[f]++;\n                member_avg_time[f] = (member_avg_time[f] * (member_tasks_done[f] - 1) + t_obs) / member_tasks_done[f];\n                \n                // Update skill estimates based on observed time\n                if (t_obs == 1) {\n                    // When t_obs = 1, we know w + r_i \u2264 0\n                    // Since r_i \u2265 -3, we have w \u2264 3\n                    // So for each skill dimension where task requires more than estimated:\n                    // We know d_k - s_k \u2264 3, so s_k \u2265 d_k - 3\n                    for (int k = 0; k < K; ++k) {\n                        if (d[task_idx][k] > skill_est[f][k]) {\n                            double new_min = d[task_idx][k] - 3.0;\n                            skill_est[f][k] = max(skill_est[f][k], new_min);\n                        }\n                    }\n                } else {\n                    // For t_obs > 1, use gradient-based update with adaptive learning rate\n                    double predicted_w = 0;\n                    int deficit_count = 0;\n                    for (int k = 0; k < K; ++k) {\n                        if (d[task_idx][k] > skill_est[f][k]) {\n                            predicted_w += d[task_idx][k] - skill_est[f][k];\n                            deficit_count++;\n                        }\n                    }\n                    predicted_w = max(1.0, predicted_w);\n                    \n                    double error = t_obs - predicted_w;\n                    // Clip error to handle random noise (r_i between -3 and 3)\n                    double clipped_error = max(-5.0, min(5.0, error));\n                    \n                    if (deficit_count > 0) {\n                        // Adaptive learning rate based on number of observations\n                        double lr = 0.2 / (1.0 + member_tasks_done[f] * 0.05);\n                        \n                        // Update skills: if error > 0, we underpredicted time, \n                        // so we need to decrease skill (increase w)\n                        for (int k = 0; k < K; ++k) {\n                            if (d[task_idx][k] > skill_est[f][k]) {\n                                skill_est[f][k] = max(0.0, skill_est[f][k] - lr * clipped_error / deficit_count);\n                            }\n                        }\n                    }\n                }\n                \n                // Update prerequisites\n                for (int next : succ[task_idx]) {\n                    --prereq_rem[next];\n                }\n                \n                member_task[f] = -1;\n                member_last_used[f] = day;\n            }\n        }\n        \n        // Find free members and ready tasks\n        vector<int> free_members;\n        for (int j = 0; j < M; ++j) {\n            if (member_task[j] == -1) {\n                free_members.push_back(j);\n            }\n        }\n        \n        vector<int> ready_tasks;\n        for (int i = 0; i < N; ++i) {\n            if (task_status[i] == -1 && prereq_rem[i] == 0) {\n                ready_tasks.push_back(i);\n            }\n        }\n        \n        if (free_members.empty() || ready_tasks.empty()) {\n            cout << \"0\\n\";\n            cout.flush();\n            continue;\n        }\n        \n        // Sort ready tasks by priority: depth descending, then difficulty ascending\n        // Prioritize tasks on critical path, but prefer easier tasks when possible\n        sort(ready_tasks.begin(), ready_tasks.end(), [&](int a, int b) {\n            if (depth[a] != depth[b]) return depth[a] > depth[b];\n            return task_difficulty[a] < task_difficulty[b];\n        });\n        \n        vector<pair<int, int>> assignments;\n        \n        // Greedy assignment: assign tasks in priority order to best member\n        for (int task_idx : ready_tasks) {\n            if (free_members.empty()) break;\n            \n            int best_member = -1;\n            double best_score = -1e18;\n            \n            for (int member_idx : free_members) {\n                // Predict time for this member on this task\n                double pred_w = 0;\n                for (int k = 0; k < K; ++k) {\n                    if (d[task_idx][k] > skill_est[member_idx][k]) {\n                        pred_w += d[task_idx][k] - skill_est[member_idx][k];\n                    }\n                }\n                double pred_time = max(1.0, pred_w);\n                \n                // Score considers predicted time and member's recent performance\n                double score = -pred_time;\n                \n                // Bonus for members who have been idle longer\n                double idle_days = day - member_last_used[member_idx];\n                score += idle_days * 0.1;\n                \n                // Bonus for members with lower average completion time\n                if (member_tasks_done[member_idx] > 0) {\n                    score -= member_avg_time[member_idx] * 0.05;\n                }\n                \n                // Bonus for task-member compatibility\n                double compatibility = 0;\n                for (int k = 0; k < K; ++k) {\n                    if (d[task_idx][k] <= skill_est[member_idx][k]) {\n                        compatibility += 1.0;\n                    }\n                }\n                score += compatibility * 0.1;\n                \n                if (score > best_score) {\n                    best_score = score;\n                    best_member = member_idx;\n                }\n            }\n            \n            if (best_member != -1) {\n                task_status[task_idx] = 0;\n                task_start_day[task_idx] = day;\n                member_task[best_member] = task_idx;\n                assignments.emplace_back(best_member, task_idx);\n                free_members.erase(find(free_members.begin(), free_members.end(), best_member));\n            }\n        }\n        \n        cout << assignments.size();\n        for (auto [member, task] : assignments) {\n            cout << ' ' << member + 1 << ' ' << task + 1;\n        }\n        cout << '\\n';\n        cout.flush();\n    }\n    \n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point {\n    int x, y;\n    Point() {}\n    Point(int x, int y) : x(x), y(y) {}\n};\n\nint manhattan(const Point& a, const Point& b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    // Read 1000 orders\n    vector<Point> restaurants(1000), destinations(1000);\n    for (int i = 0; i < 1000; ++i) {\n        cin >> restaurants[i].x >> restaurants[i].y >> destinations[i].x >> destinations[i].y;\n    }\n\n    const Point depot(400, 400);\n\n    // Step 1: Select 50 orders with smallest max distance to depot\n    vector<int> order_cost(1000);\n    for (int i = 0; i < 1000; ++i) {\n        order_cost[i] = max(manhattan(depot, restaurants[i]), manhattan(depot, destinations[i]));\n    }\n    vector<int> indices(1000);\n    iota(indices.begin(), indices.end(), 0);\n    sort(indices.begin(), indices.end(), [&](int i, int j) {\n        return order_cost[i] < order_cost[j];\n    });\n\n    vector<int> selected_orders;\n    for (int i = 0; i < 50; ++i) {\n        selected_orders.push_back(indices[i]);\n    }\n\n    // Create points for selected orders\n    vector<Point> points;\n    vector<pair<int, int>> point_info; // (order_index, type) type: 0=pickup, 1=delivery\n    for (int i = 0; i < 50; ++i) {\n        int order_idx = selected_orders[i];\n        points.push_back(restaurants[order_idx]);\n        point_info.push_back({i, 0});\n        points.push_back(destinations[order_idx]);\n        point_info.push_back({i, 1});\n    }\n\n    // Step 2: Build initial tour using cheapest insertion with multiple starting points\n    const int total_points = 100;\n    // Precompute distances\n    vector<vector<int>> dist_mat(total_points, vector<int>(total_points));\n    vector<int> dist_to_depot(total_points);\n    for (int i = 0; i < total_points; ++i) {\n        for (int j = 0; j < total_points; ++j) {\n            dist_mat[i][j] = manhattan(points[i], points[j]);\n        }\n        dist_to_depot[i] = manhattan(points[i], depot);\n    }\n\n    // Try multiple starting orders and keep the best initial tour\n    vector<int> best_tour;\n    int best_tour_length = INT_MAX;\n    \n    // Keep 30 starting points (good balance between quality and time)\n    for (int start_order = 0; start_order < 30 && start_order < 50; ++start_order) {\n        vector<int> tour = {start_order * 2, start_order * 2 + 1};\n        vector<bool> used(50, false);\n        used[start_order] = true;\n        \n        // Insert remaining orders\n        for (int step = 1; step < 50; ++step) {\n            int best_increase = INT_MAX;\n            int best_order = -1;\n            int best_pickup_pos = -1;\n            int best_delivery_pos = -1;\n\n            // Try each unused order\n            for (int order = 0; order < 50; ++order) {\n                if (used[order]) continue;\n                int pickup_idx = order * 2;\n                int delivery_idx = order * 2 + 1;\n\n                // Try all insertion positions\n                int tour_size = tour.size();\n                for (int i = 0; i <= tour_size; ++i) {\n                    for (int j = i; j <= tour_size; ++j) {\n                        int increase = 0;\n                        if (i == j) {\n                            Point A = (i == 0) ? depot : points[tour[i-1]];\n                            Point B = (i == tour_size) ? depot : points[tour[i]];\n                            int dAB = (i == 0 || i == tour_size) ? 0 : manhattan(A, B);\n                            increase = manhattan(A, points[pickup_idx]) + \n                                       dist_mat[pickup_idx][delivery_idx] + \n                                       manhattan(points[delivery_idx], B) - dAB;\n                        } else {\n                            Point A1 = (i == 0) ? depot : points[tour[i-1]];\n                            Point B1 = (i == tour_size) ? depot : points[tour[i]];\n                            int dA1B1 = (i == 0 || i == tour_size) ? 0 : manhattan(A1, B1);\n                            int inc_pickup = manhattan(A1, points[pickup_idx]) + \n                                             manhattan(points[pickup_idx], B1) - dA1B1;\n                            \n                            Point C = (j == 0) ? depot : points[tour[j-1]];\n                            Point D = (j == tour_size) ? depot : points[tour[j]];\n                            int dCD = (j == 0 || j == tour_size) ? 0 : manhattan(C, D);\n                            int inc_delivery = manhattan(C, points[delivery_idx]) + \n                                               manhattan(points[delivery_idx], D) - dCD;\n                            increase = inc_pickup + inc_delivery;\n                        }\n\n                        if (increase < best_increase) {\n                            best_increase = increase;\n                            best_order = order;\n                            best_pickup_pos = i;\n                            best_delivery_pos = j;\n                        }\n                    }\n                }\n            }\n\n            // Insert the best order\n            int pickup_idx = best_order * 2;\n            int delivery_idx = best_order * 2 + 1;\n            \n            if (best_pickup_pos == best_delivery_pos) {\n                tour.insert(tour.begin() + best_pickup_pos, pickup_idx);\n                tour.insert(tour.begin() + best_pickup_pos + 1, delivery_idx);\n            } else {\n                tour.insert(tour.begin() + best_pickup_pos, pickup_idx);\n                if (best_delivery_pos > best_pickup_pos) {\n                    best_delivery_pos++;\n                }\n                tour.insert(tour.begin() + best_delivery_pos, delivery_idx);\n            }\n            used[best_order] = true;\n        }\n        \n        // Calculate tour length\n        int tour_length = dist_to_depot[tour[0]] + dist_to_depot[tour.back()];\n        for (size_t i = 0; i < tour.size() - 1; ++i) {\n            tour_length += dist_mat[tour[i]][tour[i+1]];\n        }\n        \n        if (tour_length < best_tour_length) {\n            best_tour_length = tour_length;\n            best_tour = tour;\n        }\n    }\n    \n    vector<int> seq = best_tour;\n\n    // Step 3: Simulated annealing with fine-tuned parameters\n    auto is_feasible = [&](const vector<int>& sequence) {\n        vector<int> first_pickup(50, -1);\n        vector<int> first_delivery(50, -1);\n        for (int idx = 0; idx < sequence.size(); ++idx) {\n            int point_idx = sequence[idx];\n            auto [order, type] = point_info[point_idx];\n            if (type == 0 && first_pickup[order] == -1) {\n                first_pickup[order] = idx;\n            }\n            if (type == 1 && first_delivery[order] == -1) {\n                first_delivery[order] = idx;\n            }\n        }\n        for (int i = 0; i < 50; ++i) {\n            if (first_pickup[i] > first_delivery[i]) {\n                return false;\n            }\n        }\n        return true;\n    };\n\n    // Calculate tour length\n    auto calculate_length = [&](const vector<int>& sequence) {\n        int length = dist_to_depot[sequence[0]] + dist_to_depot[sequence.back()];\n        for (size_t i = 0; i < sequence.size() - 1; ++i) {\n            length += dist_mat[sequence[i]][sequence[i+1]];\n        }\n        return length;\n    };\n\n    // Fine-tuned SA configurations\n    vector<tuple<double, double, int, int>> sa_configs = {\n        {1600.0, 0.9997, 157657, 70},  // Slightly higher initial temp\n        {850.0, 0.9998, 133402, 60},    // Slightly higher initial temp\n        {2100.0, 0.9996, 109147, 80},   // Slightly higher initial temp\n        {550.0, 0.9999, 194040, 50},    // Slightly higher initial temp\n        {1300.0, 0.99975, 145530, 65}   // Slightly higher initial temp\n    };\n    \n    int global_best_length = calculate_length(seq);\n    vector<int> global_best_seq = seq;\n    \n    for (auto [initial_temp, cooling_rate, iterations, two_opt_percent] : sa_configs) {\n        vector<int> current_seq = seq;\n        int current_length = calculate_length(current_seq);\n        \n        double temperature = initial_temp;\n        int best_length = current_length;\n        vector<int> best_seq = current_seq;\n        int no_improve_count = 0;\n        \n        for (int iter = 0; iter < iterations && temperature > 0.1; ++iter) {\n            // Decide move type\n            bool use_two_opt = (rand() % 100) < two_opt_percent;\n            int delta = 0;\n            bool feasible = true;\n            \n            if (use_two_opt) {\n                // Generate a random 2-opt move\n                int i = rand() % (total_points - 1);\n                int j = i + 1 + rand() % (total_points - i - 1);\n                \n                // Calculate delta\n                int a = current_seq[i];\n                int b = current_seq[i + 1];\n                int c = current_seq[j];\n                int d = (j + 1 < total_points) ? current_seq[j + 1] : -1;\n\n                int old_len = dist_mat[a][b];\n                if (d == -1) old_len += dist_to_depot[c];\n                else old_len += dist_mat[c][d];\n\n                int new_len = dist_mat[a][c];\n                if (d == -1) new_len += dist_to_depot[b];\n                else new_len += dist_mat[b][d];\n\n                delta = new_len - old_len;\n                \n                // Check feasibility if move improves\n                if (delta < 0) {\n                    vector<int> new_seq = current_seq;\n                    reverse(new_seq.begin() + i + 1, new_seq.begin() + j + 1);\n                    feasible = is_feasible(new_seq);\n                }\n                \n                // Apply move if accepted\n                if (feasible && (delta < 0 || exp(-delta / temperature) > (rand() / (RAND_MAX + 1.0)))) {\n                    reverse(current_seq.begin() + i + 1, current_seq.begin() + j + 1);\n                    current_length += delta;\n                }\n            } else {\n                // Or-opt move: move a segment of 1-4 points\n                int seg_len = 1 + rand() % 4; // 1, 2, 3, or 4\n                if (seg_len >= total_points) seg_len = total_points - 1;\n                \n                int from = rand() % (total_points - seg_len + 1);\n                int to = rand() % (total_points - seg_len + 1);\n                while (abs(from - to) < seg_len) { // Ensure non-overlapping\n                    to = rand() % (total_points - seg_len + 1);\n                }\n                \n                // Calculate delta for or-opt\n                vector<int> new_seq = current_seq;\n                // Extract segment\n                vector<int> segment(new_seq.begin() + from, new_seq.begin() + from + seg_len);\n                // Remove segment\n                new_seq.erase(new_seq.begin() + from, new_seq.begin() + from + seg_len);\n                // Insert segment at new position\n                new_seq.insert(new_seq.begin() + (to > from ? to - seg_len : to), \n                              segment.begin(), segment.end());\n                \n                if (is_feasible(new_seq)) {\n                    int new_length = calculate_length(new_seq);\n                    delta = new_length - current_length;\n                    \n                    if (delta < 0 || exp(-delta / temperature) > (rand() / (RAND_MAX + 1.0))) {\n                        current_seq = new_seq;\n                        current_length = new_length;\n                    }\n                }\n            }\n            \n            // Update best solution\n            if (current_length < best_length) {\n                best_length = current_length;\n                best_seq = current_seq;\n                no_improve_count = 0;\n            } else {\n                no_improve_count++;\n                // Simple restart if stuck\n                if (no_improve_count > 10000) {\n                    current_seq = best_seq;\n                    current_length = best_length;\n                    no_improve_count = 0;\n                    temperature *= 1.5; // Reheat\n                }\n            }\n            \n            temperature *= cooling_rate;\n        }\n        \n        // Update global best\n        if (best_length < global_best_length) {\n            global_best_length = best_length;\n            global_best_seq = best_seq;\n        }\n    }\n    \n    seq = global_best_seq;\n    \n    // Step 4: Optimized local search with early termination\n    bool improved = true;\n    int passes = 0;\n    const int max_passes = 400;\n    int consecutive_no_improve = 0;\n    \n    while (improved && passes < max_passes) {\n        improved = false;\n        passes++;\n        \n        // Try 2-opt moves\n        for (int i = 0; i < total_points - 1 && !improved; ++i) {\n            for (int j = i + 1; j < total_points && !improved; ++j) {\n                int a = seq[i];\n                int b = seq[i + 1];\n                int c = seq[j];\n                int d = (j + 1 < total_points) ? seq[j + 1] : -1;\n\n                int old_len = dist_mat[a][b];\n                if (d == -1) old_len += dist_to_depot[c];\n                else old_len += dist_mat[c][d];\n\n                int new_len = dist_mat[a][c];\n                if (d == -1) new_len += dist_to_depot[b];\n                else new_len += dist_mat[b][d];\n\n                int delta = new_len - old_len;\n                \n                if (delta < 0) {\n                    vector<int> new_seq = seq;\n                    reverse(new_seq.begin() + i + 1, new_seq.begin() + j + 1);\n                    if (is_feasible(new_seq)) {\n                        seq = new_seq;\n                        improved = true;\n                    }\n                }\n            }\n        }\n        \n        // If no 2-opt improvement, try or-opt moves\n        if (!improved) {\n            for (int seg_len = 1; seg_len <= 4 && !improved; ++seg_len) {\n                for (int from = 0; from <= total_points - seg_len && !improved; ++from) {\n                    for (int to = 0; to <= total_points - seg_len && !improved; ++to) {\n                        if (abs(from - to) < seg_len) continue; // Overlap\n                        \n                        vector<int> new_seq = seq;\n                        vector<int> segment(new_seq.begin() + from, new_seq.begin() + from + seg_len);\n                        new_seq.erase(new_seq.begin() + from, new_seq.begin() + from + seg_len);\n                        new_seq.insert(new_seq.begin() + (to > from ? to - seg_len : to), \n                                      segment.begin(), segment.end());\n                        \n                        if (is_feasible(new_seq)) {\n                            int new_length = calculate_length(new_seq);\n                            int old_length = calculate_length(seq);\n                            if (new_length < old_length) {\n                                seq = new_seq;\n                                improved = true;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Early termination if no improvement for several passes\n        if (!improved) {\n            consecutive_no_improve++;\n            if (consecutive_no_improve >= 20) { // Stop if no improvement for 20 consecutive passes\n                break;\n            }\n        } else {\n            consecutive_no_improve = 0;\n        }\n    }\n\n    // Step 5: Output results\n    cout << 50 << \" \";\n    for (int i = 0; i < 50; ++i) {\n        cout << selected_orders[i] + 1 << \" \";\n    }\n    cout << \"\\n\";\n\n    cout << 102 << \" 400 400 \";\n    for (int idx : seq) {\n        cout << points[idx].x << \" \" << points[idx].y << \" \";\n    }\n    cout << \"400 400\\n\";\n\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Edge {\n    int u, v, d;\n};\n\nstruct DSU {\n    vector<int> parent, sz;\n    DSU(int n) : parent(n), sz(n, 1) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        if (parent[x] != x) parent[x] = find(parent[x]);\n        return parent[x];\n    }\n    bool unite(int x, int y) {\n        x = find(x), y = find(y);\n        if (x == y) return false;\n        if (sz[x] < sz[y]) swap(x, y);\n        parent[y] = x;\n        sz[x] += sz[y];\n        return true;\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(N), y(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> x[i] >> y[i];\n    }\n\n    const int M = 5 * (N - 1);   // 1995\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        int dx = x[u] - x[v];\n        int dy = y[u] - y[v];\n        double dist = sqrt(dx * dx + dy * dy);\n        int d = (int)(dist + 0.5);   // round to nearest integer\n        edges[i] = {u, v, d};\n    }\n\n    // Precompute for each edge whether it is a bridge in the suffix graph (edges i..M-1)\n    vector<bool> is_bridge(M, false);\n    for (int i = 0; i < M; ++i) {\n        // build adjacency for edges i..M-1\n        vector<vector<pair<int, int>>> adj(N);\n        for (int j = i; j < M; ++j) {\n            int u = edges[j].u, v = edges[j].v;\n            adj[u].emplace_back(v, j);\n            adj[v].emplace_back(u, j);\n        }\n\n        vector<int> disc(N, -1), low(N, -1);\n        int timer = 0;\n        vector<bool> bridge_this(M, false);\n\n        function<void(int, int)> dfs = [&](int v, int parent_edge) {\n            disc[v] = low[v] = timer++;\n            for (auto [to, id] : adj[v]) {\n                if (id == parent_edge) continue;\n                if (disc[to] == -1) {\n                    dfs(to, id);\n                    low[v] = min(low[v], low[to]);\n                    if (low[to] > disc[v]) {\n                        bridge_this[id] = true;\n                    }\n                } else {\n                    low[v] = min(low[v], disc[to]);\n                }\n            }\n        };\n\n        for (int v = 0; v < N; ++v) {\n            if (disc[v] == -1) {\n                dfs(v, -1);\n            }\n        }\n        is_bridge[i] = bridge_this[i];\n    }\n\n    DSU dsu(N);\n    for (int i = 0; i < M; ++i) {\n        int l;\n        cin >> l;\n        int u = edges[i].u, v = edges[i].v;\n        bool accept = false;\n        if (dsu.find(u) == dsu.find(v)) {\n            accept = false;   // would create a cycle\n        } else {\n            if (is_bridge[i]) {\n                accept = true;   // forced to keep connectivity\n            } else {\n                // accept if weight is at most twice the lower bound (mean)\n                if (l <= 2 * edges[i].d) {\n                    accept = true;\n                } else {\n                    accept = false;\n                }\n            }\n        }\n        cout << (accept ? 1 : 0) << endl;\n        if (accept) {\n            dsu.unite(u, v);\n        }\n    }\n    return 0;\n}","ahc008":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n\nusing namespace std;\n\nconst int MAXN = 30;\nconst int dirs[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};\n\nbool wall[MAXN][MAXN] = {false};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N;\n    vector<pair<int, int>> pets(N);\n    for (int i = 0; i < N; ++i) {\n        int x, y, t;\n        cin >> x >> y >> t;\n        pets[i] = {x - 1, y - 1};\n    }\n    cin >> M;\n    vector<pair<int, int>> humans(M);\n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        humans[i] = {x - 1, y - 1};\n    }\n\n    // Assign target corners to each human\n    vector<pair<int, int>> target(M);\n    for (int i = 0; i < M; ++i) {\n        if (i % 4 == 0) target[i] = {0, 0};\n        else if (i % 4 == 1) target[i] = {0, 29};\n        else if (i % 4 == 2) target[i] = {29, 0};\n        else target[i] = {29, 29};\n    }\n\n    for (int turn = 0; turn < 300; ++turn) {\n        string actions(M, '.');\n\n        // For each human, try to build a wall on an adjacent cell if safe\n        for (int i = 0; i < M; ++i) {\n            int hx = humans[i].first, hy = humans[i].second;\n            bool built = false;\n\n            // Check each adjacent cell for building\n            for (int d = 0; d < 4; ++d) {\n                int nx = hx + dirs[d][0], ny = hy + dirs[d][1];\n                if (nx < 0 || nx >= MAXN || ny < 0 || ny >= MAXN) continue;\n                if (wall[nx][ny]) continue; // already a wall\n\n                // Check no pet on the cell\n                bool pet_on_cell = false;\n                for (const auto& p : pets) {\n                    if (p.first == nx && p.second == ny) {\n                        pet_on_cell = true;\n                        break;\n                    }\n                }\n                if (pet_on_cell) continue;\n\n                // Check no human on the cell\n                bool human_on_cell = false;\n                for (int j = 0; j < M; ++j) {\n                    if (humans[j].first == nx && humans[j].second == ny) {\n                        human_on_cell = true;\n                        break;\n                    }\n                }\n                if (human_on_cell) continue;\n\n                // Check no pet adjacent to the cell\n                bool pet_adjacent = false;\n                for (int dd = 0; dd < 4; ++dd) {\n                    int nnx = nx + dirs[dd][0], nny = ny + dirs[dd][1];\n                    if (nnx < 0 || nnx >= MAXN || nny < 0 || nny >= MAXN) continue;\n                    for (const auto& p : pets) {\n                        if (p.first == nnx && p.second == nny) {\n                            pet_adjacent = true;\n                            break;\n                        }\n                    }\n                    if (pet_adjacent) break;\n                }\n                if (pet_adjacent) continue;\n\n                // Safe to build\n                if (d == 0) actions[i] = 'u';\n                else if (d == 1) actions[i] = 'd';\n                else if (d == 2) actions[i] = 'l';\n                else if (d == 3) actions[i] = 'r';\n                built = true;\n                break;\n            }\n\n            // If cannot build, move towards target corner\n            if (!built) {\n                int tx = target[i].first, ty = target[i].second;\n                // If already at target, do nothing (stay)\n                if (hx == tx && hy == ty) {\n                    actions[i] = '.';\n                } else {\n                    // Determine desired direction(s) to reduce Manhattan distance\n                    vector<int> preferred_dirs;\n                    if (hx < tx) preferred_dirs.push_back(1); // down\n                    else if (hx > tx) preferred_dirs.push_back(0); // up\n                    if (hy < ty) preferred_dirs.push_back(3); // right\n                    else if (hy > ty) preferred_dirs.push_back(2); // left\n\n                    // Try preferred directions first, then others\n                    bool moved = false;\n                    for (int d : preferred_dirs) {\n                        int nx = hx + dirs[d][0], ny = hy + dirs[d][1];\n                        if (nx < 0 || nx >= MAXN || ny < 0 || ny >= MAXN) continue;\n                        if (wall[nx][ny]) continue;\n                        // Check no pet on the cell\n                        bool pet_on_cell = false;\n                        for (const auto& p : pets) {\n                            if (p.first == nx && p.second == ny) {\n                                pet_on_cell = true;\n                                break;\n                            }\n                        }\n                        if (pet_on_cell) continue;\n                        // Check no human on the cell\n                        bool human_on_cell = false;\n                        for (int j = 0; j < M; ++j) {\n                            if (humans[j].first == nx && humans[j].second == ny) {\n                                human_on_cell = true;\n                                break;\n                            }\n                        }\n                        if (human_on_cell) continue;\n                        // Safe to move\n                        if (d == 0) actions[i] = 'U';\n                        else if (d == 1) actions[i] = 'D';\n                        else if (d == 2) actions[i] = 'L';\n                        else if (d == 3) actions[i] = 'R';\n                        moved = true;\n                        break;\n                    }\n                    // If preferred directions blocked, try any safe direction\n                    if (!moved) {\n                        for (int d = 0; d < 4; ++d) {\n                            if (find(preferred_dirs.begin(), preferred_dirs.end(), d) != preferred_dirs.end()) continue;\n                            int nx = hx + dirs[d][0], ny = hy + dirs[d][1];\n                            if (nx < 0 || nx >= MAXN || ny < 0 || ny >= MAXN) continue;\n                            if (wall[nx][ny]) continue;\n                            bool pet_on_cell = false;\n                            for (const auto& p : pets) {\n                                if (p.first == nx && p.second == ny) {\n                                    pet_on_cell = true;\n                                    break;\n                                }\n                            }\n                            if (pet_on_cell) continue;\n                            bool human_on_cell = false;\n                            for (int j = 0; j < M; ++j) {\n                                if (humans[j].first == nx && humans[j].second == ny) {\n                                    human_on_cell = true;\n                                    break;\n                                }\n                            }\n                            if (human_on_cell) continue;\n                            if (d == 0) actions[i] = 'U';\n                            else if (d == 1) actions[i] = 'D';\n                            else if (d == 2) actions[i] = 'L';\n                            else if (d == 3) actions[i] = 'R';\n                            moved = true;\n                            break;\n                        }\n                    }\n                    // If still cannot move, stay\n                    if (!moved) actions[i] = '.';\n                }\n            }\n        }\n\n        // Output actions\n        cout << actions << endl;\n        cout.flush();\n\n        // Update walls and human positions based on actions\n        for (int i = 0; i < M; ++i) {\n            char act = actions[i];\n            if (act == 'u' || act == 'd' || act == 'l' || act == 'r') {\n                int hx = humans[i].first, hy = humans[i].second;\n                int wx = hx, wy = hy;\n                if (act == 'u') wx = hx - 1;\n                else if (act == 'd') wx = hx + 1;\n                else if (act == 'l') wy = hy - 1;\n                else if (act == 'r') wy = hy + 1;\n                wall[wx][wy] = true;\n            } else if (act == 'U' || act == 'D' || act == 'L' || act == 'R') {\n                int hx = humans[i].first, hy = humans[i].second;\n                if (act == 'U') humans[i].first = hx - 1;\n                else if (act == 'D') humans[i].first = hx + 1;\n                else if (act == 'L') humans[i].second = hy - 1;\n                else if (act == 'R') humans[i].second = hy + 1;\n            }\n        }\n\n        // Read pet movements\n        vector<string> pet_moves(N);\n        for (int i = 0; i < N; ++i) {\n            cin >> pet_moves[i];\n        }\n\n        // Update pet positions\n        for (int i = 0; i < N; ++i) {\n            int x = pets[i].first, y = pets[i].second;\n            for (char c : pet_moves[i]) {\n                if (c == 'U') --x;\n                else if (c == 'D') ++x;\n                else if (c == 'L') --y;\n                else if (c == 'R') ++y;\n            }\n            pets[i] = {x, y};\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cstring>\n#include <algorithm>\n#include <cmath>\nusing namespace std;\n\nconst int N = 20;\nconst int L = 200;\nconst int STATES = N * N;\nconst int BEAM_WIDTH = 100;  // increased from 80 to 100\n\nint neighbor[STATES][4];\ndouble stay_prob[STATES][4];\ndouble move_prob[STATES][4];\ndouble V[STATES][L + 1];\nint goal_id, start_id;\n\nstruct Candidate {\n    vector<double> bel;\n    double accum;\n    string seq;\n    double estimate;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj, ti, tj;\n    double p;\n    cin >> si >> sj >> ti >> tj >> p;\n\n    vector<string> h(N);\n    for (int i = 0; i < N; ++i) cin >> h[i];\n    vector<string> v(N - 1);\n    for (int i = 0; i < N - 1; ++i) cin >> v[i];\n\n    // Build neighbour table and transition probabilities\n    memset(neighbor, -1, sizeof(neighbor));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int id = i * N + j;\n            // up\n            if (i > 0 && v[i - 1][j] == '0')\n                neighbor[id][0] = (i - 1) * N + j;\n            // down\n            if (i < N - 1 && v[i][j] == '0')\n                neighbor[id][1] = (i + 1) * N + j;\n            // left\n            if (j > 0 && h[i][j - 1] == '0')\n                neighbor[id][2] = i * N + (j - 1);\n            // right\n            if (j < N - 1 && h[i][j] == '0')\n                neighbor[id][3] = i * N + (j + 1);\n        }\n    }\n\n    // Precompute stay_prob and move_prob for each state and action\n    for (int s = 0; s < STATES; ++s) {\n        for (int a = 0; a < 4; ++a) {\n            if (neighbor[s][a] == -1) {\n                stay_prob[s][a] = 1.0;\n                move_prob[s][a] = 0.0;\n            } else {\n                stay_prob[s][a] = p;\n                move_prob[s][a] = 1.0 - p;\n            }\n        }\n    }\n\n    start_id = si * N + sj;\n    goal_id = ti * N + tj;\n\n    // DP for optimal closed\u2011loop value V[state][rem]\n    for (int s = 0; s < STATES; ++s)\n        for (int r = 0; r <= L; ++r)\n            V[s][r] = 0.0;\n\n    for (int rem = 1; rem <= L; ++rem) {\n        double reward_reach = 200.0 + rem;   // 401 - (200 - rem + 1)\n        for (int s = 0; s < STATES; ++s) {\n            if (s == goal_id) {\n                V[s][rem] = 0.0;\n                continue;\n            }\n            double best = 0.0;\n            for (int a = 0; a < 4; ++a) {\n                int nb = neighbor[s][a];\n                double sp = stay_prob[s][a];\n                double mp = move_prob[s][a];\n                double expected = sp * V[s][rem - 1];\n                if (mp > 0.0) {\n                    if (nb == goal_id) {\n                        expected += mp * reward_reach;\n                    } else {\n                        expected += mp * V[nb][rem - 1];\n                    }\n                }\n                if (expected > best) best = expected;\n            }\n            V[s][rem] = best;\n        }\n    }\n\n    // Beam search for the memorized string\n    vector<Candidate> beam;\n    vector<double> start_bel(STATES, 0.0);\n    start_bel[start_id] = 1.0;\n    beam.push_back({start_bel, 0.0, \"\", 0.0});\n\n    const char dir_chars[] = \"UDLR\";\n\n    for (int step = 1; step <= L; ++step) {\n        int rem = L - step;   // steps remaining after this one\n        vector<Candidate> next_beam;\n        next_beam.reserve(beam.size() * 4);\n\n        for (const auto& cand : beam) {\n            for (int a = 0; a < 4; ++a) {\n                vector<double> new_bel(STATES, 0.0);\n                double immediate_reward = 0.0;\n                // Compute new belief and immediate reward for this step\n                for (int s = 0; s < STATES; ++s) {\n                    double prob = cand.bel[s];\n                    if (prob == 0.0) continue;\n                    int nb = neighbor[s][a];\n                    double sp = stay_prob[s][a];\n                    double mp = move_prob[s][a];\n                    new_bel[s] += prob * sp;\n                    if (mp > 0.0) {\n                        if (nb == goal_id) {\n                            immediate_reward += prob * mp * (401 - step);\n                        } else {\n                            new_bel[nb] += prob * mp;\n                        }\n                    }\n                }\n                double new_accum = cand.accum + immediate_reward;\n                double heuristic = 0.0;\n                for (int s = 0; s < STATES; ++s)\n                    heuristic += new_bel[s] * V[s][rem];\n                double estimate = new_accum + heuristic;\n\n                Candidate new_cand;\n                new_cand.bel = move(new_bel);\n                new_cand.accum = new_accum;\n                new_cand.seq = cand.seq + dir_chars[a];\n                new_cand.estimate = estimate;\n                next_beam.push_back(move(new_cand));\n            }\n        }\n\n        // Keep only the top BEAM_WIDTH candidates by estimate\n        sort(next_beam.begin(), next_beam.end(),\n             [](const Candidate& x, const Candidate& y) {\n                 return x.estimate > y.estimate;\n             });\n        if (next_beam.size() > BEAM_WIDTH)\n            next_beam.resize(BEAM_WIDTH);\n        beam = move(next_beam);\n    }\n\n    // Select the candidate with the highest actual accumulated score\n    Candidate best = *max_element(beam.begin(), beam.end(),\n                                  [](const Candidate& x, const Candidate& y) {\n                                      return x.accum < y.accum;\n                                  });\n    cout << best.seq << endl;\n\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30;\nconst int D = 4;\nconst int di[D] = {0, -1, 0, 1};\nconst int dj[D] = {-1, 0, 1, 0};\nconst int MAX_STATES = N * N * D;\n\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\nint type[N][N];\nint rot[N][N];\nint best_rot[N][N];\nint best_score = 0;\n\ninline int get_exit(int t, int r, int d) {\n    int d_in = ((d - r) + 4) & 3;\n    int e = to[t][d_in];\n    if (e == -1) return -1;\n    return (e + r) & 3;\n}\n\ninline int state_id(int i, int j, int d) {\n    return (i * N + j) * D + d;\n}\n\ninline void state_coord(int id, int& i, int& j, int& d) {\n    d = id % D;\n    int ij = id / D;\n    j = ij % N;\n    i = ij / N;\n}\n\nint compute_score_and_cycle_count(const int rot[N][N], int& cycle_count) {\n    static int status[MAX_STATES];\n    memset(status, 0, sizeof(status));\n    \n    vector<int> cycles;\n    int path[MAX_STATES];\n    \n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            for (int d = 0; d < D; ++d) {\n                int sid = state_id(i, j, d);\n                if (status[sid]) continue;\n                \n                int t = type[i][j];\n                int r = rot[i][j];\n                if (get_exit(t, r, d) == -1) {\n                    status[sid] = 2;\n                    continue;\n                }\n                \n                int path_len = 0;\n                int ci = i, cj = j, cd = d;\n                int cur_sid = sid;\n                \n                while (true) {\n                    if (status[cur_sid] == 2) {\n                        for (int k = 0; k < path_len; ++k) {\n                            status[path[k]] = 2;\n                        }\n                        break;\n                    }\n                    if (status[cur_sid] == 1) {\n                        int cycle_start = -1;\n                        for (int k = 0; k < path_len; ++k) {\n                            if (path[k] == cur_sid) {\n                                cycle_start = k;\n                                break;\n                            }\n                        }\n                        int cycle_len = path_len - cycle_start;\n                        cycles.push_back(cycle_len);\n                        for (int k = 0; k < path_len; ++k) {\n                            status[path[k]] = 2;\n                        }\n                        break;\n                    }\n                    \n                    status[cur_sid] = 1;\n                    path[path_len++] = cur_sid;\n                    \n                    int t2 = type[ci][cj];\n                    int r2 = rot[ci][cj];\n                    int d2 = get_exit(t2, r2, cd);\n                    if (d2 == -1) {\n                        for (int k = 0; k < path_len; ++k) {\n                            status[path[k]] = 2;\n                        }\n                        break;\n                    }\n                    \n                    int ni = ci + di[d2];\n                    int nj = cj + dj[d2];\n                    if (ni < 0 || ni >= N || nj < 0 || nj >= N) {\n                        for (int k = 0; k < path_len; ++k) {\n                            status[path[k]] = 2;\n                        }\n                        break;\n                    }\n                    \n                    int nd = (d2 + 2) & 3;\n                    if (get_exit(type[ni][nj], rot[ni][nj], nd) == -1) {\n                        for (int k = 0; k < path_len; ++k) {\n                            status[path[k]] = 2;\n                        }\n                        break;\n                    }\n                    \n                    ci = ni;\n                    cj = nj;\n                    cd = nd;\n                    cur_sid = state_id(ci, cj, cd);\n                }\n            }\n        }\n    }\n    \n    sort(cycles.rbegin(), cycles.rend());\n    cycle_count = cycles.size();\n    if (cycle_count < 2) return 0;\n    return cycles[0] * cycles[1];\n}\n\nint compute_score(const int rot[N][N]) {\n    int dummy;\n    return compute_score_and_cycle_count(rot, dummy);\n}\n\nvoid ensure_initial_cycles() {\n    // Keep randomizing until we have at least 2 cycles\n    mt19937 rng(42);\n    uniform_int_distribution<int> dist(0, 3);\n    int cycle_count;\n    \n    do {\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                rot[i][j] = dist(rng);\n        compute_score_and_cycle_count(rot, cycle_count);\n    } while (cycle_count < 2);\n}\n\nvoid greedy_init() {\n    ensure_initial_cycles();\n    \n    // Multiple passes of greedy improvement\n    for (int iter = 0; iter < 5; ++iter) {\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                int best_r = rot[i][j];\n                int best_score = compute_score(rot);\n                for (int r = 0; r < 4; ++r) {\n                    if (r == rot[i][j]) continue;\n                    rot[i][j] = r;\n                    int new_score = compute_score(rot);\n                    if (new_score > best_score) {\n                        best_score = new_score;\n                        best_r = r;\n                    }\n                }\n                rot[i][j] = best_r;\n            }\n        }\n    }\n}\n\nvoid simulated_annealing() {\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> uni(0.0, 1.0);\n    uniform_int_distribution<int> rand_tile(0, N-1);\n    uniform_int_distribution<int> rand_rot(0, 3);\n    \n    int cycle_count;\n    int current_score = compute_score_and_cycle_count(rot, cycle_count);\n    best_score = current_score;\n    memcpy(best_rot, rot, sizeof(rot));\n    \n    const int max_iter = 20000;\n    const double T0 = 1000.0;\n    double T = T0;\n    \n    int no_improve = 0;\n    \n    for (int iter = 0; iter < max_iter; ++iter) {\n        // Select tile to change\n        int i = rand_tile(rng);\n        int j = rand_tile(rng);\n        \n        int old_r = rot[i][j];\n        int new_r = (old_r + 1 + rand_rot(rng)) % 4;\n        rot[i][j] = new_r;\n        \n        // Check if we still have at least 2 cycles\n        int new_cycle_count;\n        int new_score = compute_score_and_cycle_count(rot, new_cycle_count);\n        if (new_cycle_count < 2) {\n            rot[i][j] = old_r;\n            no_improve++;\n            continue;\n        }\n        \n        double delta = new_score - current_score;\n        if (delta > 0 || uni(rng) < exp(delta / T)) {\n            current_score = new_score;\n            cycle_count = new_cycle_count;\n            if (new_score > best_score) {\n                best_score = new_score;\n                memcpy(best_rot, rot, sizeof(rot));\n                no_improve = 0;\n            } else {\n                no_improve++;\n            }\n        } else {\n            rot[i][j] = old_r;\n            no_improve++;\n        }\n        \n        // Restart if stuck\n        if (no_improve > 800) {\n            // Restart from best with mutation\n            memcpy(rot, best_rot, sizeof(rot));\n            // Mutate 8 random tiles, ensuring we keep at least 2 cycles\n            for (int m = 0; m < 8; ++m) {\n                int mi = rand_tile(rng), mj = rand_tile(rng);\n                int old_mr = rot[mi][mj];\n                int new_mr = (old_mr + 1 + rand_rot(rng)) % 4;\n                rot[mi][mj] = new_mr;\n                \n                int temp_count;\n                compute_score_and_cycle_count(rot, temp_count);\n                if (temp_count < 2) {\n                    rot[mi][mj] = old_mr;\n                }\n            }\n            current_score = compute_score_and_cycle_count(rot, cycle_count);\n            no_improve = 0;\n        }\n        \n        // Cool down\n        T = T0 * pow(0.9995, iter);\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < N; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; ++j) {\n            type[i][j] = s[j] - '0';\n        }\n    }\n\n    greedy_init();\n    simulated_annealing();\n    \n    string ans;\n    ans.reserve(N * N);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            ans += char('0' + best_rot[i][j]);\n    cout << ans << endl;\n\n    return 0;\n}","ahc011":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <cstring>\n#include <stack>\n\nusing namespace std;\n\nint N, T;\nint board[10][10];\nint empty_r, empty_c;\nint total_tiles; // N*N-1\n\n// precomputed bits for patterns 0..15\nbool has_up[16], has_down[16], has_left[16], has_right[16];\n\n// direction vectors and corresponding move characters\nconst int dr[4] = {-1, 1, 0, 0};\nconst int dc[4] = {0, 0, -1, 1};\nconst char move_char[4] = {'U', 'D', 'L', 'R'};\n\nvoid precompute_bits() {\n    for (int p = 0; p < 16; ++p) {\n        has_left[p]  = p & 1;\n        has_up[p]    = p & 2;\n        has_right[p] = p & 4;\n        has_down[p]  = p & 8;\n    }\n}\n\nint hex_to_int(char c) {\n    if ('0' <= c && c <= '9') return c - '0';\n    return 10 + c - 'a';\n}\n\n// compute number of mutual edges for a cell\nint mutual_edges(int b[10][10], int i, int j) {\n    if (b[i][j] == 0) return 0;\n    int cnt = 0;\n    int p = b[i][j];\n    if (i > 0 && b[i-1][j] && has_up[p] && has_down[b[i-1][j]]) ++cnt;\n    if (i+1 < N && b[i+1][j] && has_down[p] && has_up[b[i+1][j]]) ++cnt;\n    if (j > 0 && b[i][j-1] && has_left[p] && has_right[b[i][j-1]]) ++cnt;\n    if (j+1 < N && b[i][j+1] && has_right[p] && has_left[b[i][j+1]]) ++cnt;\n    return cnt;\n}\n\n// compute change in total mutual edges when swapping empty at (er,ec) with tile at (nr,nc)\nint delta_edges(int b[10][10], int er, int ec, int nr, int nc) {\n    vector<pair<int,int>> cells;\n    cells.emplace_back(er, ec);\n    cells.emplace_back(nr, nc);\n    for (int d = 0; d < 4; ++d) {\n        int r1 = er + dr[d], c1 = ec + dc[d];\n        if (r1 >= 0 && r1 < N && c1 >= 0 && c1 < N) cells.emplace_back(r1, c1);\n        int r2 = nr + dr[d], c2 = nc + dc[d];\n        if (r2 >= 0 && r2 < N && c2 >= 0 && c2 < N) cells.emplace_back(r2, c2);\n    }\n    sort(cells.begin(), cells.end());\n    cells.erase(unique(cells.begin(), cells.end()), cells.end());\n\n    int before = 0;\n    for (auto [x,y] : cells) {\n        before += mutual_edges(b, x, y);\n    }\n\n    swap(b[er][ec], b[nr][nc]);\n\n    int after = 0;\n    for (auto [x,y] : cells) {\n        after += mutual_edges(b, x, y);\n    }\n\n    swap(b[er][ec], b[nr][nc]);\n\n    return after - before;\n}\n\n// compute size of largest tree using union-find\nint compute_tree_size(int b[10][10]) {\n    int parent[100];\n    int sz[100];\n    int edge_count[100] = {0};\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int idx = i * N + j;\n            if (b[i][j] == 0) {\n                parent[idx] = -1;\n            } else {\n                parent[idx] = idx;\n                sz[idx] = 1;\n            }\n        }\n    }\n\n    auto find = [&](int x) {\n        while (parent[x] != x) {\n            parent[x] = parent[parent[x]];\n            x = parent[x];\n        }\n        return x;\n    };\n\n    auto unite = [&](int x, int y) {\n        x = find(x);\n        y = find(y);\n        if (x == y) {\n            edge_count[x]++;\n            return;\n        }\n        if (sz[x] < sz[y]) swap(x, y);\n        parent[y] = x;\n        sz[x] += sz[y];\n        edge_count[x] += edge_count[y] + 1;\n    };\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (b[i][j] == 0) continue;\n            int idx = i * N + j;\n            int p = b[i][j];\n            if (j+1 < N && b[i][j+1] != 0) {\n                int q = b[i][j+1];\n                if (has_right[p] && has_left[q]) {\n                    unite(idx, i * N + (j+1));\n                }\n            }\n            if (i+1 < N && b[i+1][j] != 0) {\n                int q = b[i+1][j];\n                if (has_down[p] && has_up[q]) {\n                    unite(idx, (i+1) * N + j);\n                }\n            }\n        }\n    }\n\n    int max_size = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int idx = i * N + j;\n            if (b[i][j] != 0 && parent[idx] == idx) {\n                int vertices = sz[idx];\n                int edges = edge_count[idx];\n                if (edges == vertices - 1) {\n                    max_size = max(max_size, vertices);\n                }\n            }\n        }\n    }\n    return max_size;\n}\n\n// single SA run with given time budget, returns best moves and score\npair<string, int> run_sa(double time_budget, mt19937_64& rng) {\n    int cur_board[10][10];\n    memcpy(cur_board, board, sizeof(board));\n    int cur_er = empty_r, cur_ec = empty_c;\n    int cur_S = compute_tree_size(cur_board);\n    string cur_moves = \"\";\n    int steps = 0;\n\n    int best_S = cur_S;\n    string best_moves = \"\";\n    int best_score;\n    if (cur_S == total_tiles)\n        best_score = (int)round(500000.0 * (2.0 - 0.0 / T));\n    else\n        best_score = (int)round(500000.0 * cur_S / total_tiles);\n\n    // best full tree (if any)\n    int best_full_S = 0;\n    string best_full_moves = \"\";\n    int best_full_score = -1;\n\n    double temp = 5.0;\n    const double cooling = 0.99995;\n    const double min_temp = 1e-3;\n    const double edge_weight = 0.1;\n\n    uniform_int_distribution<int> dir_dist(0, 3);\n    uniform_real_distribution<double> prob_dist(0.0, 1.0);\n\n    auto start_time = chrono::steady_clock::now();\n    int iteration = 0;\n\n    while (steps < T) {\n        if ((iteration & 20000) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > time_budget) break;\n        }\n        ++iteration;\n\n        int dir = dir_dist(rng);\n        int nr = cur_er + dr[dir];\n        int nc = cur_ec + dc[dir];\n        if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n\n        int d_edges = delta_edges(cur_board, cur_er, cur_ec, nr, nc);\n\n        swap(cur_board[cur_er][cur_ec], cur_board[nr][nc]);\n        int new_S = compute_tree_size(cur_board);\n        double delta = new_S - cur_S;\n        bool accept = false;\n\n        if (delta > 0)\n            accept = true;\n        else {\n            double combined = delta + edge_weight * d_edges;\n            if (temp > 1e-9) {\n                double prob = exp(combined / temp);\n                if (prob_dist(rng) < prob)\n                    accept = true;\n            }\n        }\n\n        if (accept) {\n            cur_moves += move_char[dir];\n            ++steps;\n            cur_er = nr;\n            cur_ec = nc;\n            cur_S = new_S;\n\n            int K = steps;\n            int score;\n            if (cur_S == total_tiles)\n                score = (int)round(500000.0 * (2.0 - (double)K / T));\n            else\n                score = (int)round(500000.0 * cur_S / total_tiles);\n\n            // update best overall\n            if (score > best_score) {\n                best_score = score;\n                best_S = cur_S;\n                best_moves = cur_moves;\n            }\n\n            // update best full tree\n            if (cur_S == total_tiles) {\n                int full_score = (int)round(500000.0 * (2.0 - (double)K / T));\n                if (full_score > best_full_score) {\n                    best_full_score = full_score;\n                    best_full_S = cur_S;\n                    best_full_moves = cur_moves;\n                }\n            }\n        } else {\n            swap(cur_board[cur_er][cur_ec], cur_board[nr][nc]);\n        }\n\n        temp *= cooling;\n        if (temp < min_temp) temp = min_temp;\n    }\n\n    // choose the best between overall and full\n    if (best_full_score > best_score) {\n        return {best_full_moves, best_full_score};\n    } else {\n        return {best_moves, best_score};\n    }\n}\n\nstring solve() {\n    precompute_bits();\n    total_tiles = N * N - 1;\n\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (board[i][j] == 0) {\n                empty_r = i;\n                empty_c = j;\n            }\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    auto start_time = chrono::steady_clock::now();\n    const double total_time_limit = 2.95; // total time for all runs\n    int run = 0;\n    const int max_runs = 7; // aim for 7 runs\n\n    string best_overall_moves = \"\";\n    int best_overall_score = -1;\n\n    while (run < max_runs) {\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\n        double time_budget = min(0.42, total_time_limit - elapsed);\n        if (time_budget < 0.1) break;\n\n        auto [moves, score] = run_sa(time_budget, rng);\n        if (score > best_overall_score) {\n            best_overall_score = score;\n            best_overall_moves = moves;\n            // if we have a full tree with a very high score (close to 1e6), we can break early\n            // but we don't know the theoretical maximum; we can break if score > 900000?\n            // For now, we don't break early to allow more exploration.\n        }\n        ++run;\n    }\n\n    return best_overall_moves;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> T;\n    for (int i = 0; i < N; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; ++j) {\n            board[i][j] = hex_to_int(s[j]);\n        }\n    }\n\n    string ans = solve();\n    cout << ans << endl;\n\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\nusing int64 = long long;\n\nstruct Line {\n    int64 px, py, qx, qy;\n    int64 dx, dy;\n};\n\nstruct pair_hash {\n    template <class T1, class T2>\n    size_t operator() (const pair<T1, T2>& p) const {\n        auto h1 = hash<T1>{}(p.first);\n        auto h2 = hash<T2>{}(p.second);\n        return h1 ^ (h2 << 1);\n    }\n};\n\nbool is_valid_line(const Line& line, const vector<int64>& xs, const vector<int64>& ys) {\n    if (line.px == line.qx && line.py == line.qy) return false;\n    int N = xs.size();\n    for (int i = 0; i < N; ++i) {\n        int64 cross = line.dx * (ys[i] - line.py) - line.dy * (xs[i] - line.px);\n        if (cross == 0) return false;\n    }\n    return true;\n}\n\nbool line_cuts_circle(const Line& line) {\n    int64 num = abs(line.qx * line.py - line.qy * line.px);\n    int64 len2 = line.dx * line.dx + line.dy * line.dy;\n    return num * num < 10000LL * 10000LL * len2;\n}\n\n// Generate K random valid lines\nvector<Line> generate_random_lines(int K, const vector<int64>& xs, const vector<int64>& ys, mt19937_64& rng) {\n    uniform_int_distribution<int> coord_dist(-20000, 20000);\n    vector<Line> lines;\n    while ((int)lines.size() < K) {\n        Line line;\n        line.px = coord_dist(rng);\n        line.py = coord_dist(rng);\n        line.qx = coord_dist(rng);\n        line.qy = coord_dist(rng);\n        line.dx = line.qx - line.px;\n        line.dy = line.qy - line.py;\n        if (is_valid_line(line, xs, ys) && line_cuts_circle(line)) {\n            lines.push_back(line);\n        }\n    }\n    return lines;\n}\n\n// Evaluate score for a given set of lines\nint evaluate_score(const vector<Line>& lines, const vector<int64>& xs, const vector<int64>& ys, const int a[]) {\n    int N = xs.size();\n    int K = lines.size();\n    \n    unordered_map<pair<uint64_t, uint64_t>, int, pair_hash> pat_cnt;\n    \n    for (int i = 0; i < N; ++i) {\n        uint64_t low = 0, high = 0;\n        for (int l = 0; l < K; ++l) {\n            int side = (lines[l].dx * (ys[i] - lines[l].py) -\n                        lines[l].dy * (xs[i] - lines[l].px)) > 0 ? 1 : 0;\n            if (l < 64) {\n                if (side) low |= (1ULL << l);\n            } else {\n                if (side) high |= (1ULL << (l - 64));\n            }\n        }\n        pat_cnt[make_pair(low, high)]++;\n    }\n    \n    int b[11] = {0};\n    for (auto& [pat, cnt] : pat_cnt) {\n        if (cnt >= 1 && cnt <= 10) b[cnt]++;\n    }\n    \n    int score = 0;\n    for (int d = 1; d <= 10; ++d) score += min(a[d], b[d]);\n    return score;\n}\n\n// Local search by perturbing one line at a time\nvoid local_search(vector<Line>& lines, const vector<int64>& xs, const vector<int64>& ys, const int a[], \n                  int iterations, mt19937_64& rng) {\n    uniform_int_distribution<int> line_dist(0, lines.size() - 1);\n    uniform_int_distribution<int> delta_dist(-5, 5);\n    uniform_int_distribution<int> which_dist(0, 1);\n    \n    int current_score = evaluate_score(lines, xs, ys, a);\n    \n    for (int iter = 0; iter < iterations; ++iter) {\n        int l = line_dist(rng);\n        Line new_line = lines[l];\n        \n        // Perturb one endpoint\n        if (which_dist(rng) == 0) {\n            new_line.px += delta_dist(rng);\n            new_line.py += delta_dist(rng);\n        } else {\n            new_line.qx += delta_dist(rng);\n            new_line.qy += delta_dist(rng);\n        }\n        \n        // Skip if endpoints coincide\n        if (new_line.px == new_line.qx && new_line.py == new_line.qy) continue;\n        \n        new_line.dx = new_line.qx - new_line.px;\n        new_line.dy = new_line.qy - new_line.py;\n        \n        // Check validity\n        if (!is_valid_line(new_line, xs, ys)) continue;\n        if (!line_cuts_circle(new_line)) continue;\n        \n        // Temporarily replace line and compute new score\n        Line old_line = lines[l];\n        lines[l] = new_line;\n        int new_score = evaluate_score(lines, xs, ys, a);\n        \n        if (new_score > current_score) {\n            current_score = new_score;\n        } else {\n            // Revert\n            lines[l] = old_line;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, K;\n    cin >> N >> K;\n    int a[11];\n    for (int d = 1; d <= 10; ++d) cin >> a[d];\n    vector<int64> xs(N), ys(N);\n    for (int i = 0; i < N; ++i) cin >> xs[i] >> ys[i];\n    \n    random_device rd;\n    mt19937_64 rng(rd());\n    \n    const int MULTI_START_ITERATIONS = 300;\n    const int LOCAL_SEARCH_ITERATIONS = 400;\n    \n    vector<Line> best_lines;\n    int best_score = -1;\n    \n    // Multi-start random search\n    for (int iter = 0; iter < MULTI_START_ITERATIONS; ++iter) {\n        vector<Line> lines = generate_random_lines(K, xs, ys, rng);\n        int score = evaluate_score(lines, xs, ys, a);\n        if (score > best_score) {\n            best_score = score;\n            best_lines = lines;\n        }\n    }\n    \n    // Local search on the best configuration\n    local_search(best_lines, xs, ys, a, LOCAL_SEARCH_ITERATIONS, rng);\n    \n    cout << K << \"\\n\";\n    for (int i = 0; i < K; ++i) {\n        cout << best_lines[i].px << \" \" << best_lines[i].py << \" \"\n             << best_lines[i].qx << \" \" << best_lines[i].qy << \"\\n\";\n    }\n    \n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <array>\n#include <random>\n#include <chrono>\n#include <algorithm>\n\nusing namespace std;\n\nstruct MoveCandidate {\n    array<int, 8> pts;\n    double score;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::steady_clock::now();\n    const double TIME_LIMIT = 4.5;  // seconds\n    \n    int N, M;\n    cin >> N >> M;\n\n    const int c = (N - 1) / 2;\n    vector<vector<int>> w(N, vector<int>(N));\n    long long totalS = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int dx = i - c, dy = j - c;\n            w[i][j] = dx * dx + dy * dy + 1;\n            totalS += w[i][j];\n        }\n    }\n\n    vector<pair<int, int>> init(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> init[i].first >> init[i].second;\n    }\n\n    vector<array<int, 8>> best_ops;\n    long long best_score = -1;\n    int trial = 0;\n    \n    while (true) {\n        auto current_time = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(current_time - start_time).count();\n        if (elapsed > TIME_LIMIT) break;\n        trial++;\n        \n        // Initialize state\n        vector<vector<char>> dot(N, vector<char>(N, 0));\n        for (auto& p : init) dot[p.first][p.second] = 1;\n\n        vector<vector<char>> h_edge(N, vector<char>(N, 0));\n        vector<vector<char>> v_edge(N, vector<char>(N, 0));\n        vector<vector<char>> d1_edge(N, vector<char>(N, 0));\n        vector<vector<char>> d2_edge(N, vector<char>(N, 0));\n\n        vector<array<int, 8>> ops;\n        mt19937 rng(chrono::steady_clock::now().time_since_epoch().count() + trial);\n        uniform_real_distribution<double> noise(0.0, 0.1);\n\n        while (true) {\n            vector<MoveCandidate> candidates;\n            double max_score = -1.0;\n\n            for (int x = 0; x < N; ++x) {\n                for (int y = 0; y < N; ++y) {\n                    if (dot[x][y]) continue;\n                    int pw = w[x][y];\n\n                    // Unit squares (4 orientations)\n                    // lower-left\n                    if (x + 1 < N && y + 1 < N) {\n                        if (dot[x+1][y] && dot[x][y+1] && dot[x+1][y+1]) {\n                            if (!h_edge[x][y] && !h_edge[x][y+1] && !v_edge[x][y] && !v_edge[x+1][y]) {\n                                array<int,8> pts = {x, y, x+1, y, x+1, y+1, x, y+1};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                    // lower-right\n                    if (x - 1 >= 0 && y + 1 < N) {\n                        if (dot[x-1][y] && dot[x-1][y+1] && dot[x][y+1]) {\n                            if (!h_edge[x-1][y] && !h_edge[x-1][y+1] && !v_edge[x-1][y] && !v_edge[x][y]) {\n                                array<int,8> pts = {x, y, x, y+1, x-1, y+1, x-1, y};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                    // upper-left\n                    if (x + 1 < N && y - 1 >= 0) {\n                        if (dot[x][y-1] && dot[x+1][y-1] && dot[x+1][y]) {\n                            if (!h_edge[x][y-1] && !h_edge[x][y] && !v_edge[x][y-1] && !v_edge[x+1][y-1]) {\n                                array<int,8> pts = {x, y, x+1, y, x+1, y-1, x, y-1};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                    // upper-right\n                    if (x - 1 >= 0 && y - 1 >= 0) {\n                        if (dot[x-1][y-1] && dot[x][y-1] && dot[x-1][y]) {\n                            if (!h_edge[x-1][y-1] && !h_edge[x-1][y] && !v_edge[x-1][y-1] && !v_edge[x][y-1]) {\n                                array<int,8> pts = {x, y, x-1, y, x-1, y-1, x, y-1};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n\n                    // Unit diamonds (4 orientations)\n                    // case A\n                    if (x <= N-3 && y >= 1 && y <= N-2) {\n                        int lx = x, ly = y;\n                        if (dot[lx+1][ly+1] && dot[lx+2][ly] && dot[lx+1][ly-1]) {\n                            if (!d1_edge[lx][ly] && !d2_edge[lx+1][ly+1] && !d1_edge[lx+1][ly-1] && !d2_edge[lx][ly]) {\n                                array<int,8> pts = {lx, ly, lx+1, ly+1, lx+2, ly, lx+1, ly-1};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                    // case B\n                    if (x >= 1 && x <= N-2 && y >= 2 && y <= N-1) {\n                        int lx = x-1, ly = y-1;\n                        if (dot[lx][ly] && dot[lx+2][ly] && dot[lx+1][ly-1]) {\n                            if (!d1_edge[lx][ly] && !d2_edge[lx+1][ly+1] && !d1_edge[lx+1][ly-1] && !d2_edge[lx][ly]) {\n                                array<int,8> pts = {lx+1, ly+1, lx+2, ly, lx+1, ly-1, lx, ly};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                    // case C\n                    if (x >= 2 && y >= 1 && y <= N-2) {\n                        int lx = x-2, ly = y;\n                        if (dot[lx][ly] && dot[lx+1][ly+1] && dot[lx+1][ly-1]) {\n                            if (!d1_edge[lx][ly] && !d2_edge[lx+1][ly+1] && !d1_edge[lx+1][ly-1] && !d2_edge[lx][ly]) {\n                                array<int,8> pts = {lx+2, ly, lx+1, ly-1, lx, ly, lx+1, ly+1};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                    // case D\n                    if (x >= 1 && x <= N-2 && y >= 0 && y <= N-3) {\n                        int lx = x-1, ly = y+1;\n                        if (dot[lx][ly] && dot[lx+1][ly+1] && dot[lx+2][ly]) {\n                            if (!d1_edge[lx][ly] && !d2_edge[lx+1][ly+1] && !d1_edge[lx+1][ly-1] && !d2_edge[lx][ly]) {\n                                array<int,8> pts = {lx+1, ly-1, lx, ly, lx+1, ly+1, lx+2, ly};\n                                double score = pw + noise(rng);\n                                candidates.push_back({pts, score});\n                                if (score > max_score) max_score = score;\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (candidates.empty()) break;\n\n            // Select candidate with highest score\n            vector<int> best_idx;\n            for (size_t i = 0; i < candidates.size(); ++i) {\n                if (candidates[i].score == max_score) {\n                    best_idx.push_back(i);\n                }\n            }\n            int chosen = best_idx[uniform_int_distribution<int>(0, best_idx.size()-1)(rng)];\n            MoveCandidate& mv = candidates[chosen];\n\n            // Apply move\n            int x1 = mv.pts[0], y1 = mv.pts[1];\n            dot[x1][y1] = 1;\n\n            // Determine shape and mark edges\n            int minx = mv.pts[0], maxx = mv.pts[0], miny = mv.pts[1], maxy = mv.pts[1];\n            for (int i = 0; i < 4; ++i) {\n                int px = mv.pts[2*i], py = mv.pts[2*i+1];\n                if (px < minx) minx = px;\n                if (px > maxx) maxx = px;\n                if (py < miny) miny = py;\n                if (py > maxy) maxy = py;\n            }\n            \n            if (maxx - minx == 1 && maxy - miny == 1) {  // unit square\n                h_edge[minx][miny] = 1;\n                h_edge[minx][maxy] = 1;\n                v_edge[minx][miny] = 1;\n                v_edge[maxx][miny] = 1;\n            } else {  // unit diamond\n                int lx = minx, ly = -1;\n                for (int i = 0; i < 4; ++i) {\n                    if (mv.pts[2*i] == lx) {\n                        ly = mv.pts[2*i+1];\n                        break;\n                    }\n                }\n                d1_edge[lx][ly] = 1;\n                d2_edge[lx+1][ly+1] = 1;\n                d1_edge[lx+1][ly-1] = 1;\n                d2_edge[lx][ly] = 1;\n            }\n\n            ops.push_back(mv.pts);\n        }\n\n        // Calculate score for this trial\n        long long sum_w = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (dot[i][j]) sum_w += w[i][j];\n            }\n        }\n        double factor = (double)(N * N) / M;\n        double ratio = (double)sum_w / totalS;\n        long long score = llround(1e6 * factor * ratio);\n\n        if (score > best_score) {\n            best_score = score;\n            best_ops = ops;\n        }\n    }\n\n    // Output\n    cout << best_ops.size() << \"\\n\";\n    for (auto& op : best_ops) {\n        for (int i = 0; i < 8; ++i) {\n            if (i) cout << \" \";\n            cout << op[i];\n        }\n        cout << \"\\n\";\n    }\n\n    return 0;\n}","ahc015":"#include <iostream>\n#include <vector>\n#include <array>\n#include <queue>\n#include <utility>\n#include <algorithm>\n#include <cmath>\n#include <iomanip>\n#include <unordered_map>\n#include <string>\n#include <random>\n\nusing namespace std;\n\n// global flavors (1-indexed)\nvector<int> flavors(101);\n\n// 10x10 grid: 0 = empty, 1..3 = flavor\nusing Grid = array<array<int, 10>, 10>;\n\n// random generator with fixed seed\nmt19937 rng(12345);\n\n// ------------------------------------------------------------\n// tilt simulation\nGrid tilt(const Grid& g, char dir) {\n    Grid ng = {}; // zero-initialized\n    if (dir == 'F') {\n        for (int c = 0; c < 10; ++c) {\n            int idx = 0;\n            for (int r = 0; r < 10; ++r) {\n                if (g[r][c] != 0) {\n                    ng[idx++][c] = g[r][c];\n                }\n            }\n        }\n    } else if (dir == 'B') {\n        for (int c = 0; c < 10; ++c) {\n            int idx = 9;\n            for (int r = 9; r >= 0; --r) {\n                if (g[r][c] != 0) {\n                    ng[idx--][c] = g[r][c];\n                }\n            }\n        }\n    } else if (dir == 'L') {\n        for (int r = 0; r < 10; ++r) {\n            int idx = 0;\n            for (int c = 0; c < 10; ++c) {\n                if (g[r][c] != 0) {\n                    ng[r][idx++] = g[r][c];\n                }\n            }\n        }\n    } else if (dir == 'R') {\n        for (int r = 0; r < 10; ++r) {\n            int idx = 9;\n            for (int c = 9; c >= 0; --c) {\n                if (g[r][c] != 0) {\n                    ng[r][idx--] = g[r][c];\n                }\n            }\n        }\n    }\n    return ng;\n}\n\n// ------------------------------------------------------------\n// compute sum of squares of connected components\nint compute_sum_squares(const Grid& g) {\n    bool visited[10][10] = {};\n    int sum = 0;\n    for (int r = 0; r < 10; ++r) {\n        for (int c = 0; c < 10; ++c) {\n            if (g[r][c] != 0 && !visited[r][c]) {\n                int flavor = g[r][c];\n                int size = 0;\n                queue<pair<int, int>> q;\n                q.push({r, c});\n                visited[r][c] = true;\n                while (!q.empty()) {\n                    auto [x, y] = q.front(); q.pop();\n                    ++size;\n                    // four neighbors\n                    if (x > 0 && !visited[x-1][y] && g[x-1][y] == flavor) {\n                        visited[x-1][y] = true;\n                        q.push({x-1, y});\n                    }\n                    if (x < 9 && !visited[x+1][y] && g[x+1][y] == flavor) {\n                        visited[x+1][y] = true;\n                        q.push({x+1, y});\n                    }\n                    if (y > 0 && !visited[x][y-1] && g[x][y-1] == flavor) {\n                        visited[x][y-1] = true;\n                        q.push({x, y-1});\n                    }\n                    if (y < 9 && !visited[x][y+1] && g[x][y+1] == flavor) {\n                        visited[x][y+1] = true;\n                        q.push({x, y+1});\n                    }\n                }\n                sum += size * size;\n            }\n        }\n    }\n    return sum;\n}\n\n// ------------------------------------------------------------\n// compute total spread (sum of squared distances to centroid)\ndouble compute_spread(const Grid& g) {\n    vector<int> cnt(4, 0);\n    vector<double> sum_r(4, 0.0), sum_c(4, 0.0);\n    vector<double> sum_r2(4, 0.0), sum_c2(4, 0.0);\n    for (int r = 0; r < 10; ++r) {\n        for (int c = 0; c < 10; ++c) {\n            int f = g[r][c];\n            if (f != 0) {\n                cnt[f]++;\n                sum_r[f] += r;\n                sum_c[f] += c;\n                sum_r2[f] += r * r;\n                sum_c2[f] += c * c;\n            }\n        }\n    }\n    double total = 0.0;\n    for (int f = 1; f <= 3; ++f) {\n        if (cnt[f] > 0) {\n            double mean_r = sum_r[f] / cnt[f];\n            double mean_c = sum_c[f] / cnt[f];\n            total += (sum_r2[f] + sum_c2[f]) -\n                     (sum_r[f] * sum_r[f] + sum_c[f] * sum_c[f]) / cnt[f];\n        }\n    }\n    return total;\n}\n\n// ------------------------------------------------------------\n// helper to convert grid to string for memoization\nstring grid_to_string(const Grid& g) {\n    string s;\n    s.reserve(100);\n    for (int r = 0; r < 10; ++r) {\n        for (int c = 0; c < 10; ++c) {\n            s.push_back('0' + g[r][c]);\n        }\n    }\n    return s;\n}\n\n// ------------------------------------------------------------\n// recursive expectimax for remaining \u2264 4 candies, with memoization\ndouble expected_score(const Grid& grid, int next_idx,\n                      unordered_map<string, double>& memo) {\n    if (next_idx > 100) {\n        return compute_sum_squares(grid);\n    }\n\n    string key = grid_to_string(grid) + \":\" + to_string(next_idx);\n    auto it = memo.find(key);\n    if (it != memo.end()) {\n        return it->second;\n    }\n\n    // collect empty cells\n    vector<pair<int, int>> empties;\n    for (int r = 0; r < 10; ++r)\n        for (int c = 0; c < 10; ++c)\n            if (grid[r][c] == 0)\n                empties.emplace_back(r, c);\n\n    int E = empties.size();\n    double total = 0.0;\n\n    for (auto [r, c] : empties) {\n        // place the next candy\n        Grid g2 = grid;\n        g2[r][c] = flavors[next_idx];\n\n        // choose the best direction for this placement\n        double best = -1.0;\n        for (char dir : {'F', 'B', 'L', 'R'}) {\n            Grid g3 = tilt(g2, dir);\n            double val = expected_score(g3, next_idx + 1, memo);\n            if (val > best) best = val;\n        }\n        total += best;\n    }\n\n    double result = total / E;\n    memo[key] = result;\n    return result;\n}\n\n// ------------------------------------------------------------\n// compute adjacency score for a cell\nint compute_adjacency_score(const Grid& g, int r, int c, int flavor) {\n    int score = 0;\n    if (r > 0 && g[r-1][c] == flavor) ++score;\n    if (r < 9 && g[r+1][c] == flavor) ++score;\n    if (c > 0 && g[r][c-1] == flavor) ++score;\n    if (c < 9 && g[r][c+1] == flavor) ++score;\n    return score;\n}\n\n// ------------------------------------------------------------\n// get prioritized empty cells (sorted by adjacency to flavor)\nvector<pair<int, int>> get_prioritized_empties(const Grid& g, int flavor, int max_samples) {\n    vector<pair<int, int>> empties;\n    for (int r = 0; r < 10; ++r) {\n        for (int c = 0; c < 10; ++c) {\n            if (g[r][c] == 0) {\n                int score = compute_adjacency_score(g, r, c, flavor);\n                empties.emplace_back(r, c);\n                // store score in a separate vector for sorting\n            }\n        }\n    }\n    \n    // compute scores for each empty cell\n    vector<pair<int, pair<int, int>>> scored_empties;\n    for (auto [r, c] : empties) {\n        int score = compute_adjacency_score(g, r, c, flavor);\n        scored_empties.emplace_back(score, make_pair(r, c));\n    }\n    \n    // sort by score descending\n    sort(scored_empties.begin(), scored_empties.end(),\n         [](const auto& a, const auto& b) { return a.first > b.first; });\n    \n    // take top max_samples\n    vector<pair<int, int>> result;\n    for (int i = 0; i < min(max_samples, (int)scored_empties.size()); ++i) {\n        result.push_back(scored_empties[i].second);\n    }\n    \n    return result;\n}\n\n// ------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // read all flavors\n    for (int i = 1; i <= 100; ++i) {\n        cin >> flavors[i];\n    }\n\n    Grid grid = {};  // initially empty\n    const int SAMPLES = 12; // optimal number of samples\n    const double SPREAD_WEIGHT = 0.1; // optimal weight for spread penalty\n\n    for (int t = 1; t <= 100; ++t) {\n        int p;\n        cin >> p;\n\n        // place the t\u2011th candy in the p\u2011th empty cell (row\u2011major order)\n        int cnt = 0;\n        int r_place = -1, c_place = -1;\n        for (int r = 0; r < 10; ++r) {\n            for (int c = 0; c < 10; ++c) {\n                if (grid[r][c] == 0) {\n                    ++cnt;\n                    if (cnt == p) {\n                        r_place = r;\n                        c_place = c;\n                        break;\n                    }\n                }\n            }\n            if (cnt == p) break;\n        }\n        grid[r_place][c_place] = flavors[t];\n\n        // last tilt does nothing \u2013 output any direction and finish\n        if (t == 100) {\n            cout << 'F' << endl;\n            return 0;\n        }\n\n        int remaining = 100 - t;  // candies still to be placed after this step\n        char best_dir;\n        Grid best_grid;\n\n        if (remaining <= 4) {\n            // deep evaluation using expectimax with memoization\n            double best_val = -1.0;\n            for (char dir : {'F', 'B', 'L', 'R'}) {\n                Grid after_tilt = tilt(grid, dir);\n                unordered_map<string, double> memo;\n                double val = expected_score(after_tilt, t + 1, memo);\n                if (val > best_val) {\n                    best_val = val;\n                    best_dir = dir;\n                    best_grid = after_tilt;\n                }\n            }\n        } else {\n            // Monte Carlo lookahead with importance sampling\n            double best_expected = -1.0;\n            for (char dir : {'F', 'B', 'L', 'R'}) {\n                Grid after_tilt = tilt(grid, dir);\n\n                // get prioritized empty cells (adjacent to next flavor)\n                vector<pair<int, int>> empties = \n                    get_prioritized_empties(after_tilt, flavors[t + 1], SAMPLES);\n\n                if (empties.empty()) {\n                    continue; // should not happen when remaining > 0\n                }\n\n                double total = 0.0;\n                for (auto [r, c] : empties) {\n                    Grid g2 = after_tilt;\n                    g2[r][c] = flavors[t + 1]; // next candy\n\n                    // evaluate the best next tilt using combined score\n                    double best_score = -1e9;\n                    for (char dir2 : {'F', 'B', 'L', 'R'}) {\n                        Grid g3 = tilt(g2, dir2);\n                        int sum_sq = compute_sum_squares(g3);\n                        double spread = compute_spread(g3);\n                        double score = sum_sq - SPREAD_WEIGHT * spread;\n                        if (score > best_score) best_score = score;\n                    }\n                    total += best_score;\n                }\n\n                double expected = total / empties.size();\n                if (expected > best_expected) {\n                    best_expected = expected;\n                    best_dir = dir;\n                    best_grid = after_tilt;\n                }\n            }\n\n            // Fallback: if no direction was chosen (shouldn't happen), use greedy\n            if (best_expected < 0) {\n                int best_sum_sq = -1;\n                double best_spread = 1e9;\n                for (char dir : {'F', 'B', 'L', 'R'}) {\n                    Grid after_tilt = tilt(grid, dir);\n                    int sum_sq = compute_sum_squares(after_tilt);\n                    double spread = compute_spread(after_tilt);\n                    if (sum_sq > best_sum_sq ||\n                        (sum_sq == best_sum_sq && spread < best_spread)) {\n                        best_sum_sq = sum_sq;\n                        best_spread = spread;\n                        best_dir = dir;\n                        best_grid = after_tilt;\n                    }\n                }\n            }\n        }\n\n        cout << best_dir << endl;\n        grid = best_grid;\n    }\n\n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <string>\n#include <cmath>\n#include <cassert>\n#include <Eigen/Dense>\n\nusing namespace std;\nusing namespace Eigen;\n\n// Compute all eigenvalues of adjacency matrix (sorted descending)\nvector<double> compute_all_eigenvalues(const vector<vector<bool>>& adj, int N) {\n    // Convert to Eigen matrix\n    MatrixXd mat(N, N);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            mat(i, j) = adj[i][j] ? 1.0 : 0.0;\n        }\n    }\n    // Compute eigenvalues\n    SelfAdjointEigenSolver<MatrixXd> solver(mat);\n    VectorXd eigenvalues = solver.eigenvalues();\n    vector<double> result(eigenvalues.data(), eigenvalues.data() + eigenvalues.size());\n    sort(result.begin(), result.end(), greater<double>());\n    return result;\n}\n\nint main() {\n    // Problem parameters\n    int M;\n    double epsilon;\n    cin >> M >> epsilon;\n\n    // Fixed design choices\n    const int N = 30;                     // number of vertices\n    const int T = N * (N - 1) / 2;        // number of possible edges\n    const int TRIALS = 200;               // optimal trial count for speed/accuracy\n    const double EIG_WEIGHT = 0.85;       // slightly increased weight for eigenvalues\n\n    // ------------------------------------------------------------\n    // 1. Precompute all vertex pairs in lexicographic order\n    // ------------------------------------------------------------\n    vector<pair<int, int>> pairs;\n    pairs.reserve(T);\n    for (int i = 0; i < N; ++i)\n        for (int j = i + 1; j < N; ++j)\n            pairs.emplace_back(i, j);\n    assert(pairs.size() == T);\n\n    // ------------------------------------------------------------\n    // 2. Generate M random graphs with edge probability p_i = i/(M-1)\n    // ------------------------------------------------------------\n    // Random generator for graph construction (deterministic seed)\n    mt19937 rng_graph(12345);\n    uniform_real_distribution<double> dist_graph(0.0, 1.0);\n\n    // Storage: adjacency matrices and the output strings\n    vector<vector<vector<bool>>> adj(M, vector<vector<bool>>(N, vector<bool>(N, false)));\n    vector<string> graph_strings(M);\n\n    for (int idx = 0; idx < M; ++idx) {\n        double p = (M > 1) ? double(idx) / (M - 1) : 0.0;   // edge probability for this graph\n        string s(T, '0');\n        for (int e = 0; e < T; ++e) {\n            auto [u, v] = pairs[e];\n            if (dist_graph(rng_graph) < p) {\n                adj[idx][u][v] = true;\n                s[e] = '1';\n            }\n        }\n        graph_strings[idx] = s;\n    }\n\n    // ------------------------------------------------------------\n    // 3. Output the chosen N and the M graphs\n    // ------------------------------------------------------------\n    cout << N << endl;\n    for (int i = 0; i < M; ++i)\n        cout << graph_strings[i] << endl;\n    cout.flush();\n\n    // ------------------------------------------------------------\n    // 4. Precompute mean and variance of sorted degree sequences AND eigenvalues\n    //    under the noise model (edge flips with probability epsilon)\n    // ------------------------------------------------------------\n    // Random generator for noise simulation (different seed)\n    mt19937 rng_noise(54321);\n    uniform_real_distribution<double> dist_noise(0.0, 1.0);\n\n    // Means and variances for degree sequences (30 numbers)\n    vector<vector<double>> mean_deg(M, vector<double>(N, 0.0));\n    vector<vector<double>> var_deg(M, vector<double>(N, 0.0));\n    \n    // Means and variances for eigenvalues (30 numbers)\n    vector<vector<double>> mean_eig(M, vector<double>(N, 0.0));\n    vector<vector<double>> var_eig(M, vector<double>(N, 0.0));\n\n    for (int g = 0; g < M; ++g) {\n        // For degree sequences\n        vector<double> sum_deg(N, 0.0), sum_sq_deg(N, 0.0);\n        // For eigenvalues\n        vector<double> sum_eig(N, 0.0), sum_sq_eig(N, 0.0);\n        \n        for (int trial = 0; trial < TRIALS; ++trial) {\n            // Build noisy adjacency matrix\n            vector<vector<bool>> noisy_adj(N, vector<bool>(N, false));\n            for (int e = 0; e < T; ++e) {\n                auto [u, v] = pairs[e];\n                bool present = adj[g][u][v];\n                // flip with probability epsilon\n                if (dist_noise(rng_noise) < epsilon)\n                    present = !present;\n                if (present) {\n                    noisy_adj[u][v] = true;\n                    noisy_adj[v][u] = true;\n                }\n            }\n            \n            // Compute degree sequence\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_adj[i][j]) {\n                        deg[i]++;\n                        deg[j]++;\n                    }\n                }\n            }\n            sort(deg.begin(), deg.end());\n            for (int j = 0; j < N; ++j) {\n                sum_deg[j] += deg[j];\n                sum_sq_deg[j] += deg[j] * deg[j];\n            }\n            \n            // Compute eigenvalues\n            vector<double> eigenvalues = compute_all_eigenvalues(noisy_adj, N);\n            for (int j = 0; j < N; ++j) {\n                sum_eig[j] += eigenvalues[j];\n                sum_sq_eig[j] += eigenvalues[j] * eigenvalues[j];\n            }\n        }\n        \n        // Compute statistics for degree sequences\n        for (int j = 0; j < N; ++j) {\n            mean_deg[g][j] = sum_deg[j] / TRIALS;\n            double variance = sum_sq_deg[j] / TRIALS - mean_deg[g][j] * mean_deg[g][j];\n            if (variance < 1e-9) variance = 1e-9;\n            var_deg[g][j] = variance;\n        }\n        \n        // Compute statistics for eigenvalues\n        for (int j = 0; j < N; ++j) {\n            mean_eig[g][j] = sum_eig[j] / TRIALS;\n            double variance = sum_sq_eig[j] / TRIALS - mean_eig[g][j] * mean_eig[g][j];\n            if (variance < 1e-9) variance = 1e-9;\n            var_eig[g][j] = variance;\n        }\n    }\n\n    // ------------------------------------------------------------\n    // 5. Process the 100 queries\n    // ------------------------------------------------------------\n    for (int q = 0; q < 100; ++q) {\n        string H_str;\n        cin >> H_str;\n        assert(H_str.size() == T);\n\n        // Build adjacency matrix for H\n        vector<vector<bool>> H_adj(N, vector<bool>(N, false));\n        for (int e = 0; e < T; ++e) {\n            if (H_str[e] == '1') {\n                auto [u, v] = pairs[e];\n                H_adj[u][v] = true;\n                H_adj[v][u] = true;\n            }\n        }\n        \n        // Compute degree sequence of H\n        vector<int> deg_H(N, 0);\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) {\n                if (H_adj[i][j]) {\n                    deg_H[i]++;\n                    deg_H[j]++;\n                }\n            }\n        }\n        sort(deg_H.begin(), deg_H.end());\n        \n        // Compute eigenvalues of H\n        vector<double> eig_H = compute_all_eigenvalues(H_adj, N);\n\n        // Find the graph with smallest combined chi\u2011squared distance\n        int best_graph = 0;\n        double best_dist = 1e100;\n        for (int g = 0; g < M; ++g) {\n            // Degree sequence distance\n            double dist_deg = 0.0;\n            for (int j = 0; j < N; ++j) {\n                double diff = deg_H[j] - mean_deg[g][j];\n                dist_deg += (diff * diff) / var_deg[g][j];\n            }\n            \n            // Eigenvalue distance\n            double dist_eig = 0.0;\n            for (int j = 0; j < N; ++j) {\n                double diff = eig_H[j] - mean_eig[g][j];\n                dist_eig += (diff * diff) / var_eig[g][j];\n            }\n            \n            // Combined distance with slightly increased weight for eigenvalues\n            double total_dist = dist_deg + EIG_WEIGHT * dist_eig;\n            \n            if (total_dist < best_dist) {\n                best_dist = total_dist;\n                best_graph = g;\n            }\n        }\n\n        cout << best_graph << endl;\n        cout.flush();\n    }\n\n    return 0;\n}","ahc017":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n#include <cassert>\n\nusing namespace std;\n\nconst double INF = 1e18;\n\nstruct Edge {\n    int u, v;\n    long long w;\n};\n\nstruct Point {\n    double x, y;\n};\n\ndouble dist(const Point& a, const Point& b) {\n    double dx = a.x - b.x;\n    double dy = a.y - b.y;\n    return sqrt(dx*dx + dy*dy);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n    \n    vector<Edge> edges(M);\n    vector<vector<pair<int, int>>> adj(N);\n    \n    for (int i = 0; i < M; ++i) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        --u; --v;\n        edges[i] = {u, v, w};\n        adj[u].push_back({v, i});\n        adj[v].push_back({u, i});\n    }\n\n    vector<Point> pts(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> pts[i].x >> pts[i].y;\n    }\n\n    // Compute edge midpoints\n    vector<Point> mid(M);\n    for (int i = 0; i < M; ++i) {\n        int u = edges[i].u;\n        int v = edges[i].v;\n        mid[i].x = (pts[u].x + pts[v].x) * 0.5;\n        mid[i].y = (pts[u].y + pts[v].y) * 0.5;\n    }\n\n    // Compute edge betweenness centrality\n    vector<double> edge_betweenness(M, 0.0);\n    for (int s = 0; s < N; ++s) {\n        vector<double> dist_s(N, INF);\n        vector<double> sigma(N, 0.0);\n        vector<vector<int>> pred(N);\n        \n        dist_s[s] = 0.0;\n        sigma[s] = 1.0;\n        \n        priority_queue<pair<double, int>, vector<pair<double, int>>, greater<>> pq;\n        pq.push({0.0, s});\n        \n        while (!pq.empty()) {\n            double d = pq.top().first;\n            int v = pq.top().second;\n            pq.pop();\n            if (d > dist_s[v] + 1e-9) continue;\n            \n            for (auto& p : adj[v]) {\n                int to = p.first;\n                int eid = p.second;\n                long long w = edges[eid].w;\n                double nd = d + w;\n                if (nd < dist_s[to] - 1e-9) {\n                    dist_s[to] = nd;\n                    sigma[to] = sigma[v];\n                    pred[to].clear();\n                    pred[to].push_back(eid);\n                    pq.push({nd, to});\n                } else if (abs(nd - dist_s[to]) < 1e-9) {\n                    sigma[to] += sigma[v];\n                    pred[to].push_back(eid);\n                }\n            }\n        }\n        \n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int i, int j) { return dist_s[i] > dist_s[j]; });\n        \n        vector<double> delta(N, 0.0);\n        for (int v : order) {\n            if (v == s) continue;\n            for (int eid : pred[v]) {\n                int u = (edges[eid].u == v) ? edges[eid].v : edges[eid].u;\n                double coeff = sigma[u] / sigma[v];\n                edge_betweenness[eid] += coeff * (1.0 + delta[v]);\n                delta[u] += coeff * (1.0 + delta[v]);\n            }\n        }\n    }\n\n    // Normalize betweenness\n    double max_ebc = 0.0;\n    for (double val : edge_betweenness) {\n        if (val > max_ebc) max_ebc = val;\n    }\n    \n    vector<double> weight(M);\n    if (max_ebc < 1e-9) {\n        for (int i = 0; i < M; ++i) weight[i] = 1.0;\n    } else {\n        for (int i = 0; i < M; ++i) weight[i] = edge_betweenness[i] / max_ebc;\n    }\n\n    // Greedy assignment with spatial penalty (sum of inverse distances)\n    const double beta = 10.0;\n    vector<int> day_of(M, -1);\n    vector<int> cnt(D, 0);\n    vector<double> sum_w(D, 0.0);\n    vector<vector<Point>> day_points(D);\n\n    vector<int> order_edges(M);\n    iota(order_edges.begin(), order_edges.end(), 0);\n    sort(order_edges.begin(), order_edges.end(),\n         [&](int i, int j) { return weight[i] > weight[j]; });\n\n    for (int e : order_edges) {\n        int best_day = -1;\n        double best_score = 1e30;\n        \n        for (int d = 0; d < D; ++d) {\n            if (cnt[d] >= K) continue;\n            \n            double new_sum = sum_w[d] + weight[e];\n            \n            // Compute spatial penalty: sum of inverse distances to all edges in the day\n            double penalty = 0.0;\n            for (const Point& p : day_points[d]) {\n                double d_val = dist(mid[e], p);\n                penalty += 1.0 / (1.0 + d_val);\n            }\n            penalty *= beta;\n            \n            double score = new_sum + penalty;\n            \n            if (score < best_score) {\n                best_score = score;\n                best_day = d;\n            }\n        }\n        \n        assert(best_day != -1);\n        day_of[e] = best_day;\n        cnt[best_day]++;\n        sum_w[best_day] += weight[e];\n        day_points[best_day].push_back(mid[e]);\n    }\n\n    // Output\n    for (int i = 0; i < M; ++i) {\n        cout << day_of[i] + 1;\n        if (i < M - 1) cout << \" \";\n    }\n    cout << endl;\n\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAXD = 14;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    int D;\n    cin >> D;\n    vector<string> f1(D), r1(D), f2(D), r2(D);\n    for (int i = 0; i < D; ++i) cin >> f1[i];\n    for (int i = 0; i < D; ++i) cin >> r1[i];\n    for (int i = 0; i < D; ++i) cin >> f2[i];\n    for (int i = 0; i < D; ++i) cin >> r2[i];\n    \n    // Convert to boolean arrays for quick access\n    bool f1b[D][D] = {}, r1b[D][D] = {};\n    bool f2b[D][D] = {}, r2b[D][D] = {};\n    for (int z = 0; z < D; ++z) {\n        for (int x = 0; x < D; ++x) {\n            f1b[z][x] = (f1[z][x] == '1');\n            f2b[z][x] = (f2[z][x] == '1');\n        }\n        for (int y = 0; y < D; ++y) {\n            r1b[z][y] = (r1[z][y] == '1');\n            r2b[z][y] = (r2[z][y] == '1');\n        }\n    }\n    \n    // Allowed regions for each object\n    bool allowed1[D][D][D] = {};\n    bool allowed2[D][D][D] = {};\n    // Intersection I\n    bool I[D][D][D] = {};\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                allowed1[x][y][z] = f1b[z][x] && r1b[z][y];\n                allowed2[x][y][z] = f2b[z][x] && r2b[z][y];\n                I[x][y][z] = allowed1[x][y][z] && allowed2[x][y][z];\n            }\n        }\n    }\n    \n    // Connected components of I\n    int compI[D][D][D];\n    memset(compI, -1, sizeof(compI));\n    int num_components_I = 0;\n    const int dx[6] = {1,-1,0,0,0,0};\n    const int dy[6] = {0,0,1,-1,0,0};\n    const int dz[6] = {0,0,0,0,1,-1};\n    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 (I[x][y][z] && compI[x][y][z] == -1) {\n                    queue<tuple<int,int,int>> q;\n                    q.push({x, y, z});\n                    compI[x][y][z] = num_components_I;\n                    while (!q.empty()) {\n                        auto [cx, cy, cz] = q.front(); q.pop();\n                        for (int d = 0; d < 6; ++d) {\n                            int nx = cx + dx[d];\n                            int ny = cy + dy[d];\n                            int nz = cz + dz[d];\n                            if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D &&\n                                I[nx][ny][nz] && compI[nx][ny][nz] == -1) {\n                                compI[nx][ny][nz] = num_components_I;\n                                q.push({nx, ny, nz});\n                            }\n                        }\n                    }\n                    ++num_components_I;\n                }\n            }\n        }\n    }\n    \n    // Initialize objects with all cells from I (shared)\n    bool obj1[D][D][D] = {};\n    bool obj2[D][D][D] = {};\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 (I[x][y][z]) {\n                    obj1[x][y][z] = true;\n                    obj2[x][y][z] = true;\n                }\n    \n    // For each object, add minimal extra cells to satisfy silhouettes\n    for (int obj_id = 0; obj_id < 2; ++obj_id) {\n        bool (*obj)[D][D] = (obj_id == 0) ? obj1 : obj2;\n        bool (*fb)[D] = (obj_id == 0) ? f1b : f2b;\n        bool (*rb)[D] = (obj_id == 0) ? r1b : r2b;\n        for (int z = 0; z < D; ++z) {\n            // Lists of required x and y\n            vector<int> X, Y;\n            for (int x = 0; x < D; ++x) if (fb[z][x]) X.push_back(x);\n            for (int y = 0; y < D; ++y) if (rb[z][y]) Y.push_back(y);\n            \n            // Determine which x and y are already covered by I\n            vector<bool> x_covered(D, false), y_covered(D, false);\n            for (int x : X) {\n                for (int y = 0; y < D; ++y) {\n                    if (I[x][y][z]) {\n                        x_covered[x] = true;\n                        break;\n                    }\n                }\n            }\n            for (int y : Y) {\n                for (int x = 0; x < D; ++x) {\n                    if (I[x][y][z]) {\n                        y_covered[y] = true;\n                        break;\n                    }\n                }\n            }\n            \n            vector<int> X_rem, Y_rem;\n            for (int x : X) if (!x_covered[x]) X_rem.push_back(x);\n            for (int y : Y) if (!y_covered[y]) Y_rem.push_back(y);\n            \n            int a = X_rem.size(), b = Y_rem.size();\n            int M = max(a, b);\n            // Add cells to cover remaining requirements\n            if (a >= b) {\n                for (int i = 0; i < b; ++i) {\n                    int x = X_rem[i], y = Y_rem[i];\n                    obj[x][y][z] = true;\n                }\n                for (int i = b; i < a; ++i) {\n                    int x = X_rem[i];\n                    int y = Y.empty() ? 0 : Y[0]; // Y non\u2011empty because silhouette guarantees at least one y\n                    obj[x][y][z] = true;\n                }\n            } else {\n                for (int i = 0; i < a; ++i) {\n                    int x = X_rem[i], y = Y_rem[i];\n                    obj[x][y][z] = true;\n                }\n                for (int i = a; i < b; ++i) {\n                    int y = Y_rem[i];\n                    int x = X.empty() ? 0 : X[0];\n                    obj[x][y][z] = true;\n                }\n            }\n        }\n    }\n    \n    // Shared blocks are exactly the connected components of I\n    // Assign IDs to shared components\n    vector<int> comp_id(num_components_I);\n    int cur_id = 1;\n    for (int i = 0; i < num_components_I; ++i) comp_id[i] = cur_id++;\n    \n    // Prepare output arrays\n    vector<vector<vector<int>>> b1(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    vector<vector<vector<int>>> b2(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    \n    // Fill shared blocks in both objects\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 (I[x][y][z]) {\n                    int id = comp_id[compI[x][y][z]];\n                    b1[x][y][z] = id;\n                    b2[x][y][z] = id;\n                }\n    \n    // Unit blocks for non\u2011shared cells in obj1\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 (obj1[x][y][z] && !I[x][y][z])\n                    b1[x][y][z] = cur_id++;\n    \n    // Unit blocks for non\u2011shared cells in obj2\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 (obj2[x][y][z] && !I[x][y][z])\n                    b2[x][y][z] = cur_id++;\n    \n    // Output\n    int total_blocks = cur_id - 1;\n    cout << total_blocks << \"\\n\";\n    // b1\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                cout << b1[x][y][z];\n                if (x == D-1 && y == D-1 && z == D-1) cout << \"\\n\";\n                else cout << \" \";\n            }\n    // b2\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                cout << b2[x][y][z];\n                if (x == D-1 && y == D-1 && z == D-1) cout << \"\\n\";\n                else cout << \" \";\n            }\n    \n    return 0;\n}","ahc020":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <climits>\n#include <numeric>\n\nusing namespace std;\ntypedef long long ll;\n\nstruct Candidate {\n    int type;      // 0: active vertex, 1: inactive vertex\n    int idx;       // vertex index\n    int new_P;     // new output strength\n    ll cost;       // total cost of the action\n    int count;     // number of newly covered residents\n    int first_idx; // first index in sorted_res[idx] to cover\n    int last_idx;  // last index (exclusive) in sorted_res[idx] to cover\n};\n\n// integer ceil(sqrt(x))\nint ceil_sqrt(ll x) {\n    int r = sqrt(x);\n    while ((ll)r * r < x) ++r;\n    return r;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\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\n    vector<int> u(M), v(M), w(M);\n    vector<vector<pair<int, int>>> adj(N); // (neighbor, edge index)\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]].emplace_back(v[j], j);\n        adj[v[j]].emplace_back(u[j], j);\n    }\n\n    vector<int> a(K), b(K);\n    for (int k = 0; k < K; ++k) cin >> a[k] >> b[k];\n\n    // squared distances from vertices to residents\n    vector<vector<ll>> dist2(N, vector<ll>(K));\n    for (int i = 0; i < N; ++i) {\n        for (int k = 0; k < K; ++k) {\n            ll dx = x[i] - a[k];\n            ll dy = y[i] - b[k];\n            dist2[i][k] = dx * dx + dy * dy;\n        }\n    }\n\n    // for each vertex, residents sorted by distance\n    vector<vector<int>> sorted_res(N);\n    for (int i = 0; i < N; ++i) {\n        sorted_res[i].resize(K);\n        iota(sorted_res[i].begin(), sorted_res[i].end(), 0);\n        sort(sorted_res[i].begin(), sorted_res[i].end(),\n             [&](int k1, int k2) { return dist2[i][k1] < dist2[i][k2]; });\n    }\n\n    // state\n    vector<bool> covered(K, false);\n    int covered_cnt = 0;\n    vector<int> P(N, 0);\n    vector<int> next_uncovered(N, 0); // for active vertices\n    vector<bool> is_vertex_active(N, false);\n    is_vertex_active[0] = true; // station 1 (index 0)\n    vector<bool> is_edge_on(M, false);\n\n    // main loop\n    while (covered_cnt < K) {\n        // Dijkstra to compute additional connection costs\n        vector<ll> dist_conn(N, LLONG_MAX);\n        vector<int> prev_vertex(N, -1), prev_edge(N, -1);\n        priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<>> pq;\n        for (int i = 0; i < N; ++i) {\n            if (is_vertex_active[i]) {\n                dist_conn[i] = 0;\n                pq.emplace(0, i);\n            }\n        }\n        while (!pq.empty()) {\n            auto [d, u_idx] = pq.top(); pq.pop();\n            if (d != dist_conn[u_idx]) continue;\n            for (auto [v_idx, e_idx] : adj[u_idx]) {\n                ll cost = is_edge_on[e_idx] ? 0 : w[e_idx];\n                if (dist_conn[u_idx] + cost < dist_conn[v_idx]) {\n                    dist_conn[v_idx] = dist_conn[u_idx] + cost;\n                    prev_vertex[v_idx] = u_idx;\n                    prev_edge[v_idx] = e_idx;\n                    pq.emplace(dist_conn[v_idx], v_idx);\n                }\n            }\n        }\n\n        // evaluate all possible actions\n        Candidate best;\n        bool found = false;\n\n        // actions on active vertices - consider up to 30 candidate P values\n        for (int i = 0; i < N; ++i) {\n            if (!is_vertex_active[i]) continue;\n            // move to first uncovered resident\n            while (next_uncovered[i] < K && covered[sorted_res[i][next_uncovered[i]]])\n                ++next_uncovered[i];\n            if (next_uncovered[i] == K) continue;\n\n            int first = next_uncovered[i];\n            // Consider up to 30 candidate P values\n            for (int offset = 0; offset < 30 && first + offset < K; ++offset) {\n                int idx = first + offset;\n                int k = sorted_res[i][idx];\n                ll d2 = dist2[i][k];\n                int new_P = ceil_sqrt(d2);\n                if (new_P > 5000) continue;\n                ll new_P2 = (ll)new_P * new_P;\n                ll old_P2 = (ll)P[i] * P[i];\n\n                // count newly covered residents with d2 <= new_P2\n                int cnt = 0;\n                int last = first;\n                for (int j = first; j < K; ++j) {\n                    int res = sorted_res[i][j];\n                    if (dist2[i][res] > new_P2) break;\n                    if (!covered[res]) ++cnt;\n                    last = j + 1;\n                }\n                if (cnt == 0) continue;\n\n                ll cost_inc = new_P2 - old_P2;\n                // Use weighted efficiency: cost / (cnt^1.7)\n                double efficiency = (double)cost_inc / pow(cnt, 1.7);\n                double best_efficiency = found ? (double)best.cost / pow(best.count, 1.7) : 1e18;\n                if (efficiency < best_efficiency) {\n                    best = {0, i, new_P, cost_inc, cnt, first, last};\n                    found = true;\n                }\n            }\n        }\n\n        // actions on inactive vertices - consider up to 30 candidate P values\n        for (int i = 0; i < N; ++i) {\n            if (is_vertex_active[i]) continue;\n            if (dist_conn[i] == LLONG_MAX) continue; // should not happen\n\n            // find first uncovered resident\n            int first_idx = 0;\n            while (first_idx < K && covered[sorted_res[i][first_idx]]) ++first_idx;\n            if (first_idx == K) continue;\n\n            // Consider up to 30 candidate P values\n            for (int offset = 0; offset < 30 && first_idx + offset < K; ++offset) {\n                int idx = first_idx + offset;\n                int k = sorted_res[i][idx];\n                ll d2 = dist2[i][k];\n                int new_P = ceil_sqrt(d2);\n                if (new_P > 5000) continue;\n                ll new_P2 = (ll)new_P * new_P;\n\n                // count uncovered residents within new_P\n                int cnt = 0;\n                int last_idx = first_idx;\n                for (int j = first_idx; j < K; ++j) {\n                    int res = sorted_res[i][j];\n                    if (dist2[i][res] > new_P2) break;\n                    if (!covered[res]) ++cnt;\n                    last_idx = j + 1;\n                }\n                if (cnt == 0) continue;\n\n                ll total_cost = dist_conn[i] + new_P2;\n                // Use weighted efficiency: cost / (cnt^1.7)\n                double efficiency = (double)total_cost / pow(cnt, 1.7);\n                double best_efficiency = found ? (double)best.cost / pow(best.count, 1.7) : 1e18;\n                if (efficiency < best_efficiency) {\n                    best = {1, i, new_P, total_cost, cnt, first_idx, last_idx};\n                    found = true;\n                }\n            }\n        }\n\n        if (!found) break; // should not happen\n\n        // apply the best action\n        if (best.type == 0) { // active vertex\n            int i = best.idx;\n            P[i] = best.new_P;\n            for (int j = best.first_idx; j < best.last_idx; ++j) {\n                int res = sorted_res[i][j];\n                if (!covered[res]) {\n                    covered[res] = true;\n                    ++covered_cnt;\n                }\n            }\n            next_uncovered[i] = best.last_idx;\n        } else { // inactive vertex\n            int j = best.idx;\n            // turn on edges along the shortest path\n            int cur = j;\n            while (!is_vertex_active[cur]) {\n                int e = prev_edge[cur];\n                if (!is_edge_on[e]) is_edge_on[e] = true;\n                int prev = prev_vertex[cur];\n                is_vertex_active[cur] = true;\n                next_uncovered[cur] = 0; // newly activated, P=0 initially\n                P[cur] = 0;\n                cur = prev;\n            }\n            P[j] = best.new_P;\n            for (int idx = best.first_idx; idx < best.last_idx; ++idx) {\n                int res = sorted_res[j][idx];\n                if (!covered[res]) {\n                    covered[res] = true;\n                    ++covered_cnt;\n                }\n            }\n            next_uncovered[j] = best.last_idx;\n        }\n    }\n\n    // output\n    for (int i = 0; i < N; ++i) {\n        cout << P[i] << (i + 1 == N ? \"\\n\" : \" \");\n    }\n    for (int j = 0; j < M; ++j) {\n        cout << (is_edge_on[j] ? 1 : 0) << (j + 1 == M ? \"\\n\" : \" \");\n    }\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30; // fixed pyramid size\n\nint main() {\n    // read input\n    vector<vector<int>> a(N);\n    for (int x = 0; x < N; ++x) {\n        a[x].resize(x + 1);\n        for (int y = 0; y <= x; ++y) {\n            cin >> a[x][y];\n        }\n    }\n\n    vector<array<int, 4>> ops; // stores swaps (x1,y1,x2,y2)\n\n    // swap two adjacent balls and record the operation\n    auto do_swap = [&](int x1, int y1, int x2, int y2) {\n        swap(a[x1][y1], a[x2][y2]);\n        ops.push_back({x1, y1, x2, y2});\n    };\n\n    // sift down a value starting from (x,y) until heap property holds\n    auto sift = [&](int x, int y) {\n        while (x < N - 1) { // while not a leaf\n            int x_left = x + 1, y_left = y;      // left child\n            int x_right = x + 1, y_right = y + 1; // right child\n            // choose the child with the smaller value\n            int nx, ny;\n            if (a[x_left][y_left] <= a[x_right][y_right]) {\n                nx = x_left; ny = y_left;\n            } else {\n                nx = x_right; ny = y_right;\n            }\n            if (a[x][y] > a[nx][ny]) {\n                do_swap(x, y, nx, ny);\n                x = nx; y = ny; // continue sifting with the moved value\n            } else {\n                break;\n            }\n        }\n    };\n\n    // process rows from bottom to top\n    for (int x = N - 2; x >= 0; --x) {\n        // collect nodes in this row and sort by value descending\n        vector<pair<int, int>> nodes;\n        for (int y = 0; y <= x; ++y) {\n            nodes.emplace_back(a[x][y], y);\n        }\n        sort(nodes.begin(), nodes.end(), greater<pair<int, int>>());\n        // sift each node in that order\n        for (auto& p : nodes) {\n            sift(x, p.second);\n        }\n    }\n\n    // output\n    cout << ops.size() << '\\n';\n    for (auto& sw : ops) {\n        cout << sw[0] << ' ' << sw[1] << ' ' << sw[2] << ' ' << sw[3] << '\\n';\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int D = 9;  // Grid size is fixed at 9\nint entrance_r = 0, entrance_c = (D - 1) / 2;  // (0,4)\n\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\n\nbool obstacle[D][D] = {false};\nbool occupied[D][D] = {false};\nint container_num[D][D];       // -1 if no container\n\nint dist[D][D];                // BFS distance from entrance\nint cell_rank[D][D];           // index in the sorted order (0..M-1)\nvector<pair<int, int>> order;  // free squares sorted by (dist, row, col)\nint M;                         // number of containers\n\n// ---------- preprocessing ----------\nvoid compute_bfs_distances() {\n    for (int i = 0; i < D; ++i)\n        for (int j = 0; j < D; ++j)\n            dist[i][j] = -1;\n\n    queue<pair<int, int>> q;\n    dist[entrance_r][entrance_c] = 0;\n    q.push({entrance_r, entrance_c});\n\n    while (!q.empty()) {\n        auto [r, c] = q.front(); q.pop();\n        for (int d = 0; d < 4; ++d) {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n            if (obstacle[nr][nc]) continue;\n            if (dist[nr][nc] == -1) {\n                dist[nr][nc] = dist[r][c] + 1;\n                q.push({nr, nc});\n            }\n        }\n    }\n}\n\nvoid build_order() {\n    order.clear();\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            if (i == entrance_r && j == entrance_c) continue;\n            if (obstacle[i][j]) continue;\n            order.push_back({i, j});\n        }\n    }\n    sort(order.begin(), order.end(),\n         [](const auto& a, const auto& b) {\n             int da = dist[a.first][a.second];\n             int db = dist[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    M = order.size();\n    for (int i = 0; i < D; ++i)\n        for (int j = 0; j < D; ++j)\n            cell_rank[i][j] = -1;\n    for (int i = 0; i < M; ++i) {\n        auto [r, c] = order[i];\n        cell_rank[r][c] = i;\n    }\n}\n\n// ---------- helper for articulation test ----------\n// temporarily block (br,bc) and count reachable empty squares from entrance\nint count_reachable_without(int br, int bc, bool is_empty[D][D]) {\n    bool original = is_empty[br][bc];\n    is_empty[br][bc] = false;          // block the square\n\n    bool visited[D][D] = {false};\n    int cnt = 0;\n    queue<pair<int, int>> q;\n    q.push({entrance_r, entrance_c});\n    visited[entrance_r][entrance_c] = true;\n    ++cnt;\n\n    while (!q.empty()) {\n        auto [r, c] = q.front(); q.pop();\n        for (int d = 0; d < 4; ++d) {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n            if (!is_empty[nr][nc]) continue;\n            if (!visited[nr][nc]) {\n                visited[nr][nc] = true;\n                q.push({nr, nc});\n                ++cnt;\n            }\n        }\n    }\n\n    is_empty[br][bc] = original;       // restore\n    return cnt;\n}\n\n// Count empty neighbors for a square\nint count_empty_neighbors(int r, int c, bool is_empty[D][D]) {\n    int cnt = 0;\n    for (int d = 0; d < 4; ++d) {\n        int nr = r + dr[d], nc = c + dc[d];\n        if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n        if (is_empty[nr][nc]) cnt++;\n    }\n    return cnt;\n}\n\n// ---------- main ----------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    int input_D;  // We'll read D but ignore it since it's always 9\n    cin >> input_D >> N;\n\n    // read obstacles\n    for (int i = 0; i < N; ++i) {\n        int r, c;\n        cin >> r >> c;\n        obstacle[r][c] = true;\n    }\n\n    // preprocessing\n    compute_bfs_distances();\n    build_order();\n\n    // initialise container numbers\n    for (int i = 0; i < D; ++i)\n        for (int j = 0; j < D; ++j)\n            container_num[i][j] = -1;\n\n    // ---------- placement phase ----------\n    for (int step = 0; step < M; ++step) {\n        int t;\n        cin >> t;\n\n        // build current empty mask (entrance + all non\u2011occupied, non\u2011obstacle)\n        bool is_empty[D][D] = {false};\n        for (int i = 0; i < D; ++i)\n            for (int j = 0; j < D; ++j) {\n                if (obstacle[i][j]) is_empty[i][j] = false;\n                else if (occupied[i][j]) is_empty[i][j] = false;\n                else is_empty[i][j] = true;      // includes entrance\n            }\n\n        // collect all reachable empty squares (except entrance)\n        vector<pair<int, int>> reachable;\n        bool visited[D][D] = {false};\n        queue<pair<int, int>> q;\n        q.push({entrance_r, entrance_c});\n        visited[entrance_r][entrance_c] = true;\n\n        while (!q.empty()) {\n            auto [r, c] = q.front(); q.pop();\n            if (!(r == entrance_r && c == entrance_c))\n                reachable.push_back({r, c});\n            for (int d = 0; d < 4; ++d) {\n                int nr = r + dr[d], nc = c + dc[d];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (!is_empty[nr][nc]) continue;\n                if (!visited[nr][nc]) {\n                    visited[nr][nc] = true;\n                    q.push({nr, nc});\n                }\n            }\n        }\n\n        // among reachable squares, keep only those that are not articulation points\n        vector<pair<int, int>> safe;\n        int total_empty = reachable.size() + 1;   // +1 for entrance\n        for (auto& s : reachable) {\n            int r = s.first, c = s.second;\n            int cnt = count_reachable_without(r, c, is_empty);\n            if (cnt == total_empty - 1)          // graph stays connected\n                safe.push_back(s);\n        }\n\n        // choose a square\n        pair<int, int> chosen;\n        if (!safe.empty()) {\n            // Enhanced placement strategy: minimize |rank - t|, then maximize empty neighbors\n            int best_diff = 1e9, best_neighbors = -1, best_dist = 1e9;\n            for (auto& s : safe) {\n                int r = s.first, c = s.second;\n                int rnk = cell_rank[r][c];\n                int diff = abs(rnk - t);\n                int neighbors = count_empty_neighbors(r, c, is_empty);\n                int d = dist[r][c];\n                if (diff < best_diff || \n                   (diff == best_diff && neighbors > best_neighbors) ||\n                   (diff == best_diff && neighbors == best_neighbors && d < best_dist)) {\n                    best_diff = diff;\n                    best_neighbors = neighbors;\n                    best_dist = d;\n                    chosen = s;\n                }\n            }\n        } else {\n            // fallback: choose the reachable square with minimal |rank - t|\n            int best_diff = 1e9, best_neighbors = -1, best_dist = 1e9;\n            for (auto& s : reachable) {\n                int r = s.first, c = s.second;\n                int rnk = cell_rank[r][c];\n                int diff = abs(rnk - t);\n                int neighbors = count_empty_neighbors(r, c, is_empty);\n                int d = dist[r][c];\n                if (diff < best_diff || \n                   (diff == best_diff && neighbors > best_neighbors) ||\n                   (diff == best_diff && neighbors == best_neighbors && d < best_dist)) {\n                    best_diff = diff;\n                    best_neighbors = neighbors;\n                    best_dist = d;\n                    chosen = s;\n                }\n            }\n        }\n\n        // output placement\n        cout << chosen.first << \" \" << chosen.second << endl;\n\n        // update state\n        occupied[chosen.first][chosen.second] = true;\n        container_num[chosen.first][chosen.second] = t;\n    }\n\n    // ---------- retrieval phase ----------\n    int remaining = M;\n    while (remaining > 0) {\n        // rebuild empty mask\n        bool is_empty[D][D] = {false};\n        for (int i = 0; i < D; ++i)\n            for (int j = 0; j < D; ++j) {\n                if (obstacle[i][j]) is_empty[i][j] = false;\n                else if (occupied[i][j]) is_empty[i][j] = false;\n                else is_empty[i][j] = true;\n            }\n\n        // find all containers adjacent to an empty square\n        vector<pair<int, int>> accessible;\n        for (int i = 0; i < D; ++i) {\n            for (int j = 0; j < D; ++j) {\n                if (!occupied[i][j]) continue;\n                bool adj = false;\n                for (int d = 0; d < 4; ++d) {\n                    int ni = i + dr[d], nj = j + dc[d];\n                    if (ni < 0 || ni >= D || nj < 0 || nj >= D) continue;\n                    if (is_empty[ni][nj]) {\n                        adj = true;\n                        break;\n                    }\n                }\n                if (adj) accessible.push_back({i, j});\n            }\n        }\n\n        // Original retrieval: choose the container with the smallest number,\n        // breaking ties by choosing the one farthest from entrance, then by row and column\n        pair<int, int> best = accessible[0];\n        int best_num = container_num[best.first][best.second];\n        int best_dist = dist[best.first][best.second];\n        for (auto& p : accessible) {\n            int num = container_num[p.first][p.second];\n            int d = dist[p.first][p.second];\n            if (num < best_num) {\n                best_num = num;\n                best_dist = d;\n                best = p;\n            } else if (num == best_num) {\n                if (d > best_dist) {\n                    best_dist = d;\n                    best = p;\n                } else if (d == best_dist) {\n                    // Break tie by row then column\n                    if (p.first < best.first || \n                       (p.first == best.first && p.second < best.second)) {\n                        best = p;\n                    }\n                }\n            }\n        }\n\n        // output retrieval\n        cout << best.first << \" \" << best.second << endl;\n\n        // remove it\n        occupied[best.first][best.second] = false;\n        container_num[best.first][best.second] = -1;\n        --remaining;\n    }\n\n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <utility>\n#include <algorithm>\n#include <random>\n#include <cstring>\nusing namespace std;\n\nconst int MAXN = 50;\nconst int MAXM = 100;\n\nint n, m;\nint cur[MAXN][MAXN];\nint colorCount[MAXM+1] = {0};          // 0..100\nint edgeCount[MAXM+1][MAXM+1] = {0};   // only upper triangular used\nbool required[MAXM+1][MAXM+1] = {false};\nbool allowed[MAXM+1] = {false};        // colors that may touch 0\n\nconst int dx[4] = {1, -1, 0, 0};\nconst int dy[4] = {0, 0, 1, -1};\n\n// For ordering heuristics\nint orig_same_cnt[MAXN][MAXN];\nint boundary_side_cnt[MAXN][MAXN];\nint combined_score[MAXN][MAXN];\nint diff_neighbor_cnt[MAXN][MAXN];\nint allowed_neighbor_cnt[MAXN][MAXN];\n\n// Check if we can safely recolor (i,j) to 0\nbool isRemovable(int i, int j) {\n    int c = cur[i][j];\n    if (c == 0) return false;\n    if (!allowed[c]) return false;\n    if (colorCount[c] <= 1) return false;\n\n    int cnt[MAXM+1] = {0};   // count of neighbor colors (0..m)\n    bool adj_to_0 = false;\n    int same_color_neighbors = 0;\n\n    // examine four neighbours (outside counts as color 0)\n    for (int d = 0; d < 4; ++d) {\n        int ni = i + dx[d], nj = j + dy[d];\n        int col;\n        if (ni >= 0 && ni < n && nj >= 0 && nj < n)\n            col = cur[ni][nj];\n        else\n            col = 0;   // outside\n        cnt[col]++;\n        if (col == 0) adj_to_0 = true;\n        else if (!allowed[col]) return false;   // would create forbidden 0\u2013col adjacency\n        if (col == c) same_color_neighbors++;\n    }\n    if (!adj_to_0) return false;\n\n    // Edge count constraints\n    for (int d = 0; d <= m; ++d) {\n        if (cnt[d] == 0 || d == c) continue;\n        if (d == 0) {\n            // need at least one edge between c and 0 after removal\n            if (edgeCount[0][c] - cnt[0] < 1) return false;\n        } else {\n            int a = min(c, d), b = max(c, d);\n            if (required[a][b] && edgeCount[a][b] - cnt[d] < 1) return false;\n        }\n    }\n\n    // Connectivity of color c after removal\n    if (same_color_neighbors == 0) return false;   // should not happen\n    if (same_color_neighbors == 1) return true;    // leaf \u2013 safe\n\n    // BFS on color c, excluding (i,j)\n    int start_i = -1, start_j = -1;\n    for (int d = 0; d < 4; ++d) {\n        int ni = i + dx[d], nj = j + dy[d];\n        if (ni >= 0 && ni < n && nj >= 0 && nj < n && cur[ni][nj] == c) {\n            start_i = ni; start_j = nj; break;\n        }\n    }\n    if (start_i == -1) return false;   // no neighbour of same colour \u2013 impossible\n\n    bool visited[MAXN][MAXN] = {false};\n    queue<pair<int,int>> q;\n    visited[start_i][start_j] = true;\n    q.push({start_i, start_j});\n    int count = 0;\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        count++;\n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (nx >= 0 && nx < n && ny >= 0 && ny < n && !visited[nx][ny] &&\n                cur[nx][ny] == c && !(nx == i && ny == j)) {\n                visited[nx][ny] = true;\n                q.push({nx, ny});\n            }\n        }\n    }\n    return (count == colorCount[c] - 1);\n}\n\n// Actually recolor (i,j) from its colour c to 0\nvoid removeCell(int i, int j) {\n    int c = cur[i][j];\n    // Update edge counts for all incident edges\n    for (int d = 0; d < 4; ++d) {\n        int ni = i + dx[d], nj = j + dy[d];\n        int col;\n        if (ni >= 0 && ni < n && nj >= 0 && nj < n)\n            col = cur[ni][nj];\n        else\n            col = 0;   // outside\n        if (col == c) continue;   // no edge between same colours\n        // Remove edge c\u2013col\n        if (col == 0) {\n            edgeCount[0][c]--;\n        } else {\n            int a = min(c, col), b = max(c, col);\n            edgeCount[a][b]--;\n        }\n        // After recoloring, add edge 0\u2013col (if col != 0)\n        if (col != 0) {\n            edgeCount[0][col]++;\n        }\n    }\n    // Perform the recolor\n    cur[i][j] = 0;\n    colorCount[c]--;\n    colorCount[0]++;\n}\n\n// Compute colorCount and edgeCount from current grid\nvoid computeCounts() {\n    memset(colorCount, 0, sizeof(colorCount));\n    memset(edgeCount, 0, sizeof(edgeCount));\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c = cur[i][j];\n            colorCount[c]++;\n            // down\n            if (i+1 < n) {\n                int d = cur[i+1][j];\n                if (c != d) {\n                    int a = min(c,d), b = max(c,d);\n                    edgeCount[a][b]++;\n                }\n            }\n            // right\n            if (j+1 < n) {\n                int d = cur[i][j+1];\n                if (c != d) {\n                    int a = min(c,d), b = max(c,d);\n                    edgeCount[a][b]++;\n                }\n            }\n            // outside sides\n            if (i == 0) edgeCount[0][c]++;\n            if (i == n-1) edgeCount[0][c]++;\n            if (j == 0) edgeCount[0][c]++;\n            if (j == n-1) edgeCount[0][c]++;\n        }\n    }\n}\n\n// Perform erosion with given order_type and seed\n// order_type: 0=row-major, 1=col-major, 2=dist ascending, 3=dist descending,\n//             4=same-color neighbors ascending, 5=same-color neighbors descending,\n//             6=boundary side count descending, 7=boundary side count ascending,\n//             8=combined score descending, 9=combined score ascending,\n//             10=diff neighbor count descending, 11=diff neighbor count ascending,\n//             12=allowed neighbor count descending, 13=allowed neighbor count ascending,\n//             -1=random shuffle\nint erosion(int order_type, int seed) {\n    vector<pair<int,int>> cells;\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cells.emplace_back(i, j);\n        }\n    }\n\n    // For deterministic orders, sort once\n    if (order_type == 0) { // row-major\n        sort(cells.begin(), cells.end(), [](const auto& a, const auto& b) {\n            if (a.first != b.first) return a.first < b.first;\n            return a.second < b.second;\n        });\n    } else if (order_type == 1) { // column-major\n        sort(cells.begin(), cells.end(), [](const auto& a, const auto& b) {\n            if (a.second != b.second) return a.second < b.second;\n            return a.first < b.first;\n        });\n    } else if (order_type == 2) { // distance ascending\n        sort(cells.begin(), cells.end(), [](const auto& a, const auto& b) {\n            int da = min({a.first, n-1-a.first, a.second, n-1-a.second});\n            int db = min({b.first, n-1-b.first, b.second, n-1-b.second});\n            return da < db;\n        });\n    } else if (order_type == 3) { // distance descending\n        sort(cells.begin(), cells.end(), [](const auto& a, const auto& b) {\n            int da = min({a.first, n-1-a.first, a.second, n-1-a.second});\n            int db = min({b.first, n-1-b.first, b.second, n-1-b.second});\n            return da > db;\n        });\n    } else if (order_type == 4) { // same-color neighbors ascending\n        sort(cells.begin(), cells.end(), [](const auto& a, const auto& b) {\n            return orig_same_cnt[a.first][a.second] < orig_same_cnt[b.first][b.second];\n        });\n    } else if (order_type == 5) { // same-color neighbors descending\n        sort(cells.begin(), cells.end(), [](const auto& a, const auto& b) {\n            return orig_same_cnt[a.first][a.second] > orig_same_cnt[b.first][b.second];\n        });\n    } else if (order_type == 6) { // boundary side count descending\n        sort(cells.begin(), cells.end(), [](const auto& a, const auto& b) {\n            return boundary_side_cnt[a.first][a.second] > boundary_side_cnt[b.first][b.second];\n        });\n    } else if (order_type == 7) { // boundary side count ascending\n        sort(cells.begin(), cells.end(), [](const auto& a, const auto& b) {\n            return boundary_side_cnt[a.first][a.second] < boundary_side_cnt[b.first][b.second];\n        });\n    } else if (order_type == 8) { // combined score descending\n        sort(cells.begin(), cells.end(), [](const auto& a, const auto& b) {\n            return combined_score[a.first][a.second] > combined_score[b.first][b.second];\n        });\n    } else if (order_type == 9) { // combined score ascending\n        sort(cells.begin(), cells.end(), [](const auto& a, const auto& b) {\n            return combined_score[a.first][a.second] < combined_score[b.first][b.second];\n        });\n    } else if (order_type == 10) { // diff neighbor count descending\n        sort(cells.begin(), cells.end(), [](const auto& a, const auto& b) {\n            return diff_neighbor_cnt[a.first][a.second] > diff_neighbor_cnt[b.first][b.second];\n        });\n    } else if (order_type == 11) { // diff neighbor count ascending\n        sort(cells.begin(), cells.end(), [](const auto& a, const auto& b) {\n            return diff_neighbor_cnt[a.first][a.second] < diff_neighbor_cnt[b.first][b.second];\n        });\n    } else if (order_type == 12) { // allowed neighbor count descending\n        sort(cells.begin(), cells.end(), [](const auto& a, const auto& b) {\n            return allowed_neighbor_cnt[a.first][a.second] > allowed_neighbor_cnt[b.first][b.second];\n        });\n    } else if (order_type == 13) { // allowed neighbor count ascending\n        sort(cells.begin(), cells.end(), [](const auto& a, const auto& b) {\n            return allowed_neighbor_cnt[a.first][a.second] < allowed_neighbor_cnt[b.first][b.second];\n        });\n    }\n    // For random order, we will shuffle each pass\n\n    mt19937 rng(seed);\n    bool changed;\n    do {\n        if (order_type == -1) {\n            shuffle(cells.begin(), cells.end(), rng);\n        }\n        changed = false;\n        for (auto [i, j] : cells) {\n            if (cur[i][j] == 0) continue;\n            if (isRemovable(i, j)) {\n                removeCell(i, j);\n                changed = true;\n            }\n        }\n    } while (changed);\n    return colorCount[0];\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Read original map\n    int orig_cur[MAXN][MAXN];\n    cin >> n >> m;\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cin >> orig_cur[i][j];\n        }\n    }\n\n    // Compute allowed and required from original map (they remain constant)\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (i == 0 || i == n-1 || j == 0 || j == n-1)\n                allowed[orig_cur[i][j]] = true;\n        }\n    }\n    // required for 0-c from boundary\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (i == 0 || i == n-1 || j == 0 || j == n-1) {\n                int c = orig_cur[i][j];\n                required[0][c] = true;\n            }\n        }\n    }\n    // required for c-d from internal edges\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c = orig_cur[i][j];\n            if (i+1 < n) {\n                int d = orig_cur[i+1][j];\n                if (c != d) {\n                    int a = min(c,d), b = max(c,d);\n                    required[a][b] = true;\n                }\n            }\n            if (j+1 < n) {\n                int d = orig_cur[i][j+1];\n                if (c != d) {\n                    int a = min(c,d), b = max(c,d);\n                    required[a][b] = true;\n                }\n            }\n        }\n    }\n\n    // Compute initial heuristics\n    memset(orig_same_cnt, 0, sizeof(orig_same_cnt));\n    memset(boundary_side_cnt, 0, sizeof(boundary_side_cnt));\n    memset(combined_score, 0, sizeof(combined_score));\n    memset(diff_neighbor_cnt, 0, sizeof(diff_neighbor_cnt));\n    memset(allowed_neighbor_cnt, 0, sizeof(allowed_neighbor_cnt));\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c = orig_cur[i][j];\n            // same-color neighbors, diff neighbors, allowed neighbors\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + dx[d], nj = j + dy[d];\n                int col;\n                if (ni >= 0 && ni < n && nj >= 0 && nj < n) {\n                    col = orig_cur[ni][nj];\n                } else {\n                    col = 0; // outside\n                }\n                if (col == c) {\n                    orig_same_cnt[i][j]++;\n                } else {\n                    diff_neighbor_cnt[i][j]++;\n                }\n                // allowed neighbor: if col == 0 or allowed[col] is true\n                if (col == 0 || allowed[col]) {\n                    allowed_neighbor_cnt[i][j]++;\n                }\n            }\n            // boundary sides\n            if (i == 0) boundary_side_cnt[i][j]++;\n            if (i == n-1) boundary_side_cnt[i][j]++;\n            if (j == 0) boundary_side_cnt[i][j]++;\n            if (j == n-1) boundary_side_cnt[i][j]++;\n            // combined score\n            combined_score[i][j] = boundary_side_cnt[i][j] * orig_same_cnt[i][j];\n        }\n    }\n\n    int best_E = -1;\n    int best_cur[MAXN][MAXN];\n    vector<pair<int, int>> attempts = {\n        {0, 0},      // row-major\n        {1, 0},      // column-major\n        {2, 0},      // distance ascending\n        {3, 0},      // distance descending\n        {4, 0},      // same-color neighbors ascending\n        {5, 0},      // same-color neighbors descending\n        {6, 0},      // boundary side count descending\n        {7, 0},      // boundary side count ascending\n        {8, 0},      // combined score descending\n        {9, 0},      // combined score ascending\n        {10, 0},     // diff neighbor count descending\n        {11, 0},     // diff neighbor count ascending\n        {12, 0},     // allowed neighbor count descending\n        {13, 0},     // allowed neighbor count ascending\n        {-1, 12345}, // random seed 12345\n        {-1, 67890}, // random seed 67890\n        {-1, 11111}, // random seed 11111\n        {-1, 22222}, // random seed 22222\n        {-1, 33333}, // random seed 33333\n        {-1, 44444}, // random seed 44444\n        {-1, 55555}, // random seed 55555\n        {-1, 66666}, // random seed 66666\n        {-1, 77777}, // random seed 77777\n        {-1, 88888}, // random seed 88888\n        {-1, 99999}, // random seed 99999\n        {-1, 123456}, // random seed 123456\n        {-1, 13579}, // random seed 13579\n        {-1, 24680}, // random seed 24680\n        {-1, 11223}, // random seed 11223\n        {-1, 33445}, // random seed 33445\n        {-1, 55667}, // random seed 55667\n        {-1, 77889}, // random seed 77889\n        {-1, 99001}, // random seed 99001\n        {-1, 111111}, // random seed 111111\n        {-1, 222222}, // random seed 222222\n        {-1, 333333}, // random seed 333333\n        {-1, 444444}, // random seed 444444\n        {-1, 555555}, // random seed 555555\n        {-1, 666777}, // random seed 666777\n        {-1, 888999}, // random seed 888999\n        {-1, 123123}, // random seed 123123\n        {-1, 456456}, // random seed 456456\n        {-1, 789789}, // random seed 789789\n        {-1, 111222}, // random seed 111222\n        {-1, 333444}, // random seed 333444\n        {-1, 555666}, // random seed 555666\n        {-1, 1234567}, // random seed 1234567\n        {-1, 7654321}, // random seed 7654321\n        {-1, 1111111}, // random seed 1111111\n        {-1, 2222222}, // random seed 2222222\n        {-1, 3333333}, // random seed 3333333\n        {-1, 4444444}, // random seed 4444444\n        {-1, 5555555}, // random seed 5555555\n        {-1, 6666666}, // random seed 6666666\n        {-1, 7777777}, // random seed 7777777\n        {-1, 8888888}, // random seed 8888888\n        {-1, 9999999}, // random seed 9999999\n        {-1, 1010101}, // random seed 1010101\n        {-1, 1212121}, // random seed 1212121\n        {-1, 2323232}, // random seed 2323232\n        {-1, 3434343}, // random seed 3434343\n        {-1, 4545454}, // random seed 4545454\n        {-1, 5656565}, // random seed 5656565\n        {-1, 6767676}, // random seed 6767676\n        {-1, 7878787}, // random seed 7878787\n        {-1, 8989898}, // random seed 8989898\n        {-1, 9090909}, // random seed 9090909\n        {-1, 10101010} // random seed 10101010\n    };\n\n    for (auto [order_type, seed] : attempts) {\n        // Copy original grid to cur\n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                cur[i][j] = orig_cur[i][j];\n            }\n        }\n        computeCounts();\n        int E = erosion(order_type, seed);\n        if (E > best_E) {\n            best_E = E;\n            for (int i = 0; i < n; ++i) {\n                for (int j = 0; j < n; ++j) {\n                    best_cur[i][j] = cur[i][j];\n                }\n            }\n        }\n    }\n\n    // Output the best map\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (j) cout << ' ';\n            cout << best_cur[i][j];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, D, Q;\nvector<vector<int>> cmp;   // -2 unknown, -1: <, 0: =, 1: >\nint queries_used = 0;\n\n// Compare items i and j\nint compare_items(int i, int j) {\n    if (i == j) return 0;\n    if (cmp[i][j] != -2) return cmp[i][j];\n    cout << \"1 1 \" << i << \" \" << j << endl;\n    cout.flush();\n    string res;\n    cin >> res;\n    ++queries_used;\n    int ans;\n    if (res == \"<\") ans = -1;\n    else if (res == \">\") ans = 1;\n    else ans = 0;\n    cmp[i][j] = ans;\n    cmp[j][i] = -ans;\n    return ans;\n}\n\n// Compare two groups by total weight\nint compare_groups(const vector<int>& A, const vector<int>& B) {\n    if (A.empty() || B.empty()) return 0;\n    if (queries_used >= Q) return 0; // Fallback if no queries left\n    cout << A.size() << \" \" << B.size();\n    for (int x : A) cout << \" \" << x;\n    for (int x : B) cout << \" \" << x;\n    cout << endl;\n    cout.flush();\n    string res;\n    cin >> res;\n    ++queries_used;\n    if (res == \"<\") return -1;\n    else if (res == \">\") return 1;\n    else return 0;\n}\n\n// Merge sort for items\nvoid merge_sort(vector<int>& arr, int left, int right) {\n    if (left >= right || queries_used >= Q) return;\n    int mid = (left + right) / 2;\n    merge_sort(arr, left, mid);\n    merge_sort(arr, mid+1, right);\n    \n    vector<int> temp;\n    int i = left, j = mid+1;\n    while (i <= mid && j <= right && queries_used < Q) {\n        int res = compare_items(arr[i], arr[j]);\n        if (res <= 0) {\n            temp.push_back(arr[i++]);\n        } else {\n            temp.push_back(arr[j++]);\n        }\n    }\n    while (i <= mid) temp.push_back(arr[i++]);\n    while (j <= right) temp.push_back(arr[j++]);\n    \n    for (int k = 0; k < (int)temp.size(); ++k) {\n        arr[left + k] = temp[k];\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cout.tie(nullptr);\n\n    cin >> N >> D >> Q;\n    cmp.assign(N, vector<int>(N, -2));\n\n    // Estimate assignment cost: N * log2(D) comparisons\n    int logD = 0;\n    for (int t = D; t > 1; t >>= 1) ++logD;\n    logD = max(1, logD); // Ensure at least 1\n    int assign_budget = N * (logD + 1); // Conservative estimate\n    \n    int sort_budget = Q;\n    bool use_group_comparisons = (Q >= assign_budget);\n    if (use_group_comparisons) {\n        sort_budget = max(0, Q - assign_budget);\n    }\n\n    // Create item indices and sort using merge sort\n    vector<int> items(N);\n    iota(items.begin(), items.end(), 0);\n    \n    // Shuffle for better average-case performance\n    mt19937 rng(123456);\n    shuffle(items.begin(), items.end(), rng);\n    \n    // Perform merge sort with budget\n    merge_sort(items, 0, N-1);\n    \n    // If we didn't finish sorting due to budget, do insertion sort on remaining\n    if (queries_used < sort_budget) {\n        // Partial insertion sort to improve order\n        for (int i = 1; i < N && queries_used < sort_budget; ++i) {\n            int key = items[i];\n            int j = i - 1;\n            while (j >= 0 && queries_used < sort_budget) {\n                int res = compare_items(key, items[j]);\n                if (res < 0) {\n                    items[j+1] = items[j];\n                    --j;\n                } else break;\n            }\n            items[j+1] = key;\n        }\n    }\n\n    // Now items are sorted in ascending order (lightest to heaviest)\n    // We'll assign from heaviest to lightest\n    \n    vector<vector<int>> groups(D);\n    \n    // Seed groups with D heaviest items\n    for (int i = 0; i < D && i < N; ++i) {\n        int item = items[N-1-i]; // heaviest first\n        groups[i].push_back(item);\n    }\n\n    // Prepare items to assign (remaining heaviest to lightest)\n    vector<int> to_assign;\n    for (int i = D; i < N; ++i) {\n        to_assign.push_back(items[N-1-i]);\n    }\n\n    int assigned_idx = 0;\n    if (use_group_comparisons && queries_used < Q) {\n        // Use heap for efficient group selection\n        auto cmp_groups = [&](int i, int j) {\n            return compare_groups(groups[i], groups[j]) > 0; // Min-heap by weight\n        };\n        priority_queue<int, vector<int>, decltype(cmp_groups)> pq(cmp_groups);\n        \n        for (int i = 0; i < D; ++i) pq.push(i);\n        \n        while (assigned_idx < (int)to_assign.size() && queries_used < Q) {\n            // Estimate cost: 2*logD comparisons for pop+push\n            if (queries_used + 2*logD > Q) break;\n            \n            int g = pq.top(); pq.pop();\n            groups[g].push_back(to_assign[assigned_idx++]);\n            pq.push(g);\n        }\n    }\n\n    // Assign any remaining items without comparisons (round-robin)\n    for (; assigned_idx < (int)to_assign.size(); ++assigned_idx) {\n        int g = assigned_idx % D;\n        groups[g].push_back(to_assign[assigned_idx]);\n    }\n\n    // Output assignment\n    vector<int> ans(N);\n    for (int g = 0; g < D; ++g) {\n        for (int item : groups[g]) {\n            ans[item] = g;\n        }\n    }\n\n    // Dummy queries if needed\n    while (queries_used < Q) {\n        cout << \"1 1 0 1\" << endl;\n        cout.flush();\n        string dummy;\n        cin >> dummy;\n        ++queries_used;\n    }\n\n    // Output final division\n    for (int i = 0; i < N; ++i) {\n        cout << ans[i];\n        if (i < N-1) cout << \" \";\n    }\n    cout << endl;\n    cout.flush();\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    int n, m;\n    cin >> n >> m;\n    int k = n / m;\n    vector<vector<int>> stacks(m);\n    for (int i = 0; i < m; ++i) {\n        stacks[i].resize(k);\n        for (int j = 0; j < k; ++j) {\n            cin >> stacks[i][j];\n        }\n    }\n\n    vector<pair<int, int>> ops;\n\n    auto target_stack = [&](int v) {\n        return (v - 1) / k;\n    };\n\n    for (int v = 1; v <= n; ++v) {\n        int cur = -1, pos = -1;\n        for (int i = 0; i < m; ++i) {\n            for (int j = 0; j < (int)stacks[i].size(); ++j) {\n                if (stacks[i][j] == v) {\n                    cur = i;\n                    pos = j;\n                    break;\n                }\n            }\n            if (cur != -1) break;\n        }\n\n        if (pos == (int)stacks[cur].size() - 1) {\n            ops.emplace_back(v, 0);\n            stacks[cur].pop_back();\n            continue;\n        }\n\n        int w = stacks[cur][pos + 1];\n        \n        vector<int> block(stacks[cur].begin() + pos + 1, stacks[cur].end());\n        stacks[cur].erase(stacks[cur].begin() + pos + 1, stacks[cur].end());\n        \n        int max_in_block = *max_element(block.begin(), block.end());\n        int min_in_block = *min_element(block.begin(), block.end());\n        \n        vector<int> target_counts(m, 0);\n        int all_same_target = -1;\n        bool all_same = true;\n        for (int box : block) {\n            int t = target_stack(box);\n            target_counts[t]++;\n            if (all_same_target == -1) all_same_target = t;\n            else if (all_same_target != t) all_same = false;\n        }\n        \n        int best_target = -1;\n        int max_count = 0;\n        for (int i = 0; i < m; ++i) {\n            if (target_counts[i] > max_count) {\n                max_count = target_counts[i];\n                best_target = i;\n            } else if (target_counts[i] == max_count && best_target != -1) {\n                int top_best = stacks[best_target].empty() ? -1 : stacks[best_target].back();\n                int top_i = stacks[i].empty() ? -1 : stacks[i].back();\n                if (top_i > top_best) {\n                    best_target = i;\n                }\n            }\n        }\n        \n        bool block_sorted = true;\n        for (int i = 1; i < (int)block.size(); ++i) {\n            if (block[i] > block[i-1]) {\n                block_sorted = false;\n                break;\n            }\n        }\n        \n        int dest = -1;\n        double best_score = -1e9;\n        \n        for (int d = 0; d < m; ++d) {\n            if (d == cur) continue;\n            \n            double score = 0.0;\n            int top_d = stacks[d].empty() ? -1 : stacks[d].back();\n            \n            // Empty stack bonus\n            if (stacks[d].empty()) {\n                score += 115.0;\n            }\n            \n            // Target stack match\n            if (d == best_target) {\n                score += 85.0 * max_count / block.size();\n            }\n            \n            // All boxes in same target\n            if (all_same && d == all_same_target) {\n                score += 60.0;\n            }\n            \n            // Inversion avoidance\n            if (top_d > max_in_block) {\n                score += 105.0;\n                score += 25.0 * (top_d - max_in_block) / 200.0;\n            } else if (top_d > min_in_block) {\n                score += 22.0 * (top_d - min_in_block) / (max_in_block - min_in_block + 1);\n            }\n            \n            // Stack height penalty\n            score -= 9.0 * stacks[d].size();\n            \n            // Block order bonus\n            if (block_sorted && top_d > max_in_block) {\n                score += 48.0;\n            }\n            \n            // Lookahead for next 6 boxes with linear decay\n            vector<vector<int>> temp_stacks = stacks;\n            temp_stacks[d].insert(temp_stacks[d].end(), block.begin(), block.end());\n            \n            for (int l = 1; l <= 6; ++l) {\n                if (v + l > n) break;\n                double weight = 38.0 / l;\n                for (int i = 0; i < m; ++i) {\n                    for (int j = 0; j < (int)temp_stacks[i].size(); ++j) {\n                        if (temp_stacks[i][j] == v + l) {\n                            int boxes_above = temp_stacks[i].size() - j - 1;\n                            score -= weight * boxes_above;\n                            break;\n                        }\n                    }\n                }\n            }\n            \n            // Bonus for blocks in destination's range\n            int expected_min = d * k + 1;\n            int expected_max = (d + 1) * k;\n            int in_range = 0;\n            for (int box : block) {\n                if (box >= expected_min && box <= expected_max) in_range++;\n            }\n            if (in_range == (int)block.size()) {\n                score += 38.0;\n            } else if (in_range > 0) {\n                score += 14.0 * in_range / block.size();\n            }\n            \n            if (score > best_score) {\n                best_score = score;\n                dest = d;\n            }\n        }\n        \n        if (dest == -1) {\n            for (int i = 0; i < m; ++i) {\n                if (i != cur) {\n                    dest = i;\n                    break;\n                }\n            }\n        }\n\n        ops.emplace_back(w, dest + 1);\n        stacks[dest].insert(stacks[dest].end(), block.begin(), block.end());\n\n        ops.emplace_back(v, 0);\n        stacks[cur].pop_back();\n    }\n\n    for (auto& p : ops) {\n        cout << p.first << \" \" << p.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAX_MOVES = 100000;\n\n// directions: up, down, left, right\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\nconst char move_char[] = {'U', 'D', 'L', 'R'};\nconst char opposite_char[] = {'D', 'U', 'R', 'L'};\n\nint N;\nvector<string> h, v;\nvector<vector<int>> d;\n\n// adjacency list: for each cell (i,j) list of (ni,nj,move_char)\nvector<vector<vector<tuple<int,int,char>>>> adj;\n\n// for coverage\nvector<vector<bool>> visited;\n\n// distances to (0,0)\nvector<vector<int>> dist0;\n\nchar get_opposite(char c) {\n    for (int k = 0; k < 4; ++k)\n        if (move_char[k] == c) return opposite_char[k];\n    return '?';\n}\n\nvoid build_graph() {\n    adj.assign(N, vector<vector<tuple<int,int,char>>>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            // down\n            if (i+1 < N && h[i][j] == '0')\n                adj[i][j].emplace_back(i+1, j, 'D');\n            // up\n            if (i-1 >= 0 && h[i-1][j] == '0')\n                adj[i][j].emplace_back(i-1, j, 'U');\n            // right\n            if (j+1 < N && v[i][j] == '0')\n                adj[i][j].emplace_back(i, j+1, 'R');\n            // left\n            if (j-1 >= 0 && v[i][j-1] == '0')\n                adj[i][j].emplace_back(i, j-1, 'L');\n        }\n    }\n}\n\nvoid compute_dist0() {\n    dist0.assign(N, vector<int>(N, -1));\n    queue<pair<int,int>> q;\n    q.emplace(0, 0);\n    dist0[0][0] = 0;\n    while (!q.empty()) {\n        auto [i,j] = q.front(); q.pop();\n        for (auto [ni, nj, move] : adj[i][j]) {\n            if (dist0[ni][nj] == -1) {\n                dist0[ni][nj] = dist0[i][j] + 1;\n                q.emplace(ni, nj);\n            }\n        }\n    }\n}\n\n// returns the base route (greedy DFS) and updates last_visit, current position, and time\nstring generate_base_route(vector<vector<int>>& last_visit, int& t, pair<int,int>& cur) {\n    visited.assign(N, vector<bool>(N, false));\n    string route;\n    stack<pair<int,int>> st;\n    stack<char> move_stack;\n    st.emplace(0, 0);\n    visited[0][0] = true;\n    last_visit[0][0] = 0;\n    t = 0;\n    cur = {0,0};\n\n    while (!st.empty()) {\n        auto [i,j] = st.top();\n        // find the unvisited neighbor with highest d / (dist0+1)\n        double best_score = -1.0;\n        int best_d = -1;\n        char best_move = '?';\n        int best_ni = -1, best_nj = -1;\n        for (auto [ni, nj, move] : adj[i][j]) {\n            if (!visited[ni][nj]) {\n                double score = (double)d[ni][nj] / (dist0[ni][nj] + 1);\n                if (score > best_score || \n                    (score == best_score && d[ni][nj] > best_d) ||\n                    (score == best_score && d[ni][nj] == best_d && dist0[ni][nj] < dist0[best_ni][best_nj])) {\n                    best_score = score;\n                    best_d = d[ni][nj];\n                    best_move = move;\n                    best_ni = ni;\n                    best_nj = nj;\n                }\n            }\n        }\n        if (best_move != '?') {\n            // move to the best neighbor\n            visited[best_ni][best_nj] = true;\n            route += best_move;\n            ++t;\n            last_visit[best_ni][best_nj] = t;\n            cur = {best_ni, best_nj};\n            move_stack.push(best_move);\n            st.emplace(best_ni, best_nj);\n        } else {\n            // backtrack\n            st.pop();\n            if (!move_stack.empty()) {\n                char move_back = get_opposite(move_stack.top());\n                move_stack.pop();\n                route += move_back;\n                ++t;\n                auto [pi, pj] = st.top();\n                last_visit[pi][pj] = t;\n                cur = {pi, pj};\n            }\n        }\n    }\n    return route;\n}\n\n// greedy phase: returns the additional moves\nstring greedy_phase(pair<int,int> cur, int t, vector<vector<int>>& last_visit) {\n    string extra;\n    while (t < MAX_MOVES) {\n        int remaining = MAX_MOVES - t;\n        int ci = cur.first, cj = cur.second;\n        // if we must go directly to (0,0)\n        if (dist0[ci][cj] == remaining) {\n            // find the neighbor with dist0 = remaining-1 that has the highest dirtiness\n            int best_dirt = -1;\n            int best_d = -1;\n            char best_move = '?';\n            int best_ni = -1, best_nj = -1;\n            for (auto [ni, nj, move] : adj[ci][cj]) {\n                if (dist0[ni][nj] == remaining - 1) {\n                    int dirt = (t - last_visit[ni][nj]) * d[ni][nj];\n                    if (dirt > best_dirt || \n                        (dirt == best_dirt && d[ni][nj] > best_d) ||\n                        (dirt == best_dirt && d[ni][nj] == best_d && dist0[ni][nj] < dist0[best_ni][best_nj])) {\n                        best_dirt = dirt;\n                        best_d = d[ni][nj];\n                        best_move = move;\n                        best_ni = ni;\n                        best_nj = nj;\n                    }\n                }\n            }\n            if (best_move != '?') {\n                extra += best_move;\n                ++t;\n                last_visit[best_ni][best_nj] = t;\n                cur = {best_ni, best_nj};\n            }\n        } else {\n            // try two-step lookahead if we have at least 2 moves left\n            if (remaining >= 2) {\n                int best_total = -1;\n                char best_move1 = '?', best_move2 = '?';\n                int best_n1i = -1, best_n1j = -1;\n                int best_n2i = -1, best_n2j = -1;\n                for (auto [n1i, n1j, move1] : adj[ci][cj]) {\n                    if (dist0[n1i][n1j] <= remaining - 1) {\n                        int dirt1 = (t - last_visit[n1i][n1j]) * d[n1i][n1j];\n                        // for each possible second move from n1\n                        for (auto [n2i, n2j, move2] : adj[n1i][n1j]) {\n                            if (dist0[n2i][n2j] <= remaining - 2) {\n                                int dirt2 = (t + 1 - last_visit[n2i][n2j]) * d[n2i][n2j];\n                                int total = dirt1 + dirt2;\n                                if (total > best_total) {\n                                    best_total = total;\n                                    best_move1 = move1;\n                                    best_move2 = move2;\n                                    best_n1i = n1i;\n                                    best_n1j = n1j;\n                                    best_n2i = n2i;\n                                    best_n2j = n2j;\n                                }\n                            }\n                        }\n                    }\n                }\n                if (best_move1 != '?') {\n                    // execute the first move\n                    extra += best_move1;\n                    ++t;\n                    last_visit[best_n1i][best_n1j] = t;\n                    cur = {best_n1i, best_n1j};\n                    // execute the second move\n                    extra += best_move2;\n                    ++t;\n                    last_visit[best_n2i][best_n2j] = t;\n                    cur = {best_n2i, best_n2j};\n                    continue;\n                }\n            }\n            // fallback to one-step greedy using scoring function\n            double best_score = -1.0;\n            int best_dirt = -1;\n            char best_move = '?';\n            int best_ni = -1, best_nj = -1;\n            for (auto [ni, nj, move] : adj[ci][cj]) {\n                if (dist0[ni][nj] <= remaining - 1) {\n                    int dirt = (t - last_visit[ni][nj]) * d[ni][nj];\n                    double score = (double)dirt / (dist0[ni][nj] + 1);\n                    if (score > best_score || \n                        (score == best_score && dirt > best_dirt) ||\n                        (score == best_score && dirt == best_dirt && dist0[ni][nj] < dist0[best_ni][best_nj])) {\n                        best_score = score;\n                        best_dirt = dirt;\n                        best_move = move;\n                        best_ni = ni;\n                        best_nj = nj;\n                    }\n                }\n            }\n            if (best_move != '?') {\n                extra += best_move;\n                ++t;\n                last_visit[best_ni][best_nj] = t;\n                cur = {best_ni, best_nj};\n            } else {\n                // fallback: move to any neighbor that reduces dist0\n                for (auto [ni, nj, move] : adj[ci][cj]) {\n                    if (dist0[ni][nj] < dist0[ci][cj]) {\n                        extra += move;\n                        ++t;\n                        last_visit[ni][nj] = t;\n                        cur = {ni, nj};\n                        break;\n                    }\n                }\n            }\n        }\n    }\n    return extra;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    h.resize(N-1);\n    for (int i = 0; i < N-1; ++i) cin >> h[i];\n    v.resize(N);\n    for (int i = 0; i < N; ++i) cin >> v[i];\n    d.assign(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> d[i][j];\n\n    build_graph();\n    compute_dist0();\n\n    vector<vector<int>> last_visit(N, vector<int>(N, 0));\n    int t = 0;\n    pair<int,int> cur = {0,0};\n    string base_route = generate_base_route(last_visit, t, cur);\n\n    string extra_route = greedy_phase(cur, t, last_visit);\n\n    cout << base_route << extra_route << endl;\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int INF = 1e9;\n\nstruct Solver {\n    int N, M, start_idx;\n    vector<int> xs, ys;\n    vector<vector<int>> cells;\n    vector<string> patterns;\n    vector<vector<char>> ov;\n\n    Solver(int N, int M, int start_idx, const vector<string>& grid, const vector<string>& patterns)\n        : N(N), M(M), start_idx(start_idx), patterns(patterns) {\n        int total = N * N;\n        xs.resize(total);\n        ys.resize(total);\n        cells.resize(26);\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                int idx = i * N + j;\n                xs[idx] = i;\n                ys[idx] = j;\n                int ch = grid[i][j] - 'A';\n                cells[ch].push_back(idx);\n            }\n        }\n\n        ov.assign(M, vector<char>(M, 0));\n        for (int i = 0; i < M; ++i) {\n            for (int j = 0; j < M; ++j) {\n                if (i == j) continue;\n                const string &a = patterns[i], &b = patterns[j];\n                for (int k = 4; k >= 1; --k) {\n                    if (a.compare(5 - k, k, b, 0, k) == 0) {\n                        ov[i][j] = k;\n                        break;\n                    }\n                }\n            }\n        }\n    }\n\n    vector<int> greedy_order_from(int start) const {\n        vector<bool> used(M, false);\n        vector<int> order;\n        order.push_back(start);\n        used[start] = true;\n        for (int step = 1; step < M; ++step) {\n            int last = order.back();\n            int best_ov = -1, best_next = -1;\n            for (int j = 0; j < M; ++j) {\n                if (!used[j]) {\n                    int o = ov[last][j];\n                    if (o > best_ov) {\n                        best_ov = o;\n                        best_next = j;\n                    }\n                }\n            }\n            order.push_back(best_next);\n            used[best_next] = true;\n        }\n        return order;\n    }\n\n    vector<int> random_greedy_order_from(int start, mt19937& rng) const {\n        vector<bool> used(M, false);\n        vector<int> order;\n        order.push_back(start);\n        used[start] = true;\n        for (int step = 1; step < M; ++step) {\n            int last = order.back();\n            int best_ov = -1;\n            vector<int> candidates;\n            for (int j = 0; j < M; ++j) {\n                if (!used[j]) {\n                    int o = ov[last][j];\n                    if (o > best_ov) {\n                        best_ov = o;\n                        candidates.clear();\n                        candidates.push_back(j);\n                    } else if (o == best_ov) {\n                        candidates.push_back(j);\n                    }\n                }\n            }\n            uniform_int_distribution<int> dist(0, candidates.size() - 1);\n            int chosen = candidates[dist(rng)];\n            order.push_back(chosen);\n            used[chosen] = true;\n        }\n        return order;\n    }\n\n    pair<int, vector<int>> solve_order(const vector<int>& order) const {\n        string S;\n        S.reserve(5 * M);\n        S += patterns[order[0]];\n        for (size_t i = 1; i < order.size(); ++i) {\n            int prev = order[i - 1];\n            int cur = order[i];\n            int k = ov[prev][cur];\n            S += patterns[cur].substr(k);\n        }\n        int L = S.size();\n        int total_cells = N * N;\n\n        vector<int> dp_prev(total_cells, INF);\n        vector<int> dp_curr(total_cells, INF);\n        vector<short> prev_cell(L * total_cells, -1);\n\n        int first_ch = S[0] - 'A';\n        for (int v : cells[first_ch]) {\n            int d = abs(xs[start_idx] - xs[v]) + abs(ys[start_idx] - ys[v]);\n            dp_prev[v] = d + 1;\n            prev_cell[0 * total_cells + v] = -1;\n        }\n\n        for (int pos = 1; pos < L; ++pos) {\n            int cur_ch = S[pos] - 'A';\n            int prev_ch = S[pos - 1] - 'A';\n            const auto& prev_cells = cells[prev_ch];\n            const auto& cur_cells = cells[cur_ch];\n\n            fill(dp_curr.begin(), dp_curr.end(), INF);\n            for (int v : cur_cells) {\n                int best = INF;\n                short best_u = -1;\n                for (int u : prev_cells) {\n                    if (dp_prev[u] == INF) continue;\n                    int d = abs(xs[u] - xs[v]) + abs(ys[u] - ys[v]);\n                    int cand = dp_prev[u] + d;\n                    if (cand < best) {\n                        best = cand;\n                        best_u = u;\n                    }\n                }\n                dp_curr[v] = best + 1;\n                prev_cell[pos * total_cells + v] = best_u;\n            }\n            swap(dp_prev, dp_curr);\n        }\n\n        int last_ch = S[L - 1] - 'A';\n        int best_cost = INF, best_end = -1;\n        for (int v : cells[last_ch]) {\n            if (dp_prev[v] < best_cost) {\n                best_cost = dp_prev[v];\n                best_end = v;\n            }\n        }\n\n        vector<int> path(L);\n        int cur_cell = best_end;\n        for (int pos = L - 1; pos >= 0; --pos) {\n            path[pos] = cur_cell;\n            cur_cell = prev_cell[pos * total_cells + cur_cell];\n        }\n\n        return {best_cost, path};\n    }\n\n    vector<int> two_opt_improve(vector<int> order, int iterations, mt19937& rng) const {\n        int cur_cost = solve_order(order).first;\n        int n = order.size();\n        for (int iter = 0; iter < iterations; ++iter) {\n            int i = rng() % n;\n            int j = rng() % n;\n            if (i == j) continue;\n            if (i > j) swap(i, j);\n            // reverse segment [i, j]\n            reverse(order.begin() + i, order.begin() + j + 1);\n            int new_cost = solve_order(order).first;\n            if (new_cost < cur_cost) {\n                cur_cost = new_cost;\n            } else {\n                // revert\n                reverse(order.begin() + i, order.begin() + j + 1);\n            }\n        }\n        return order;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n    int si, sj;\n    cin >> si >> sj;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n    vector<string> patterns(M);\n    for (int k = 0; k < M; ++k) cin >> patterns[k];\n\n    Solver solver(N, M, si * N + sj, grid, patterns);\n\n    mt19937 rng(123456);\n    const int K = 10;  // Increased from 5 to 10\n\n    int best_cost = INF;\n    vector<int> best_order;\n\n    for (int start = 0; start < M; ++start) {\n        // Deterministic greedy\n        vector<int> order = solver.greedy_order_from(start);\n        auto [cost, path] = solver.solve_order(order);\n        if (cost < best_cost) {\n            best_cost = cost;\n            best_order = order;\n        }\n        reverse(order.begin(), order.end());\n        auto [cost_rev, path_rev] = solver.solve_order(order);\n        if (cost_rev < best_cost) {\n            best_cost = cost_rev;\n            best_order = order;\n        }\n\n        // Random greedy orders\n        for (int iter = 0; iter < K; ++iter) {\n            vector<int> rand_order = solver.random_greedy_order_from(start, rng);\n            auto [cost_rand, path_rand] = solver.solve_order(rand_order);\n            if (cost_rand < best_cost) {\n                best_cost = cost_rand;\n                best_order = rand_order;\n            }\n            reverse(rand_order.begin(), rand_order.end());\n            auto [cost_rand_rev, path_rand_rev] = solver.solve_order(rand_order);\n            if (cost_rand_rev < best_cost) {\n                best_cost = cost_rand_rev;\n                best_order = rand_order;\n            }\n        }\n    }\n\n    // Apply 2-opt local search to further improve the best order\n    mt19937 rng2(654321);  // Different seed for local search\n    best_order = solver.two_opt_improve(best_order, 2000, rng2);\n\n    auto [final_cost, final_path] = solver.solve_order(best_order);\n    for (int idx : final_path) {\n        int i = idx / N;\n        int j = idx % N;\n        cout << i << ' ' << j << '\\n';\n    }\n\n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <cmath>\n#include <numeric>\n#include <cstdint>\n#include <tuple>\n\nusing namespace std;\n\nstruct Placement {\n    vector<short> cells;          // indices of covered cells (0..N*N-1)\n    vector<uint8_t> contrib;      // contribution to each measurement\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cout.tie(nullptr);\n\n    int N, M;\n    double eps;\n    cin >> N >> M >> eps;\n    double alpha = 1.0 - 2.0 * eps;\n    double beta = eps;\n\n    // read shapes\n    vector<vector<pair<int, int>>> shape_cells(M);\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        shape_cells[k].resize(d);\n        for (int t = 0; t < d; ++t) {\n            cin >> shape_cells[k][t].first >> shape_cells[k][t].second;\n        }\n    }\n\n    // number of divine queries: enough for recovery but leave room for fallback drilling\n    int L = min(150, N * N - 10);\n    // random generator for subsets\n    mt19937 rng(123456);\n    uniform_real_distribution<double> prob(0.0, 1.0);\n\n    // generate random subsets and record which measurements contain each cell\n    vector<vector<int>> subsets(L);\n    vector<vector<int>> meas_including(N * N);\n    for (int l = 0; l < L; ++l) {\n        vector<int>& sub = subsets[l];\n        for (int idx = 0; idx < N * N; ++idx) {\n            if (prob(rng) < 0.5) {\n                sub.push_back(idx);\n                meas_including[idx].push_back(l);\n            }\n        }\n    }\n\n    // precompute all possible placements and their contributions\n    vector<vector<Placement>> placements(M);\n    for (int k = 0; k < M; ++k) {\n        const auto& cells = shape_cells[k];\n        int max_i = 0, max_j = 0;\n        for (auto& p : cells) {\n            max_i = max(max_i, p.first);\n            max_j = max(max_j, p.second);\n        }\n        int h = max_i + 1, w = max_j + 1;\n        for (int dx = 0; dx <= N - h; ++dx) {\n            for (int dy = 0; dy <= N - w; ++dy) {\n                Placement pl;\n                // compute cell indices\n                for (auto& p : cells) {\n                    int i = dx + p.first;\n                    int j = dy + p.second;\n                    pl.cells.push_back(i * N + j);\n                }\n                // compute contribution vector\n                pl.contrib.assign(L, 0);\n                for (int idx : pl.cells) {\n                    for (int l : meas_including[idx]) {\n                        pl.contrib[l]++;\n                    }\n                }\n                placements[k].push_back(move(pl));\n            }\n        }\n    }\n\n    // perform divine queries\n    vector<double> z_vals(L);\n    for (int l = 0; l < L; ++l) {\n        int k = subsets[l].size();\n        cout << \"q \" << k;\n        for (int idx : subsets[l]) {\n            int i = idx / N, j = idx % N;\n            cout << ' ' << i << ' ' << j;\n        }\n        cout << endl;\n        int y;\n        cin >> y;\n        z_vals[l] = (y - beta * k) / alpha;\n    }\n\n    // ----- Greedy OMP to obtain an initial assignment -----\n    vector<int> assignment(M, -1);\n    vector<double> residual = z_vals;\n    for (int iter = 0; iter < M; ++iter) {\n        double best_score = -1e100;\n        int best_shape = -1, best_place = -1;\n        for (int k = 0; k < M; ++k) {\n            if (assignment[k] != -1) continue;\n            const auto& plist = placements[k];\n            for (size_t p_idx = 0; p_idx < plist.size(); ++p_idx) {\n                const auto& p = plist[p_idx];\n                double dot = 0.0, norm2 = 0.0;\n                for (int l = 0; l < L; ++l) {\n                    double c = p.contrib[l];\n                    dot += residual[l] * c;\n                    norm2 += c * c;\n                }\n                if (norm2 == 0) continue;\n                double score = dot / sqrt(norm2);\n                if (score > best_score) {\n                    best_score = score;\n                    best_shape = k;\n                    best_place = p_idx;\n                }\n            }\n        }\n        // assign the best found\n        assignment[best_shape] = best_place;\n        const auto& p = placements[best_shape][best_place];\n        for (int l = 0; l < L; ++l) {\n            residual[l] -= p.contrib[l];\n        }\n    }\n\n    // ----- Simulated Annealing to refine the assignment -----\n    // current sums and error\n    vector<double> cur_sum(L, 0.0);\n    for (int k = 0; k < M; ++k) {\n        const auto& p = placements[k][assignment[k]];\n        for (int l = 0; l < L; ++l) cur_sum[l] += p.contrib[l];\n    }\n    double cur_err = 0.0;\n    for (int l = 0; l < L; ++l) {\n        double diff = z_vals[l] - cur_sum[l];\n        cur_err += diff * diff;\n    }\n\n    vector<int> best_assignment = assignment;\n    double best_err = cur_err;\n\n    const int SA_ITER = 50000;\n    const double INITIAL_TEMP = 1000.0;\n    const double COOLING = 0.9995;\n    double temp = INITIAL_TEMP;\n\n    mt19937 rng_sa(987654);\n    uniform_int_distribution<int> shape_dist(0, M - 1);\n    vector<uniform_int_distribution<int>> place_dist;\n    for (int k = 0; k < M; ++k) {\n        place_dist.emplace_back(0, placements[k].size() - 1);\n    }\n\n    for (int it = 0; it < SA_ITER; ++it) {\n        int k = shape_dist(rng_sa);\n        int old_idx = assignment[k];\n        int new_idx = place_dist[k](rng_sa);\n        if (new_idx == old_idx) continue;\n\n        const auto& p_old = placements[k][old_idx];\n        const auto& p_new = placements[k][new_idx];\n\n        double delta_err = 0.0;\n        for (int l = 0; l < L; ++l) {\n            double delta = (double)p_new.contrib[l] - (double)p_old.contrib[l];\n            double e_l = z_vals[l] - cur_sum[l];\n            delta_err += -2.0 * e_l * delta + delta * delta;\n        }\n\n        if (delta_err < 0 || uniform_real_distribution<double>(0, 1)(rng_sa) < exp(-delta_err / temp)) {\n            cur_err += delta_err;\n            for (int l = 0; l < L; ++l) {\n                cur_sum[l] += (p_new.contrib[l] - p_old.contrib[l]);\n            }\n            assignment[k] = new_idx;\n            if (cur_err < best_err) {\n                best_err = cur_err;\n                best_assignment = assignment;\n            }\n        }\n        temp *= COOLING;\n    }\n\n    // use the best assignment found\n    assignment = best_assignment;\n    // recompute current sums and error for this assignment\n    fill(cur_sum.begin(), cur_sum.end(), 0.0);\n    for (int k = 0; k < M; ++k) {\n        const auto& p = placements[k][assignment[k]];\n        for (int l = 0; l < L; ++l) cur_sum[l] += p.contrib[l];\n    }\n    cur_err = 0.0;\n    for (int l = 0; l < L; ++l) {\n        double diff = z_vals[l] - cur_sum[l];\n        cur_err += diff * diff;\n    }\n\n    // ----- Local hill climbing -----\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng_sa);\n        for (int k : order) {\n            int old_idx = assignment[k];\n            const auto& p_old = placements[k][old_idx];\n            for (size_t new_idx = 0; new_idx < placements[k].size(); ++new_idx) {\n                if (new_idx == static_cast<size_t>(old_idx)) continue;\n                const auto& p_new = placements[k][new_idx];\n                double delta_err = 0.0;\n                for (int l = 0; l < L; ++l) {\n                    double delta = (double)p_new.contrib[l] - (double)p_old.contrib[l];\n                    double e_l = z_vals[l] - cur_sum[l];\n                    delta_err += -2.0 * e_l * delta + delta * delta;\n                }\n                if (delta_err < -1e-9) {\n                    cur_err += delta_err;\n                    for (int l = 0; l < L; ++l) {\n                        double delta = (double)p_new.contrib[l] - (double)p_old.contrib[l];\n                        cur_sum[l] += delta;\n                    }\n                    assignment[k] = new_idx;\n                    improved = true;\n                    break; // go to next shape\n                }\n            }\n        }\n    }\n\n    // ----- Reconstruct the island from the assignment -----\n    vector<vector<int>> grid(N, vector<int>(N, 0));\n    for (int k = 0; k < M; ++k) {\n        const auto& p = placements[k][assignment[k]];\n        for (int idx : p.cells) {\n            int i = idx / N, j = idx % N;\n            grid[i][j]++;\n        }\n    }\n\n    // collect cells with positive oil reserves\n    vector<pair<int, int>> positive;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] > 0) {\n                positive.emplace_back(i, j);\n            }\n        }\n    }\n\n    // ----- First guess -----\n    cout << \"a \" << positive.size();\n    for (auto& p : positive) {\n        cout << ' ' << p.first << ' ' << p.second;\n    }\n    cout << endl;\n\n    int resp;\n    cin >> resp;\n    if (resp == 1) {\n        return 0;\n    }\n\n    // ----- Fallback: drill every cell -----\n    vector<bool> has_oil(N * N, false);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << \"q 1 \" << i << ' ' << j << endl;\n            int val;\n            cin >> val;\n            if (val > 0) {\n                has_oil[i * N + j] = true;\n            }\n        }\n    }\n\n    positive.clear();\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (has_oil[i * N + j]) {\n                positive.emplace_back(i, j);\n            }\n        }\n    }\n\n    cout << \"a \" << positive.size();\n    for (auto& p : positive) {\n        cout << ' ' << p.first << ' ' << p.second;\n    }\n    cout << endl;\n\n    cin >> resp; // should be 1\n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cstdint>\n#include <cmath>\n\nusing namespace std;\nusing ll = long long;\n\nint W, D, N;\n\nstruct Partition {\n    bool is_one_row;\n    vector<int> widths; // for one row\n    int h; // for two rows\n    vector<int> top_widths;\n    vector<int> bottom_widths;\n};\n\nstruct Rect {\n    int top, left, bottom, right;\n};\n\nll compute_shortage(const vector<int>& sorted_areas, const vector<ll>& areas) {\n    ll cost = 0;\n    for (size_t i = 0; i < sorted_areas.size(); ++i) {\n        if (sorted_areas[i] > areas[i]) {\n            cost += 100LL * (sorted_areas[i] - areas[i]);\n        }\n    }\n    return cost;\n}\n\nvector<ll> get_areas_from_partition(const Partition& part) {\n    vector<ll> areas;\n    if (part.is_one_row) {\n        for (int w : part.widths) {\n            areas.push_back((ll)w * W);\n        }\n    } else {\n        for (int w : part.top_widths) {\n            areas.push_back((ll)w * part.h);\n        }\n        for (int w : part.bottom_widths) {\n            areas.push_back((ll)w * (W - part.h));\n        }\n    }\n    sort(areas.begin(), areas.end(), greater<ll>());\n    return areas;\n}\n\nvector<int> compute_widths_for_row(const vector<int>& areas, int height) {\n    int M = areas.size();\n    vector<int> widths(M, 1);\n    int total = M;\n    for (int i = 0; i < M; ++i) {\n        int needed = (areas[i] + height - 1) / height;\n        int add = min(W - total, max(0, needed - 1));\n        widths[i] += add;\n        total += add;\n    }\n    if (total < W) {\n        widths[0] += (W - total);\n    }\n    return widths;\n}\n\nPartition compute_optimal_one_row(const vector<int>& sorted_areas) {\n    Partition part;\n    part.is_one_row = true;\n    part.widths.assign(N, 1);\n    int total = N;\n    for (int i = 0; i < N; ++i) {\n        int needed = (sorted_areas[i] + W - 1) / W;\n        int add = min(W - total, max(0, needed - 1));\n        part.widths[i] += add;\n        total += add;\n    }\n    if (total < W) {\n        part.widths[0] += (W - total);\n    }\n    return part;\n}\n\nPartition compute_two_row_partition(const vector<int>& sorted_areas, int h, bool top_largest) {\n    Partition part;\n    part.is_one_row = false;\n    part.h = h;\n    int split = N / 2; // top gets half, bottom gets half\n    vector<int> top_areas, bottom_areas;\n    if (top_largest) {\n        top_areas.assign(sorted_areas.begin(), sorted_areas.begin() + split);\n        bottom_areas.assign(sorted_areas.begin() + split, sorted_areas.end());\n    } else {\n        top_areas.assign(sorted_areas.begin() + split, sorted_areas.end());\n        bottom_areas.assign(sorted_areas.begin(), sorted_areas.begin() + split);\n    }\n    part.top_widths = compute_widths_for_row(top_areas, h);\n    part.bottom_widths = compute_widths_for_row(bottom_areas, W - h);\n    return part;\n}\n\nvoid fill_edge_arrays(const Partition& part, vector<vector<bool>>& horiz, vector<vector<bool>>& vert) {\n    horiz.assign(W, vector<bool>(W, false));\n    vert.assign(W, vector<bool>(W, false));\n    if (part.is_one_row) {\n        int cum = 0;\n        for (int i = 0; i < N-1; ++i) {\n            cum += part.widths[i];\n            for (int y = 0; y < W; ++y) {\n                vert[cum][y] = true;\n            }\n        }\n    } else {\n        for (int x = 0; x < W; ++x) {\n            horiz[x][part.h] = true;\n        }\n        int cum = 0;\n        for (size_t i = 0; i < part.top_widths.size() - 1; ++i) {\n            cum += part.top_widths[i];\n            for (int y = 0; y < part.h; ++y) {\n                vert[cum][y] = true;\n            }\n        }\n        cum = 0;\n        for (size_t i = 0; i < part.bottom_widths.size() - 1; ++i) {\n            cum += part.bottom_widths[i];\n            for (int y = part.h; y < W; ++y) {\n                vert[cum][y] = true;\n            }\n        }\n    }\n}\n\nint compute_transition_cost(const Partition& part1, const Partition& part2) {\n    vector<vector<bool>> horiz1, vert1, horiz2, vert2;\n    fill_edge_arrays(part1, horiz1, vert1);\n    fill_edge_arrays(part2, horiz2, vert2);\n    int cost = 0;\n    for (int i = 1; i < W; ++i) {\n        for (int j = 0; j < W; ++j) {\n            if (horiz1[i][j] != horiz2[i][j]) cost++;\n        }\n    }\n    for (int i = 0; i < W; ++i) {\n        for (int j = 1; j < W; ++j) {\n            if (vert1[i][j] != vert2[i][j]) cost++;\n        }\n    }\n    return cost;\n}\n\nvoid output_rectangles(const Partition& part, const vector<int>& orig_idx) {\n    struct RectWithArea {\n        ll area;\n        Rect rect;\n    };\n    vector<RectWithArea> rects;\n    if (part.is_one_row) {\n        int left = 0;\n        for (int i = 0; i < N; ++i) {\n            int right = left + part.widths[i];\n            rects.push_back({(ll)part.widths[i] * W, {0, left, W, right}});\n            left = right;\n        }\n    } else {\n        int left = 0;\n        for (int w : part.top_widths) {\n            int right = left + w;\n            rects.push_back({(ll)w * part.h, {0, left, part.h, right}});\n            left = right;\n        }\n        left = 0;\n        for (int w : part.bottom_widths) {\n            int right = left + w;\n            rects.push_back({(ll)w * (W - part.h), {part.h, left, W, right}});\n            left = right;\n        }\n    }\n    sort(rects.begin(), rects.end(), [](const RectWithArea& a, const RectWithArea& b) {\n        return a.area > b.area;\n    });\n    vector<Rect> assign(N);\n    for (int i = 0; i < N; ++i) {\n        assign[orig_idx[i]] = rects[i].rect;\n    }\n    for (int k = 0; k < N; ++k) {\n        Rect r = assign[k];\n        cout << r.top << \" \" << r.left << \" \" << r.bottom << \" \" << r.right << \"\\n\";\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    cin >> W >> D >> N;\n    vector<vector<int>> a(D, vector<int>(N));\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            cin >> a[d][k];\n        }\n    }\n    vector<pair<int,int>> order(N);\n    vector<int> sorted_areas(N), orig_idx(N);\n    // day 0\n    for (int k = 0; k < N; ++k) order[k] = {a[0][k], k};\n    sort(order.begin(), order.end(), greater<pair<int,int>>());\n    for (int i = 0; i < N; ++i) {\n        sorted_areas[i] = order[i].first;\n        orig_idx[i] = order[i].second;\n    }\n    Partition current = compute_optimal_one_row(sorted_areas);\n    output_rectangles(current, orig_idx);\n    // subsequent days\n    for (int d = 1; d < D; ++d) {\n        for (int k = 0; k < N; ++k) order[k] = {a[d][k], k};\n        sort(order.begin(), order.end(), greater<pair<int,int>>());\n        for (int i = 0; i < N; ++i) {\n            sorted_areas[i] = order[i].first;\n            orig_idx[i] = order[i].second;\n        }\n        // one-row candidate\n        Partition one_row = compute_optimal_one_row(sorted_areas);\n        ll shortage_one = compute_shortage(sorted_areas, get_areas_from_partition(one_row));\n        // two-row candidates\n        vector<Partition> two_row_candidates;\n        vector<int> h_vals = {1, W/4, W/2, 3*W/4, W-1};\n        for (int h : h_vals) {\n            if (h <= 0 || h >= W) continue;\n            two_row_candidates.push_back(compute_two_row_partition(sorted_areas, h, true));\n            two_row_candidates.push_back(compute_two_row_partition(sorted_areas, h, false));\n        }\n        // find best two-row\n        ll best_two_shortage = 1e18;\n        Partition best_two;\n        for (auto& cand : two_row_candidates) {\n            ll shortage = compute_shortage(sorted_areas, get_areas_from_partition(cand));\n            if (shortage < best_two_shortage) {\n                best_two_shortage = shortage;\n                best_two = cand;\n            }\n        }\n        // compute transition costs\n        int trans_one = compute_transition_cost(current, one_row);\n        int trans_two = compute_transition_cost(current, best_two);\n        ll cost_one = shortage_one + trans_one;\n        ll cost_two = best_two_shortage + trans_two;\n        ll cost_keep = compute_shortage(sorted_areas, get_areas_from_partition(current));\n        if (cost_keep <= cost_one && cost_keep <= cost_two) {\n            output_rectangles(current, orig_idx);\n        } else if (cost_one <= cost_two) {\n            current = one_row;\n            output_rectangles(one_row, orig_idx);\n        } else {\n            current = best_two;\n            output_rectangles(best_two, orig_idx);\n        }\n    }\n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <array>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <cstdint>\n\nusing namespace std;\n\nconst int MOD = 998244353;\nconst int N = 9, M = 20, K = 81;\n\nstruct Operation {\n    int stamp, p, q;\n    vector<pair<int, int>> cells;\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m, k;\n    cin >> n >> m >> k;\n\n    vector<int64_t> cur(81);\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cin >> cur[i * 9 + j];\n        }\n    }\n\n    vector<array<array<int, 3>, 3>> stamps(m);\n    for (int s = 0; s < m; ++s) {\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                cin >> stamps[s][i][j];\n            }\n        }\n    }\n\n    vector<Operation> ops;\n    for (int s = 0; s < m; ++s) {\n        for (int p = 0; p <= n - 3; ++p) {\n            for (int q = 0; q <= n - 3; ++q) {\n                Operation op;\n                op.stamp = s;\n                op.p = p;\n                op.q = q;\n                for (int i = 0; i < 3; ++i) {\n                    for (int j = 0; j < 3; ++j) {\n                        int cell = (p + i) * 9 + (q + j);\n                        int val = stamps[s][i][j];\n                        op.cells.emplace_back(cell, val);\n                    }\n                }\n                ops.push_back(move(op));\n            }\n        }\n    }\n    const int num_ops = ops.size();\n\n    int64_t score = 0;\n    for (int i = 0; i < 81; ++i) score += cur[i] % MOD;\n\n    auto delta_add = [&](int id) -> int64_t {\n        int64_t d = 0;\n        for (auto [idx, val] : ops[id].cells) {\n            int64_t old_rem = cur[idx] % MOD;\n            int64_t new_val = cur[idx] + val;\n            int64_t new_rem = new_val % MOD;\n            d += new_rem - old_rem;\n        }\n        return d;\n    };\n\n    auto apply_add = [&](int id) {\n        for (auto [idx, val] : ops[id].cells) {\n            cur[idx] += val;\n        }\n    };\n\n    auto delta_remove = [&](int id) -> int64_t {\n        int64_t d = 0;\n        for (auto [idx, val] : ops[id].cells) {\n            int64_t old_rem = cur[idx] % MOD;\n            int64_t new_val = cur[idx] - val;\n            int64_t new_rem = new_val % MOD;\n            d += new_rem - old_rem;\n        }\n        return d;\n    };\n\n    auto apply_remove = [&](int id) {\n        for (auto [idx, val] : ops[id].cells) {\n            cur[idx] -= val;\n        }\n    };\n\n    // Greedy initial solution\n    vector<int> init_ops;\n    while (init_ops.size() < K) {\n        int best_id = -1;\n        int64_t best_delta = 0;\n        for (int id = 0; id < num_ops; ++id) {\n            int64_t d = delta_add(id);\n            if (d > best_delta) {\n                best_delta = d;\n                best_id = id;\n            }\n        }\n        if (best_delta <= 0) break;\n        apply_add(best_id);\n        init_ops.push_back(best_id);\n        score += best_delta;\n    }\n    \n    // Store initial state\n    vector<int64_t> init_cur = cur;\n    int64_t init_score = score;\n    \n    // Prepare for multi-restart SA\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> uni_real(0.0, 1.0);\n    \n    // Track best solution across restarts\n    vector<int> best_ops = init_ops;\n    vector<int64_t> best_cur = init_cur;\n    int64_t best_score = init_score;\n    \n    // Successful parameters with increased iterations\n    const int num_restarts = 6;\n    const int iter_per_restart = 2'000'000; // Total 12M iterations\n    const double T0 = 1e8; // Higher initial temperature\n    const int perturb_count = 7; // Increased perturbation\n    \n    static int64_t contrib[81];\n    static vector<int> touched;\n    \n    // Current solution variables\n    vector<int> cur_ops;\n    \n    for (int restart = 0; restart < num_restarts; ++restart) {\n        // Reset contrib array\n        for (int i = 0; i < 81; ++i) contrib[i] = 0;\n        \n        // Determine starting point\n        if (restart == 0) {\n            // First restart: start from greedy\n            cur = init_cur;\n            cur_ops = init_ops;\n            score = init_score;\n        } else {\n            // Subsequent restarts: start from best solution with perturbation\n            cur = best_cur;\n            cur_ops = best_ops;\n            score = best_score;\n            \n            // Perturb: remove operations and greedily refill\n            int to_remove = min(perturb_count, (int)cur_ops.size());\n            \n            // Remove random operations\n            for (int i = 0; i < to_remove; ++i) {\n                int idx = rng() % cur_ops.size();\n                int old_id = cur_ops[idx];\n                apply_remove(old_id);\n                cur_ops[idx] = cur_ops.back();\n                cur_ops.pop_back();\n            }\n            \n            // Greedily refill to size K\n            while (cur_ops.size() < K) {\n                int best_id = -1;\n                int64_t best_delta = 0;\n                for (int id = 0; id < num_ops; ++id) {\n                    int64_t d = delta_add(id);\n                    if (d > best_delta) {\n                        best_delta = d;\n                        best_id = id;\n                    }\n                }\n                if (best_delta <= 0) {\n                    // No positive gain, add a random operation\n                    int new_id = rng() % num_ops;\n                    apply_add(new_id);\n                    cur_ops.push_back(new_id);\n                } else {\n                    apply_add(best_id);\n                    cur_ops.push_back(best_id);\n                }\n            }\n            \n            // Recompute score after perturbation\n            score = 0;\n            for (int i = 0; i < 81; ++i) score += cur[i] % MOD;\n        }\n        \n        double T = T0;\n        \n        // SA for this restart with linear cooling\n        for (int iter = 0; iter < iter_per_restart; ++iter) {\n            double r = uni_real(rng);\n            // Probabilities: 15% add, 15% remove, 70% replace\n            if (r < 0.15 && cur_ops.size() < K) {\n                // Add operation\n                int new_id = rng() % num_ops;\n                int64_t delta = delta_add(new_id);\n                if (delta > 0 || (delta <= 0 && exp(delta / T) > uni_real(rng))) {\n                    apply_add(new_id);\n                    cur_ops.push_back(new_id);\n                    score += delta;\n                }\n            } else if (r < 0.30 && !cur_ops.empty()) {\n                // Remove operation\n                int idx = rng() % cur_ops.size();\n                int old_id = cur_ops[idx];\n                int64_t delta = delta_remove(old_id);\n                if (delta > 0 || (delta <= 0 && exp(delta / T) > uni_real(rng))) {\n                    apply_remove(old_id);\n                    cur_ops[idx] = cur_ops.back();\n                    cur_ops.pop_back();\n                    score += delta;\n                }\n            } else if (!cur_ops.empty()) {\n                // Replace operation (70% chance)\n                int idx = rng() % cur_ops.size();\n                int old_id = cur_ops[idx];\n                int new_id = rng() % num_ops;\n                if (new_id == old_id) continue;\n\n                touched.clear();\n                for (auto [i, v] : ops[old_id].cells) {\n                    if (contrib[i] == 0) touched.push_back(i);\n                    contrib[i] -= v;\n                }\n                for (auto [i, v] : ops[new_id].cells) {\n                    if (contrib[i] == 0) touched.push_back(i);\n                    contrib[i] += v;\n                }\n\n                int64_t delta = 0;\n                for (int i : touched) {\n                    int64_t net = contrib[i];\n                    int64_t old_rem = cur[i] % MOD;\n                    int64_t new_val = cur[i] + net;\n                    int64_t new_rem = new_val % MOD;\n                    delta += new_rem - old_rem;\n                }\n\n                if (delta > 0 || (delta <= 0 && exp(delta / T) > uni_real(rng))) {\n                    for (int i : touched) {\n                        cur[i] += contrib[i];\n                    }\n                    cur_ops[idx] = new_id;\n                    score += delta;\n                }\n\n                for (int i : touched) {\n                    contrib[i] = 0;\n                }\n            }\n\n            // Linear cooling (proven effective)\n            T = T0 * (1.0 - (double)iter / iter_per_restart);\n        }\n        \n        // Update best solution if this restart improved\n        if (score > best_score) {\n            best_score = score;\n            best_ops = cur_ops;\n            best_cur = cur;\n        }\n    }\n    \n    // Output best solution found\n    cout << best_ops.size() << '\\n';\n    for (int id : best_ops) {\n        cout << ops[id].stamp << ' ' << ops[id].p << ' ' << ops[id].q << '\\n';\n    }\n\n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <climits>\n\nusing namespace std;\n\nconst int N = 5;\n\nint main() {\n    int N_val;\n    cin >> N_val;\n    \n    int A[N][N];\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            cin >> A[i][j];\n    \n    int gate_of[25], pos_of[25];\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++) {\n            gate_of[A[i][j]] = i;\n            pos_of[A[i][j]] = j;\n        }\n    \n    int grid[N][N];\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            grid[i][j] = -1;\n    \n    vector<int> gate_queue[N];\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            gate_queue[i].push_back(A[i][j]);\n    \n    int cr = 0, cc = 0;\n    bool holding = false;\n    int held = -1;\n    \n    vector<string> actions(5);\n    int turn = 0;\n    int dispatched = 0;\n    \n    auto do_turn = [&](char action) {\n        turn++;\n        actions[0] += action;\n        for (int i = 1; i < 5; i++)\n            actions[i] += (turn == 1) ? 'B' : '.';\n        \n        for (int g = 0; g < N; g++) {\n            if (gate_queue[g].empty() || grid[g][0] != -1) continue;\n            if (cr == g && cc == 0 && holding) continue;\n            grid[g][0] = gate_queue[g][0];\n            gate_queue[g].erase(gate_queue[g].begin());\n        }\n        \n        switch (action) {\n            case 'U': cr--; break;\n            case 'D': cr++; break;\n            case 'L': cc--; break;\n            case 'R': cc++; break;\n            case 'P':\n                if (grid[cr][cc] != -1) {\n                    held = grid[cr][cc];\n                    holding = true;\n                    grid[cr][cc] = -1;\n                }\n                break;\n            case 'Q':\n                if (holding && grid[cr][cc] == -1) {\n                    grid[cr][cc] = held;\n                    holding = false;\n                    held = -1;\n                }\n                break;\n        }\n        \n        for (int g = 0; g < N; g++)\n            if (grid[g][N-1] != -1) {\n                grid[g][N-1] = -1;\n                dispatched++;\n            }\n    };\n    \n    auto move_to = [&](int tr, int tc) {\n        while (cr != tr || cc != tc) {\n            if (cr < tr) do_turn('D');\n            else if (cr > tr) do_turn('U');\n            else if (cc < tc) do_turn('R');\n            else do_turn('L');\n        }\n    };\n    \n    // Process row by row, containers in order within each row\n    int picked[5] = {0};\n    \n    for (int r = 0; r < 5; r++) {\n        for (int b = 5*r; b < 5*(r+1); b++) {\n            // Check if b is in buffer (columns 1-3)\n            int br = -1, bc = -1;\n            for (int c = 1; c <= 3 && br == -1; c++)\n                for (int i = 0; i < N && br == -1; i++)\n                    if (grid[i][c] == b) { br = i; bc = c; }\n            \n            if (br != -1) {\n                move_to(br, bc);\n                do_turn('P');\n                move_to(r, N-1);\n                do_turn('Q');\n                continue;\n            }\n            \n            int g = gate_of[b];\n            int p = pos_of[b];\n            \n            if (picked[g] > p) continue; // Already dispatched\n            \n            // Pick up blocking containers and store in buffer\n            while (picked[g] < p) {\n                move_to(g, 0);\n                while (grid[g][0] == -1 && !gate_queue[g].empty())\n                    do_turn('.');\n                if (grid[g][0] == -1) break;\n                \n                do_turn('P');\n                if (!holding) break;\n                \n                int container = held;\n                picked[g]++;\n                \n                // Find empty buffer cell (columns 1-3)\n                int sr = -1, sc = -1;\n                for (int c = 1; c <= 3 && sr == -1; c++)\n                    for (int i = 0; i < N && sr == -1; i++)\n                        if (grid[i][c] == -1) { sr = i; sc = c; }\n                \n                if (sr != -1) {\n                    move_to(sr, sc);\n                    do_turn('Q');\n                } else {\n                    move_to(container / N, N-1);\n                    do_turn('Q');\n                }\n            }\n            \n            // Pick up target container\n            if (picked[g] == p) {\n                move_to(g, 0);\n                while (grid[g][0] == -1 && !gate_queue[g].empty())\n                    do_turn('.');\n                if (grid[g][0] != -1) {\n                    do_turn('P');\n                    if (holding) {\n                        picked[g]++;\n                        move_to(r, N-1);\n                        do_turn('Q');\n                    }\n                }\n            }\n        }\n    }\n    \n    int max_len = 0;\n    for (int i = 0; i < 5; i++)\n        max_len = max(max_len, (int)actions[i].size());\n    for (int i = 0; i < 5; i++)\n        while ((int)actions[i].size() < max_len)\n            actions[i] += '.';\n    \n    for (int i = 0; i < 5; i++)\n        cout << actions[i] << endl;\n    \n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <cassert>\n\nusing namespace std;\n\nstruct Square {\n    int x, y, h;\n};\n\ninline int manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\npair<long long, bool> evaluate(const vector<int>& perm, const vector<Square>& squares) {\n    long long total_steps = 0;\n    long long load_dist = 0;\n    int load = 0;\n    int cur_x = 0, cur_y = 0;\n    bool feasible = true;\n\n    for (int idx : perm) {\n        const Square& sq = squares[idx];\n        int d = manhattan(cur_x, cur_y, sq.x, sq.y);\n        total_steps += d;\n        load_dist += (long long)load * d;\n\n        load += sq.h;\n        if (load < 0) {\n            feasible = false;\n            break;\n        }\n\n        cur_x = sq.x;\n        cur_y = sq.y;\n    }\n\n    if (load != 0) feasible = false;\n\n    long long cost_without_base = 100 * total_steps + load_dist;\n    return {cost_without_base, feasible};\n}\n\nvector<int> greedy_permutation(const vector<Square>& squares, mt19937& rng) {\n    int M = squares.size();\n    vector<bool> used(M, false);\n    vector<int> perm;\n    int cur_x = 0, cur_y = 0;\n    int load = 0;\n    int remaining = M;\n\n    while (remaining > 0) {\n        vector<int> candidates;\n        int best_dist = 1e9;\n\n        for (int i = 0; i < M; ++i) {\n            if (used[i]) continue;\n            const Square& sq = squares[i];\n            bool feasible = false;\n            if (sq.h > 0) {\n                feasible = true;\n            } else {\n                if (load >= -sq.h) feasible = true;\n            }\n            if (!feasible) continue;\n            int d = manhattan(cur_x, cur_y, sq.x, sq.y);\n            if (d < best_dist) {\n                best_dist = d;\n                candidates.clear();\n                candidates.push_back(i);\n            } else if (d == best_dist) {\n                candidates.push_back(i);\n            }\n        }\n\n        assert(!candidates.empty());\n        uniform_int_distribution<int> dist(0, candidates.size()-1);\n        int best_idx = candidates[dist(rng)];\n\n        used[best_idx] = true;\n        perm.push_back(best_idx);\n        cur_x = squares[best_idx].x;\n        cur_y = squares[best_idx].y;\n        load += squares[best_idx].h;\n        --remaining;\n    }\n\n    return perm;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<vector<int>> h(N, vector<int>(N));\n    long long base = 0;\n    vector<Square> squares;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> h[i][j];\n            if (h[i][j] != 0) {\n                squares.push_back({i, j, h[i][j]});\n                base += abs(h[i][j]);\n            }\n        }\n    }\n\n    int M = squares.size();\n    if (M == 0) {\n        return 0;\n    }\n\n    random_device rd;\n    mt19937 rng(rd());\n    uniform_real_distribution<double> uni(0.0, 1.0);\n    uniform_int_distribution<int> rand_idx(0, M-1);\n\n    // SA parameters\n    const int MAX_ITER = 400000;\n    const int RESTART_INTERVAL = 40000;\n    double start_temp = 10000.0;\n    double end_temp = 1e-5;\n    double cooling = exp(log(end_temp / start_temp) / MAX_ITER);\n\n    vector<int> best_perm;\n    long long best_cost = 1e18;\n\n    // initial solution\n    vector<int> cur_perm = greedy_permutation(squares, rng);\n    auto [init_cost, feasible_init] = evaluate(cur_perm, squares);\n    assert(feasible_init);\n    best_perm = cur_perm;\n    best_cost = init_cost;\n    long long cur_cost = init_cost;\n\n    for (int iter = 0; iter < MAX_ITER; ++iter) {\n        // periodic restart\n        if (iter % RESTART_INTERVAL == 0 && iter > 0) {\n            cur_perm = greedy_permutation(squares, rng);\n            auto [cost, feasible] = evaluate(cur_perm, squares);\n            if (feasible) {\n                cur_cost = cost;\n                if (cur_cost < best_cost) {\n                    best_perm = cur_perm;\n                    best_cost = cur_cost;\n                }\n            }\n        }\n\n        double T = start_temp * pow(cooling, iter);\n        vector<int> new_perm = cur_perm;\n        double move_type = uni(rng);\n\n        if (move_type < 0.33) {\n            // swap two random positions\n            int i = rand_idx(rng);\n            int j = rand_idx(rng);\n            if (i != j) swap(new_perm[i], new_perm[j]);\n        } else if (move_type < 0.66) {\n            // reverse a random segment\n            int i = rand_idx(rng);\n            int j = rand_idx(rng);\n            if (i > j) swap(i, j);\n            reverse(new_perm.begin() + i, new_perm.begin() + j + 1);\n        } else {\n            // move a random element to another random position\n            int i = rand_idx(rng);\n            int j = rand_idx(rng);\n            if (i != j) {\n                int val = new_perm[i];\n                new_perm.erase(new_perm.begin() + i);\n                if (j > i) --j;\n                new_perm.insert(new_perm.begin() + j, val);\n            }\n        }\n\n        auto [new_cost, feasible] = evaluate(new_perm, squares);\n        if (!feasible) continue;\n\n        if (new_cost < cur_cost || uni(rng) < exp((cur_cost - new_cost) / T)) {\n            cur_perm = new_perm;\n            cur_cost = new_cost;\n            if (cur_cost < best_cost) {\n                best_perm = cur_perm;\n                best_cost = cur_cost;\n            }\n        }\n    }\n\n    // 2-opt local search (max 10 passes)\n    for (int pass = 0; pass < 10; ++pass) {\n        bool improved = false;\n        for (int i = 0; i < M; ++i) {\n            for (int j = i+1; j < M; ++j) {\n                vector<int> new_perm = best_perm;\n                reverse(new_perm.begin() + i, new_perm.begin() + j + 1);\n                auto [new_cost, feasible] = evaluate(new_perm, squares);\n                if (feasible && new_cost < best_cost) {\n                    best_perm = new_perm;\n                    best_cost = new_cost;\n                    improved = true;\n                }\n            }\n        }\n        if (!improved) break;\n    }\n\n    // Or-opt local search (random moves for segments of length 1 and 2)\n    const int OR_OPT_ATTEMPTS = 2000;\n    uniform_int_distribution<int> rand_len(1, 2);\n    for (int attempt = 0; attempt < OR_OPT_ATTEMPTS; ++attempt) {\n        int L = rand_len(rng);\n        if (L > M) continue;\n        int i = uniform_int_distribution<int>(0, M - L)(rng);\n        int j = uniform_int_distribution<int>(0, M - L)(rng);\n        if (i == j) continue;\n        vector<int> new_perm = best_perm;\n        // remove segment\n        vector<int> segment(new_perm.begin() + i, new_perm.begin() + i + L);\n        new_perm.erase(new_perm.begin() + i, new_perm.begin() + i + L);\n        // adjust j if necessary\n        if (j > i) j -= L;\n        // insert segment at position j\n        new_perm.insert(new_perm.begin() + j, segment.begin(), segment.end());\n        auto [new_cost, feasible] = evaluate(new_perm, squares);\n        if (feasible && new_cost < best_cost) {\n            best_perm = new_perm;\n            best_cost = new_cost;\n        }\n    }\n\n    // Output operations\n    int cur_x = 0, cur_y = 0, load = 0;\n    for (int idx : best_perm) {\n        const Square& sq = squares[idx];\n        while (cur_y < sq.y) { cout << \"R\\n\"; ++cur_y; }\n        while (cur_y > sq.y) { cout << \"L\\n\"; --cur_y; }\n        while (cur_x < sq.x) { cout << \"D\\n\"; ++cur_x; }\n        while (cur_x > sq.x) { cout << \"U\\n\"; --cur_x; }\n\n        if (sq.h > 0) {\n            cout << \"+\" << sq.h << \"\\n\";\n            load += sq.h;\n        } else {\n            cout << \"-\" << -sq.h << \"\\n\";\n            load += sq.h;\n        }\n    }\n\n    return 0;\n}","ahc035":"#include <cstdio>\n#include <vector>\n#include <array>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n#include <set>\n\nusing namespace std;\n\nconst int N = 6;\nconst int M = 15;\nconst int T = 10;\nconst int SEED_COUNT = 2 * N * (N - 1); // 60\n\nusing Seed = array<int, M>;\n\n// Complementarity score: sum of max values per attribute\nint complementarity(const Seed& a, const Seed& b) {\n    int res = 0;\n    for (int l = 0; l < M; ++l) {\n        res += max(a[l], b[l]);\n    }\n    return res;\n}\n\n// Select seeds with diversity and high potential\nvector<int> select_seeds(const vector<Seed>& seeds, const vector<int>& sums) {\n    vector<int> selected;\n    vector<bool> used(SEED_COUNT, false);\n    \n    // First, take top 10 by sum (high value seeds)\n    vector<int> by_sum(SEED_COUNT);\n    iota(by_sum.begin(), by_sum.end(), 0);\n    sort(by_sum.begin(), by_sum.end(), [&](int a, int b) { return sums[a] > sums[b]; });\n    \n    for (int i = 0; i < 10 && i < SEED_COUNT; ++i) {\n        selected.push_back(by_sum[i]);\n        used[by_sum[i]] = true;\n    }\n    \n    // Then add seeds that are complementary to existing ones\n    while (selected.size() < 36) {\n        int best_seed = -1;\n        int best_score = -1;\n        \n        for (int i = 0; i < SEED_COUNT; ++i) {\n            if (used[i]) continue;\n            \n            // Score: sum of complementarity with all selected seeds\n            int score = 0;\n            for (int s : selected) {\n                score += complementarity(seeds[i], seeds[s]);\n            }\n            score /= selected.size(); // Normalize by number of selected\n            \n            // Add a bonus for high individual sum\n            score += sums[i] / 10;\n            \n            if (score > best_score) {\n                best_score = score;\n                best_seed = i;\n            }\n        }\n        \n        if (best_seed != -1) {\n            selected.push_back(best_seed);\n            used[best_seed] = true;\n        } else {\n            break;\n        }\n    }\n    \n    // If we still need more, add by highest sum\n    if (selected.size() < 36) {\n        for (int i = 0; i < SEED_COUNT && selected.size() < 36; ++i) {\n            if (!used[i]) {\n                selected.push_back(i);\n                used[i] = true;\n            }\n        }\n    }\n    \n    return selected;\n}\n\n// Place seeds to maximize good pairings\nvoid place_seeds(const vector<Seed>& seeds, const vector<int>& sums, \n                 const vector<int>& selected, vector<vector<int>>& grid) {\n    // We'll use a greedy approach considering complementarity\n    vector<bool> used(SEED_COUNT, false);\n    for (int s : selected) used[s] = true;\n    \n    // Start with the highest sum seed in the center\n    vector<int> selected_copy = selected;\n    sort(selected_copy.begin(), selected_copy.end(), [&](int a, int b) { \n        return sums[a] > sums[b]; \n    });\n    \n    // Place highest sum seeds in interior cells first\n    vector<pair<int, int>> interior_cells;\n    vector<pair<int, int>> border_cells;\n    \n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            bool is_interior = (i > 0 && i < N-1 && j > 0 && j < N-1);\n            if (is_interior) {\n                interior_cells.push_back({i, j});\n            } else {\n                border_cells.push_back({i, j});\n            }\n        }\n    }\n    \n    // Place top seeds in interior\n    for (int i = 0; i < interior_cells.size() && i < selected_copy.size(); ++i) {\n        auto [r, c] = interior_cells[i];\n        grid[r][c] = selected_copy[i];\n    }\n    \n    // Fill remaining cells with remaining seeds\n    vector<int> remaining_seeds;\n    for (int s : selected_copy) {\n        bool placed = false;\n        for (int i = 0; i < N && !placed; ++i) {\n            for (int j = 0; j < N && !placed; ++j) {\n                if (grid[i][j] == s) {\n                    placed = true;\n                }\n            }\n        }\n        if (!placed) {\n            remaining_seeds.push_back(s);\n        }\n    }\n    \n    // Place border seeds\n    for (int i = 0; i < border_cells.size() && !remaining_seeds.empty(); ++i) {\n        auto [r, c] = border_cells[i];\n        grid[r][c] = remaining_seeds.back();\n        remaining_seeds.pop_back();\n    }\n    \n    // Fill any remaining empty cells\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] == -1 && !remaining_seeds.empty()) {\n                grid[i][j] = remaining_seeds.back();\n                remaining_seeds.pop_back();\n            }\n        }\n    }\n    \n    // Now optimize placement by swapping to increase complementarity\n    for (int iter = 0; iter < 100; ++iter) {\n        bool improved = false;\n        \n        for (int i1 = 0; i1 < N; ++i1) {\n            for (int j1 = 0; j1 < N; ++j1) {\n                for (int i2 = 0; i2 < N; ++i2) {\n                    for (int j2 = 0; j2 < N; ++j2) {\n                        if (i1 == i2 && j1 == j2) continue;\n                        \n                        // Calculate current complementarity for neighbors of both cells\n                        auto get_neighbors = [&](int i, int j) {\n                            vector<pair<int, int>> neighbors;\n                            if (i > 0) neighbors.push_back({i-1, j});\n                            if (i < N-1) neighbors.push_back({i+1, j});\n                            if (j > 0) neighbors.push_back({i, j-1});\n                            if (j < N-1) neighbors.push_back({i, j+1});\n                            return neighbors;\n                        };\n                        \n                        auto neighbors1 = get_neighbors(i1, j1);\n                        auto neighbors2 = get_neighbors(i2, j2);\n                        \n                        int current_score = 0;\n                        for (auto [ni, nj] : neighbors1) {\n                            current_score += complementarity(seeds[grid[i1][j1]], seeds[grid[ni][nj]]);\n                        }\n                        for (auto [ni, nj] : neighbors2) {\n                            current_score += complementarity(seeds[grid[i2][j2]], seeds[grid[ni][nj]]);\n                        }\n                        \n                        // Try swapping\n                        swap(grid[i1][j1], grid[i2][j2]);\n                        \n                        int new_score = 0;\n                        for (auto [ni, nj] : neighbors1) {\n                            new_score += complementarity(seeds[grid[i1][j1]], seeds[grid[ni][nj]]);\n                        }\n                        for (auto [ni, nj] : neighbors2) {\n                            new_score += complementarity(seeds[grid[i2][j2]], seeds[grid[ni][nj]]);\n                        }\n                        \n                        if (new_score > current_score) {\n                            improved = true;\n                        } else {\n                            swap(grid[i1][j1], grid[i2][j2]);\n                        }\n                    }\n                }\n            }\n        }\n        \n        if (!improved) break;\n    }\n}\n\nint main() {\n    vector<Seed> seeds(SEED_COUNT);\n    vector<int> sums(SEED_COUNT);\n    \n    // Read initial seeds\n    for (int i = 0; i < SEED_COUNT; ++i) {\n        for (int j = 0; j < M; ++j) {\n            scanf(\"%d\", &seeds[i][j]);\n        }\n        sums[i] = accumulate(seeds[i].begin(), seeds[i].end(), 0);\n    }\n    \n    for (int t = 0; t < T; ++t) {\n        // Select seeds\n        vector<int> selected = select_seeds(seeds, sums);\n        \n        // Place seeds\n        vector<vector<int>> grid(N, vector<int>(N, -1));\n        place_seeds(seeds, sums, selected, grid);\n        \n        // Output the grid\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                printf(\"%d\", grid[i][j]);\n                if (j < N - 1) printf(\" \");\n                else printf(\"\\n\");\n            }\n        }\n        fflush(stdout);\n        \n        // Read new seeds\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            for (int j = 0; j < M; ++j) {\n                scanf(\"%d\", &seeds[i][j]);\n            }\n            sums[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 <climits>\n\nusing namespace std;\n\nstruct Point {\n    int x, y;\n    Point(int x = 0, int y = 0) : x(x), y(y) {}\n};\n\nint manhattan(const Point& a, const Point& b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, V;\n    cin >> N >> M >> V;\n    \n    vector<string> s_grid(N), t_grid(N);\n    for (int i = 0; i < N; ++i) cin >> s_grid[i];\n    for (int i = 0; i < N; ++i) cin >> t_grid[i];\n    \n    vector<Point> pickups, dropoffs;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (s_grid[i][j] == '1' && t_grid[i][j] == '0') pickups.push_back(Point(i, j));\n            if (s_grid[i][j] == '0' && t_grid[i][j] == '1') dropoffs.push_back(Point(i, j));\n        }\n    }\n    \n    int sum_x = 0, sum_y = 0;\n    for (const auto& p : pickups) { sum_x += p.x; sum_y += p.y; }\n    int cx = pickups.empty() ? 0 : sum_x / pickups.size();\n    int cy = pickups.empty() ? 0 : sum_y / pickups.size();\n    \n    // Try multiple starting positions\n    vector<pair<int,int>> starts = {{cx, cy}, {0, 0}, {N/2, N/2}, {N-1, N-1}};\n    \n    int best_start_x = cx, best_start_y = cy;\n    int best_total = INT_MAX;\n    vector<int> best_order;\n    \n    for (auto [sx, sy] : starts) {\n        vector<int> order;\n        vector<bool> used(pickups.size(), false);\n        int rx = sx, ry = sy;\n        int total = 0;\n        vector<bool> du(dropoffs.size(), false);\n        \n        for (size_t step = 0; step < pickups.size(); ++step) {\n            int best = -1, bd = INT_MAX;\n            for (size_t i = 0; i < pickups.size(); ++i) {\n                if (!used[i]) {\n                    int dist = manhattan(Point(rx, ry), pickups[i]);\n                    if (dist < bd) { bd = dist; best = i; }\n                }\n            }\n            total += bd;\n            order.push_back(best);\n            rx = pickups[best].x; ry = pickups[best].y;\n            used[best] = true;\n            \n            int best_d = -1, bdd = INT_MAX;\n            for (size_t j = 0; j < dropoffs.size(); ++j) {\n                if (!du[j]) {\n                    int dist = manhattan(Point(rx, ry), dropoffs[j]);\n                    if (dist < bdd) { bdd = dist; best_d = j; }\n                }\n            }\n            total += bdd;\n            rx = dropoffs[best_d].x; ry = dropoffs[best_d].y;\n            du[best_d] = true;\n        }\n        \n        if (total < best_total) {\n            best_total = total;\n            best_start_x = sx;\n            best_start_y = sy;\n            best_order = order;\n        }\n    }\n    \n    cout << \"1\\n\" << best_start_x << \" \" << best_start_y << \"\\n\";\n    \n    int rx = best_start_x, ry = best_start_y;\n    vector<string> turns;\n    vector<bool> dropoff_used(dropoffs.size(), false);\n    \n    for (int idx : best_order) {\n        while (rx != pickups[idx].x) { turns.push_back(rx < pickups[idx].x ? \"D.\" : \"U.\"); rx += rx < pickups[idx].x ? 1 : -1; }\n        while (ry != pickups[idx].y) { turns.push_back(ry < pickups[idx].y ? \"R.\" : \"L.\"); ry += ry < pickups[idx].y ? 1 : -1; }\n        turns.push_back(\".P\");\n        \n        int best_dropoff = -1, bd = INT_MAX;\n        for (size_t j = 0; j < dropoffs.size(); ++j) {\n            if (!dropoff_used[j]) {\n                int dist = manhattan(Point(rx, ry), dropoffs[j]);\n                if (dist < bd) { bd = dist; best_dropoff = j; }\n            }\n        }\n        \n        while (rx != dropoffs[best_dropoff].x) { turns.push_back(rx < dropoffs[best_dropoff].x ? \"D.\" : \"U.\"); rx += rx < dropoffs[best_dropoff].x ? 1 : -1; }\n        while (ry != dropoffs[best_dropoff].y) { turns.push_back(ry < dropoffs[best_dropoff].y ? \"R.\" : \"L.\"); ry += ry < dropoffs[best_dropoff].y ? 1 : -1; }\n        turns.push_back(\".P\");\n        dropoff_used[best_dropoff] = true;\n    }\n    \n    for (const string& turn : turns) cout << turn << \"\\n\";\n    \n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <cmath>\n#include <unordered_map>\n#include <climits>\n#include <queue>\n#include <chrono>\n\nusing namespace std;\n\nstruct Point {\n    int x, y, w;\n};\n\n// 2D Fenwick Tree for point counting\nclass Fenwick2D {\n    int n, m;\n    vector<vector<int>> tree;\n    \npublic:\n    Fenwick2D(int n, int m) : n(n), m(m), tree(n + 1, vector<int>(m + 1, 0)) {}\n    \n    void update(int x, int y, int delta) {\n        for (int i = x + 1; i <= n; i += i & -i)\n            for (int j = y + 1; j <= m; j += j & -j)\n                tree[i][j] += delta;\n    }\n    \n    int query(int x, int y) const {\n        int sum = 0;\n        for (int i = x + 1; i > 0; i -= i & -i)\n            for (int j = y + 1; j > 0; j -= j & -j)\n                sum += tree[i][j];\n        return sum;\n    }\n    \n    int query(int x1, int y1, int x2, int y2) const {\n        if (x1 > x2 || y1 > y2) return 0;\n        return query(x2, y2) - query(x1-1, y2) - query(x2, y1-1) + query(x1-1, y1-1);\n    }\n};\n\n// K-means++ clustering\nvector<pair<int, int>> cluster_points(const vector<Point>& points, int k, mt19937& rng) {\n    int n = points.size();\n    if (n == 0) return {};\n    if (k >= n) {\n        vector<pair<int, int>> centroids;\n        for (const auto& p : points) {\n            centroids.emplace_back(p.x, p.y);\n        }\n        return centroids;\n    }\n    \n    vector<pair<int, int>> centroids(k);\n    \n    uniform_int_distribution<int> dist(0, n-1);\n    centroids[0] = {points[dist(rng)].x, points[dist(rng)].y};\n    \n    for (int i = 1; i < k; ++i) {\n        vector<double> distances(n);\n        double total = 0;\n        for (int j = 0; j < n; ++j) {\n            double min_dist = 1e18;\n            for (int c = 0; c < i; ++c) {\n                double dx = points[j].x - centroids[c].first;\n                double dy = points[j].y - centroids[c].second;\n                double d = dx*dx + dy*dy;\n                min_dist = min(min_dist, d);\n            }\n            distances[j] = min_dist;\n            total += min_dist;\n        }\n        \n        uniform_real_distribution<double> real_dist(0, total);\n        double r = real_dist(rng);\n        double sum = 0;\n        for (int j = 0; j < n; ++j) {\n            sum += distances[j];\n            if (sum >= r) {\n                centroids[i] = {points[j].x, points[j].y};\n                break;\n            }\n        }\n    }\n    \n    vector<int> assignments(n);\n    for (int iter = 0; iter < 20; ++iter) {\n        bool changed = false;\n        \n        for (int j = 0; j < n; ++j) {\n            int best = 0;\n            long long best_dist = LLONG_MAX;\n            for (int i = 0; i < k; ++i) {\n                long long dx = points[j].x - centroids[i].first;\n                long long dy = points[j].y - centroids[i].second;\n                long long d = dx*dx + dy*dy;\n                if (d < best_dist) {\n                    best_dist = d;\n                    best = i;\n                }\n            }\n            if (assignments[j] != best) {\n                assignments[j] = best;\n                changed = true;\n            }\n        }\n        \n        if (!changed) break;\n        \n        vector<int> counts(k, 0);\n        vector<long long> sum_x(k, 0), sum_y(k, 0);\n        for (int j = 0; j < n; ++j) {\n            int cluster = assignments[j];\n            counts[cluster]++;\n            sum_x[cluster] += points[j].x;\n            sum_y[cluster] += points[j].y;\n        }\n        \n        for (int i = 0; i < k; ++i) {\n            if (counts[i] > 0) {\n                centroids[i].first = sum_x[i] / counts[i];\n                centroids[i].second = sum_y[i] / counts[i];\n            }\n        }\n    }\n    \n    return centroids;\n}\n\n// Function to evaluate a rectangle\nint evaluate_rect(const Fenwick2D& fenw, const vector<int>& xs, const vector<int>& ys, \n                  int l, int r, int b, int t) {\n    int l_idx = lower_bound(xs.begin(), xs.end(), l) - xs.begin();\n    int r_idx = upper_bound(xs.begin(), xs.end(), r) - xs.begin() - 1;\n    int b_idx = lower_bound(ys.begin(), ys.end(), b) - ys.begin();\n    int t_idx = upper_bound(ys.begin(), ys.end(), t) - ys.begin() - 1;\n    \n    if (l_idx > r_idx || b_idx > t_idx) return -1000000;\n    return fenw.query(l_idx, b_idx, r_idx, t_idx);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    cin >> N;\n    \n    vector<Point> mackerels(N), sardines(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> mackerels[i].x >> mackerels[i].y;\n        mackerels[i].w = 1;\n    }\n    for (int i = 0; i < N; ++i) {\n        cin >> sardines[i].x >> sardines[i].y;\n        sardines[i].w = -1;\n    }\n    \n    // Combine all points\n    vector<Point> all_points;\n    all_points.reserve(2 * N);\n    all_points.insert(all_points.end(), mackerels.begin(), mackerels.end());\n    all_points.insert(all_points.end(), sardines.begin(), sardines.end());\n    \n    // Compress coordinates\n    vector<int> xs, ys;\n    for (const auto& p : all_points) {\n        xs.push_back(p.x);\n        ys.push_back(p.y);\n    }\n    sort(xs.begin(), xs.end());\n    xs.erase(unique(xs.begin(), xs.end()), xs.end());\n    sort(ys.begin(), ys.end());\n    ys.erase(unique(ys.begin(), ys.end()), ys.end());\n    \n    int X = xs.size(), Y = ys.size();\n    \n    // Build Fenwick tree\n    Fenwick2D fenw(X, Y);\n    for (const auto& p : all_points) {\n        int xi = lower_bound(xs.begin(), xs.end(), p.x) - xs.begin();\n        int yi = lower_bound(ys.begin(), ys.end(), p.y) - ys.begin();\n        fenw.update(xi, yi, p.w);\n    }\n    \n    // Run multiple attempts with different random seeds\n    int best_score = -1000000;\n    tuple<int, int, int, int> best_rect;\n    \n    for (int attempt = 0; attempt < 5; ++attempt) {\n        random_device rd;\n        mt19937 rng(rd() + attempt);\n        \n        // Cluster mackerels to find promising regions\n        vector<pair<int, int>> all_centroids;\n        for (int k : {8, 12, 16, 20, 25, 30}) {\n            auto centroids = cluster_points(mackerels, k, rng);\n            all_centroids.insert(all_centroids.end(), centroids.begin(), centroids.end());\n        }\n        \n        // Candidate rectangles\n        vector<tuple<int, int, int, int>> candidates;\n        \n        // Add bounding box of all mackerels\n        int min_x = 100000, max_x = 0, min_y = 100000, max_y = 0;\n        for (const auto& p : mackerels) {\n            min_x = min(min_x, p.x);\n            max_x = max(max_x, p.x);\n            min_y = min(min_y, p.y);\n            max_y = max(max_y, p.y);\n        }\n        candidates.emplace_back(min_x, max_x, min_y, max_y);\n        \n        // Add rectangles around cluster centers with various sizes\n        for (const auto& center : all_centroids) {\n            int cx = center.first, cy = center.second;\n            for (int size : {2000, 4000, 6000, 8000, 10000, 15000, 20000}) {\n                int left = max(0, cx - size);\n                int right = min(100000, cx + size);\n                int bottom = max(0, cy - size);\n                int top = min(100000, cy + size);\n                candidates.emplace_back(left, right, bottom, top);\n            }\n        }\n        \n        // Add rectangles based on point pairs\n        uniform_int_distribution<int> point_dist(0, N-1);\n        for (int i = 0; i < 500; ++i) {\n            int idx1 = point_dist(rng);\n            int idx2 = point_dist(rng);\n            int left = min(mackerels[idx1].x, mackerels[idx2].x);\n            int right = max(mackerels[idx1].x, mackerels[idx2].x);\n            int bottom = min(mackerels[idx1].y, mackerels[idx2].y);\n            int top = max(mackerels[idx1].y, mackerels[idx2].y);\n            \n            uniform_int_distribution<int> expand_dist(500, 5000);\n            int expand = expand_dist(rng);\n            left = max(0, left - expand);\n            right = min(100000, right + expand);\n            bottom = max(0, bottom - expand);\n            top = min(100000, top + expand);\n            \n            candidates.emplace_back(left, right, bottom, top);\n        }\n        \n        // Add rectangles that avoid sardine-dense areas\n        auto sardine_centroids = cluster_points(sardines, 8, rng);\n        for (const auto& sc : sardine_centroids) {\n            int sx = sc.first, sy = sc.second;\n            \n            for (int avoid_size : {3000, 5000, 8000}) {\n                for (int dx : {-1, 1}) {\n                    for (int dy : {-1, 1}) {\n                        int left = (dx == -1) ? 0 : min(100000, sx + avoid_size);\n                        int right = (dx == -1) ? max(0, sx - avoid_size) : 100000;\n                        int bottom = (dy == -1) ? 0 : min(100000, sy + avoid_size);\n                        int top = (dy == -1) ? max(0, sy - avoid_size) : 100000;\n                        \n                        if (left < right && bottom < top) {\n                            candidates.emplace_back(left, right, bottom, top);\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Add bounding boxes of random subsets of mackerels\n        for (int subset_size : {10, 20, 50, 100}) {\n            for (int i = 0; i < 50; ++i) {\n                vector<int> indices(N);\n                iota(indices.begin(), indices.end(), 0);\n                shuffle(indices.begin(), indices.end(), rng);\n                \n                int left = 100000, right = 0, bottom = 100000, top = 0;\n                for (int j = 0; j < subset_size; ++j) {\n                    int idx = indices[j];\n                    left = min(left, mackerels[idx].x);\n                    right = max(right, mackerels[idx].x);\n                    bottom = min(bottom, mackerels[idx].y);\n                    top = max(top, mackerels[idx].y);\n                }\n                \n                int expand = 1000;\n                left = max(0, left - expand);\n                right = min(100000, right + expand);\n                bottom = max(0, bottom - expand);\n                top = min(100000, top + expand);\n                \n                candidates.emplace_back(left, right, bottom, top);\n            }\n        }\n        \n        // Add convex hull bounding boxes for clusters\n        for (int k : {5, 10, 15}) {\n            auto cluster_centroids = cluster_points(mackerels, k, rng);\n            for (const auto& centroid : cluster_centroids) {\n                vector<pair<int, int>> distances;\n                for (int i = 0; i < N; ++i) {\n                    int dx = mackerels[i].x - centroid.first;\n                    int dy = mackerels[i].y - centroid.second;\n                    int dist = dx*dx + dy*dy;\n                    distances.emplace_back(dist, i);\n                }\n                sort(distances.begin(), distances.end());\n                \n                int take = max(1, N / 5);\n                int left = 100000, right = 0, bottom = 100000, top = 0;\n                for (int i = 0; i < take; ++i) {\n                    int idx = distances[i].second;\n                    left = min(left, mackerels[idx].x);\n                    right = max(right, mackerels[idx].x);\n                    bottom = min(bottom, mackerels[idx].y);\n                    top = max(top, mackerels[idx].y);\n                }\n                \n                if (left < right && bottom < top) {\n                    candidates.emplace_back(left, right, bottom, top);\n                }\n            }\n        }\n        \n        // Evaluate candidates and keep top 100 for local optimization\n        vector<pair<int, tuple<int, int, int, int>>> scored_candidates;\n        for (const auto& rect : candidates) {\n            auto [l, r, b, t] = rect;\n            if (l >= r || b >= t) continue;\n            \n            int score = evaluate_rect(fenw, xs, ys, l, r, b, t);\n            if (score > 0) {\n                scored_candidates.emplace_back(score, rect);\n            }\n        }\n        \n        sort(scored_candidates.begin(), scored_candidates.end(), \n             [](const auto& a, const auto& b) { return a.first > b.first; });\n        \n        vector<tuple<int, int, int, int>> top_candidates;\n        for (int i = 0; i < min(100, (int)scored_candidates.size()); ++i) {\n            top_candidates.push_back(scored_candidates[i].second);\n        }\n        \n        // Local optimization on top candidates\n        for (auto rect : top_candidates) {\n            auto [L, R, B, T] = rect;\n            int current_score = evaluate_rect(fenw, xs, ys, L, R, B, T);\n            \n            // Local optimization with exhaustive nearby coordinate search\n            bool improved = true;\n            int iterations = 0;\n            while (improved && iterations < 30) {\n                improved = false;\n                iterations++;\n                \n                int l_idx = lower_bound(xs.begin(), xs.end(), L) - xs.begin();\n                int r_idx = upper_bound(xs.begin(), xs.end(), R) - xs.begin() - 1;\n                int b_idx = lower_bound(ys.begin(), ys.end(), B) - ys.begin();\n                int t_idx = upper_bound(ys.begin(), ys.end(), T) - ys.begin() - 1;\n                \n                // Try moving boundaries to nearby coordinates\n                for (int i = max(0, l_idx - 50); i <= min(X-1, l_idx + 50); ++i) {\n                    if (i == l_idx) continue;\n                    int newL = xs[i];\n                    if (newL >= 0 && newL < R) {\n                        int score = evaluate_rect(fenw, xs, ys, newL, R, B, T);\n                        if (score > current_score) {\n                            current_score = score;\n                            L = newL;\n                            l_idx = i;\n                            improved = true;\n                        }\n                    }\n                }\n                \n                for (int i = max(0, r_idx - 50); i <= min(X-1, r_idx + 50); ++i) {\n                    if (i == r_idx) continue;\n                    int newR = xs[i];\n                    if (newR > L && newR <= 100000) {\n                        int score = evaluate_rect(fenw, xs, ys, L, newR, B, T);\n                        if (score > current_score) {\n                            current_score = score;\n                            R = newR;\n                            r_idx = i;\n                            improved = true;\n                        }\n                    }\n                }\n                \n                for (int i = max(0, b_idx - 50); i <= min(Y-1, b_idx + 50); ++i) {\n                    if (i == b_idx) continue;\n                    int newB = ys[i];\n                    if (newB >= 0 && newB < T) {\n                        int score = evaluate_rect(fenw, xs, ys, L, R, newB, T);\n                        if (score > current_score) {\n                            current_score = score;\n                            B = newB;\n                            b_idx = i;\n                            improved = true;\n                        }\n                    }\n                }\n                \n                for (int i = max(0, t_idx - 50); i <= min(Y-1, t_idx + 50); ++i) {\n                    if (i == t_idx) continue;\n                    int newT = ys[i];\n                    if (newT > B && newT <= 100000) {\n                        int score = evaluate_rect(fenw, xs, ys, L, R, B, newT);\n                        if (score > current_score) {\n                            current_score = score;\n                            T = newT;\n                            t_idx = i;\n                            improved = true;\n                        }\n                    }\n                }\n                \n                // Also try fixed step adjustments\n                for (int delta : {-1000, -500, -200, 200, 500, 1000}) {\n                    int newL = L + delta;\n                    if (newL >= 0 && newL < R) {\n                        int score = evaluate_rect(fenw, xs, ys, newL, R, B, T);\n                        if (score > current_score) {\n                            current_score = score;\n                            L = newL;\n                            improved = true;\n                        }\n                    }\n                    \n                    int newR = R + delta;\n                    if (newR > L && newR <= 100000) {\n                        int score = evaluate_rect(fenw, xs, ys, L, newR, B, T);\n                        if (score > current_score) {\n                            current_score = score;\n                            R = newR;\n                            improved = true;\n                        }\n                    }\n                    \n                    int newB = B + delta;\n                    if (newB >= 0 && newB < T) {\n                        int score = evaluate_rect(fenw, xs, ys, L, R, newB, T);\n                        if (score > current_score) {\n                            current_score = score;\n                            B = newB;\n                            improved = true;\n                        }\n                    }\n                    \n                    int newT = T + delta;\n                    if (newT > B && newT <= 100000) {\n                        int score = evaluate_rect(fenw, xs, ys, L, R, B, newT);\n                        if (score > current_score) {\n                            current_score = score;\n                            T = newT;\n                            improved = true;\n                        }\n                    }\n                }\n            }\n            \n            if (current_score > best_score) {\n                best_score = current_score;\n                best_rect = {L, R, B, T};\n            }\n        }\n    }\n    \n    // Final refinement: try very small adjustments\n    auto [L, R, B, T] = best_rect;\n    for (int iter = 0; iter < 20; ++iter) {\n        bool improved = false;\n        \n        for (int delta : {-10, -5, -2, -1, 1, 2, 5, 10}) {\n            int newL = L + delta;\n            if (newL >= 0 && newL < R) {\n                int score = evaluate_rect(fenw, xs, ys, newL, R, B, T);\n                if (score > best_score) {\n                    best_score = score;\n                    L = newL;\n                    improved = true;\n                }\n            }\n            \n            int newR = R + delta;\n            if (newR > L && newR <= 100000) {\n                int score = evaluate_rect(fenw, xs, ys, L, newR, B, T);\n                if (score > best_score) {\n                    best_score = score;\n                    R = newR;\n                    improved = true;\n                }\n            }\n            \n            int newB = B + delta;\n            if (newB >= 0 && newB < T) {\n                int score = evaluate_rect(fenw, xs, ys, L, R, newB, T);\n                if (score > best_score) {\n                    best_score = score;\n                    B = newB;\n                    improved = true;\n                }\n            }\n            \n            int newT = T + delta;\n            if (newT > B && newT <= 100000) {\n                int score = evaluate_rect(fenw, xs, ys, L, R, B, newT);\n                if (score > best_score) {\n                    best_score = score;\n                    T = newT;\n                    improved = true;\n                }\n            }\n        }\n        \n        if (!improved) break;\n    }\n    \n    best_rect = {L, R, B, T};\n    \n    // Output the best rectangle\n    auto [outL, outR, outB, outT] = best_rect;\n    cout << \"4\\n\";\n    cout << outL << \" \" << outB << \"\\n\";\n    cout << outR << \" \" << outB << \"\\n\";\n    cout << outR << \" \" << outT << \"\\n\";\n    cout << outL << \" \" << outT << \"\\n\";\n    \n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <tuple>\n\nusing namespace std;\n\nstruct Rectangle {\n    int x, y, w, h;\n    int right() const { return x + w; }\n    int bottom() const { return y + h; }\n};\n\nint compute_y0(int x0, int width, const vector<int>& placed_indices, const Rectangle rect_of_index[]) {\n    int y0 = 0;\n    for (int idx : placed_indices) {\n        const Rectangle& R = rect_of_index[idx];\n        if (x0 < R.right() && x0 + width > R.x) {\n            y0 = max(y0, R.bottom());\n        }\n    }\n    return y0;\n}\n\nint compute_x0(int y0, int height, const vector<int>& placed_indices, const Rectangle rect_of_index[]) {\n    int x0 = 0;\n    for (int idx : placed_indices) {\n        const Rectangle& R = rect_of_index[idx];\n        if (y0 < R.bottom() && y0 + height > R.y) {\n            x0 = max(x0, R.right());\n        }\n    }\n    return x0;\n}\n\nvoid solve_turn(const vector<int>& w, const vector<int>& h, int N, mt19937& rng) {\n    vector<int> placed_indices;\n    Rectangle rect_of_index[N];\n    bool is_placed[N] = {false};\n    int W = 0, H = 0;\n    \n    vector<tuple<int, int, char, int>> ops;\n    \n    uniform_real_distribution<double> dist_real(0.0, 1.0);\n    uniform_int_distribution<int> dist_binary(0, 1);\n    \n    const double p_place = 0.92;  // Slightly higher placement probability\n    const int ATTEMPTS = 8;       // More attempts for better exploration\n    \n    for (int i = 0; i < N; ++i) {\n        if (dist_real(rng) >= p_place) continue;\n        \n        // Try multiple attempts and keep the best that satisfies condition\n        int best_score = 1e9;\n        int best_r = 0, best_b = -1;\n        char best_d = 'U';\n        int best_newW = W, best_newH = H;\n        int best_x0 = 0, best_y0 = 0;\n        bool found_valid = false;\n        \n        for (int attempt = 0; attempt < ATTEMPTS; ++attempt) {\n            // Random rotation and direction\n            int r = dist_binary(rng);\n            char d = (dist_binary(rng) == 0) ? 'U' : 'L';\n            int width = (r == 0) ? w[i] : h[i];\n            int height = (r == 0) ? h[i] : w[i];\n            \n            // Find best reference for this rotation and direction\n            int best_b_this = -1;\n            int best_score_this = 1e9;\n            int best_newW_this = W, best_newH_this = H;\n            int best_x0_this = 0, best_y0_this = 0;\n            \n            // Try all references\n            vector<int> b_candidates = {-1};\n            for (int idx : placed_indices) b_candidates.push_back(idx);\n            \n            for (int b : b_candidates) {\n                int x0, y0;\n                if (d == 'U') {\n                    x0 = (b == -1) ? 0 : rect_of_index[b].right();\n                    y0 = compute_y0(x0, width, placed_indices, rect_of_index);\n                } else {\n                    y0 = (b == -1) ? 0 : rect_of_index[b].bottom();\n                    x0 = compute_x0(y0, height, placed_indices, rect_of_index);\n                }\n                \n                int newW = max(W, x0 + width);\n                int newH = max(H, y0 + height);\n                int score = newW + newH;\n                \n                if (score < best_score_this) {\n                    best_score_this = score;\n                    best_b_this = b;\n                    best_newW_this = newW;\n                    best_newH_this = newH;\n                    best_x0_this = x0;\n                    best_y0_this = y0;\n                }\n            }\n            \n            // Check if this attempt is better and satisfies condition\n            if (best_score_this < best_score && \n                best_score_this <= W + H + w[i] + h[i]) {\n                best_score = best_score_this;\n                best_r = r;\n                best_d = d;\n                best_b = best_b_this;\n                best_newW = best_newW_this;\n                best_newH = best_newH_this;\n                best_x0 = best_x0_this;\n                best_y0 = best_y0_this;\n                found_valid = true;\n            }\n        }\n        \n        // Place if we found a valid placement\n        if (found_valid) {\n            rect_of_index[i] = {best_x0, best_y0, \n                               (best_r == 0) ? w[i] : h[i], \n                               (best_r == 0) ? h[i] : w[i]};\n            is_placed[i] = true;\n            placed_indices.push_back(i);\n            W = best_newW;\n            H = best_newH;\n            ops.emplace_back(i, best_r, best_d, best_b);\n        }\n    }\n    \n    // Output operations\n    cout << ops.size() << '\\n';\n    for (const auto& [p, r, d, b] : ops) {\n        cout << p << ' ' << r << ' ' << d << ' ' << b << '\\n';\n    }\n    cout.flush();\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, T, sigma;\n    cin >> N >> T >> sigma;\n    vector<int> w(N), h(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> w[i] >> h[i];\n    }\n    \n    random_device rd;\n    mt19937 rng(rd());\n    \n    for (int t = 0; t < T; ++t) {\n        solve_turn(w, h, N, rng);\n        int Wp, Hp;\n        cin >> Wp >> Hp;\n    }\n    \n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <random>\n#include <cmath>\n#include <numeric>\n#include <chrono>\nusing namespace std;\n\nint N, H;\nvector<vector<int>> adj;\nvector<int> A;\n\n// Check if changing vertex v to newd is feasible (without modifying state)\nbool can_change(int v, int newd, const vector<int>& depth) {\n    if (newd > 0) {\n        bool has = false;\n        for (int u : adj[v]) {\n            if (depth[u] == newd - 1) {\n                has = true;\n                break;\n            }\n        }\n        if (!has) return false;\n    }\n    for (int u : adj[v]) {\n        if (depth[u] == 0) continue;\n        bool has = false;\n        for (int w : adj[u]) {\n            int d_w = (w == v) ? newd : depth[w];\n            if (d_w == depth[u] - 1) {\n                has = true;\n                break;\n            }\n        }\n        if (!has) return false;\n    }\n    return true;\n}\n\n// Try to raise vertex v to target depth, recursively raising neighbors if needed\nbool raise_to(vector<int>& depth, int v, int target, vector<bool>& visited) {\n    if (depth[v] >= target) return true;\n    if (target > H) return false;\n    \n    if (can_change(v, target, depth)) {\n        depth[v] = target;\n        return true;\n    }\n    \n    visited[v] = true;\n    for (int u : adj[v]) {\n        if (visited[u]) continue;\n        if (depth[u] < target - 1) {\n            if (raise_to(depth, u, target - 1, visited)) {\n                if (can_change(v, target, depth)) {\n                    depth[v] = target;\n                    visited[v] = false;\n                    return true;\n                }\n            }\n        }\n    }\n    visited[v] = false;\n    return false;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    cin >> N >> M >> H;\n    A.resize(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n    adj.resize(N);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // ---------- 1. Compute H-neighborhoods ----------\n    vector<vector<int>> cover(N);\n    for (int v = 0; v < N; ++v) {\n        vector<int> dist(N, -1);\n        queue<int> q;\n        dist[v] = 0;\n        q.push(v);\n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            if (dist[u] > H) continue;\n            cover[v].push_back(u);\n            if (dist[u] == H) continue;\n            for (int w : adj[u]) {\n                if (dist[w] == -1) {\n                    dist[w] = dist[u] + 1;\n                    q.push(w);\n                }\n            }\n        }\n    }\n\n    // ---------- 2. Greedy set cover to choose roots ----------\n    vector<bool> covered(N, false);\n    vector<int> roots;\n    int remaining = N;\n    while (remaining > 0) {\n        int best_v = -1, best_cnt = -1;\n        for (int v = 0; v < N; ++v) {\n            int cnt = 0;\n            for (int u : cover[v]) if (!covered[u]) cnt++;\n            if (cnt > best_cnt) {\n                best_cnt = cnt;\n                best_v = v;\n            } else if (cnt == best_cnt && cnt > 0) {\n                if (best_v == -1 || A[v] < A[best_v] || \n                    (A[v] == A[best_v] && adj[v].size() > adj[best_v].size())) {\n                    best_v = v;\n                }\n            }\n        }\n        if (best_v == -1) break;\n        roots.push_back(best_v);\n        for (int u : cover[best_v]) if (!covered[u]) {\n            covered[u] = true;\n            --remaining;\n        }\n    }\n\n    // ---------- 3. Multi-source BFS to get initial depths ----------\n    vector<int> depth(N, -1);\n    queue<int> q;\n    for (int r : roots) {\n        depth[r] = 0;\n        q.push(r);\n    }\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (int v : adj[u]) {\n            if (depth[v] == -1) {\n                depth[v] = depth[u] + 1;\n                q.push(v);\n            }\n        }\n    }\n    long long cur_obj = 0;\n    for (int v = 0; v < N; ++v) cur_obj += depth[v] * A[v];\n\n    // ---------- 4. Simulated Annealing ----------\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> rand_v(0, N-1);\n    uniform_int_distribution<int> rand_d(0, H);\n    uniform_real_distribution<double> rand_float(0.0, 1.0);\n\n    const int ITER = 2500000;\n    double temp = 1000.0;\n    const double cooling = 0.999996;\n\n    for (int iter = 0; iter < ITER; ++iter) {\n        int v = rand_v(rng);\n        int oldd = depth[v];\n        int newd = rand_d(rng);\n        if (newd == oldd) continue;\n        int delta = (newd - oldd) * A[v];\n        if (!can_change(v, newd, depth)) continue;\n        if (delta >= 0 || rand_float(rng) < exp(delta / temp)) {\n            depth[v] = newd;\n            cur_obj += delta;\n        }\n        temp *= cooling;\n    }\n\n    // ---------- 5. Greedy improvement with recursive raising to H ----------\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    vector<bool> visited(N, false);\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int v : order) {\n            if (depth[v] == H) continue;\n            if (raise_to(depth, v, H, visited)) {\n                long long new_obj = 0;\n                for (int i = 0; i < N; ++i) new_obj += depth[i] * A[i];\n                if (new_obj > cur_obj) {\n                    cur_obj = new_obj;\n                    improved = true;\n                }\n            }\n        }\n    }\n\n    // ---------- 6. Targeted improvement for vertices at H-1 ----------\n    for (int v = 0; v < N; ++v) {\n        if (depth[v] == H-1) {\n            if (raise_to(depth, v, H, visited)) {\n                long long new_obj = 0;\n                for (int i = 0; i < N; ++i) new_obj += depth[i] * A[i];\n                if (new_obj > cur_obj) {\n                    cur_obj = new_obj;\n                }\n            }\n        }\n    }\n\n    // ---------- 7. Multiple random sweeps ----------\n    for (int sweep = 0; sweep < 4; ++sweep) {\n        vector<int> rand_order(N);\n        iota(rand_order.begin(), rand_order.end(), 0);\n        shuffle(rand_order.begin(), rand_order.end(), rng);\n        for (int v : rand_order) {\n            while (depth[v] < H) {\n                int newd = depth[v] + 1;\n                if (can_change(v, newd, depth)) {\n                    depth[v] = newd;\n                    cur_obj += A[v];\n                } else {\n                    break;\n                }\n            }\n        }\n    }\n\n    // ---------- 8. Final improvement for vertices at H-2 ----------\n    for (int v = 0; v < N; ++v) {\n        if (depth[v] == H-2) {\n            if (raise_to(depth, v, H, visited)) {\n                long long new_obj = 0;\n                for (int i = 0; i < N; ++i) new_obj += depth[i] * A[i];\n                if (new_obj > cur_obj) {\n                    cur_obj = new_obj;\n                }\n            }\n        }\n    }\n\n    // ---------- 9. Build parent pointers ----------\n    vector<int> parent(N, -1);\n    for (int v = 0; v < N; ++v) {\n        if (depth[v] == 0) continue;\n        for (int u : adj[v]) {\n            if (depth[u] == depth[v] - 1) {\n                parent[v] = u;\n                break;\n            }\n        }\n    }\n\n    // ---------- 10. Output ----------\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << parent[i];\n    }\n    cout << endl;\n\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 20;\nconst int TOP_K = 5;\n\nstruct Op {\n    int type; // 0:U,1:D,2:L,3:R\n    int idx;  // column for U/D, row for L/R\n    int k;    // number of shifts\n};\n\nstruct Candidate {\n    int i, j, dir;\n    int cost, count;\n    double ratio;\n};\n\n// Find the best operation on a given grid (without modifying it)\nCandidate best_op(const vector<vector<char>>& grid) {\n    int n = grid.size();\n    Candidate best = {-1, -1, -1, 0, 0, -1.0};\n    \n    auto is_safe = [&](int i, int j, int dir) -> bool {\n        if (dir == 0) { // up\n            for (int r = 0; r < i; ++r) {\n                if (grid[r][j] == 'o') return false;\n            }\n            return true;\n        } else if (dir == 1) { // down\n            for (int r = i+1; r < n; ++r) {\n                if (grid[r][j] == 'o') return false;\n            }\n            return true;\n        } else if (dir == 2) { // left\n            for (int c = 0; c < j; ++c) {\n                if (grid[i][c] == 'o') return false;\n            }\n            return true;\n        } else { // right\n            for (int c = j+1; c < n; ++c) {\n                if (grid[i][c] == 'o') return false;\n            }\n            return true;\n        }\n    };\n    \n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (grid[i][j] != 'x') continue;\n            for (int dir = 0; dir < 4; ++dir) {\n                if (!is_safe(i, j, dir)) continue;\n                int cost;\n                if (dir == 0) cost = i + 1;\n                else if (dir == 1) cost = n - i;\n                else if (dir == 2) cost = j + 1;\n                else cost = n - j;\n                \n                int count = 0;\n                if (dir == 0) { // up\n                    for (int r = 0; r <= i; ++r) {\n                        if (grid[r][j] == 'x') count++;\n                    }\n                } else if (dir == 1) { // down\n                    for (int r = i; r < n; ++r) {\n                        if (grid[r][j] == 'x') count++;\n                    }\n                } else if (dir == 2) { // left\n                    for (int c = 0; c <= j; ++c) {\n                        if (grid[i][c] == 'x') count++;\n                    }\n                } else { // right\n                    for (int c = j; c < n; ++c) {\n                        if (grid[i][c] == 'x') count++;\n                    }\n                }\n                \n                double ratio = static_cast<double>(count) / cost;\n                if (ratio > best.ratio || (ratio == best.ratio && cost < best.cost)) {\n                    best = {i, j, dir, cost, count, ratio};\n                }\n            }\n        }\n    }\n    return best;\n}\n\n// Apply an operation to a grid and return the new grid\nvector<vector<char>> apply_op(const vector<vector<char>>& grid, const Candidate& op) {\n    int n = grid.size();\n    vector<vector<char>> new_grid = grid;\n    if (op.dir == 0) { // up\n        for (int r = 0; r <= op.i; ++r) new_grid[r][op.j] = '.';\n    } else if (op.dir == 1) { // down\n        for (int r = op.i; r < n; ++r) new_grid[r][op.j] = '.';\n    } else if (op.dir == 2) { // left\n        for (int c = 0; c <= op.j; ++c) new_grid[op.i][c] = '.';\n    } else { // right\n        for (int c = op.j; c < n; ++c) new_grid[op.i][c] = '.';\n    }\n    return new_grid;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    int n;\n    cin >> n;\n    vector<string> board(n);\n    for (int i = 0; i < n; ++i) {\n        cin >> board[i];\n    }\n    \n    vector<vector<char>> grid(n, vector<char>(n));\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            grid[i][j] = board[i][j];\n        }\n    }\n    \n    vector<Op> ops;\n    \n    while (true) {\n        bool any_oni = false;\n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                if (grid[i][j] == 'x') {\n                    any_oni = true;\n                    break;\n                }\n            }\n            if (any_oni) break;\n        }\n        if (!any_oni) break;\n        \n        // Collect all possible operations with their ratios\n        vector<Candidate> candidates;\n        auto is_safe = [&](int i, int j, int dir) -> bool {\n            if (dir == 0) { // up\n                for (int r = 0; r < i; ++r) {\n                    if (grid[r][j] == 'o') return false;\n                }\n                return true;\n            } else if (dir == 1) { // down\n                for (int r = i+1; r < n; ++r) {\n                    if (grid[r][j] == 'o') return false;\n                }\n                return true;\n            } else if (dir == 2) { // left\n                for (int c = 0; c < j; ++c) {\n                    if (grid[i][c] == 'o') return false;\n                }\n                return true;\n            } else { // right\n                for (int c = j+1; c < n; ++c) {\n                    if (grid[i][c] == 'o') return false;\n                }\n                return true;\n            }\n        };\n        \n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                if (grid[i][j] != 'x') continue;\n                for (int dir = 0; dir < 4; ++dir) {\n                    if (!is_safe(i, j, dir)) continue;\n                    int cost;\n                    if (dir == 0) cost = i + 1;\n                    else if (dir == 1) cost = n - i;\n                    else if (dir == 2) cost = j + 1;\n                    else cost = n - j;\n                    \n                    int count = 0;\n                    if (dir == 0) { // up\n                        for (int r = 0; r <= i; ++r) {\n                            if (grid[r][j] == 'x') count++;\n                        }\n                    } else if (dir == 1) { // down\n                        for (int r = i; r < n; ++r) {\n                            if (grid[r][j] == 'x') count++;\n                        }\n                    } else if (dir == 2) { // left\n                        for (int c = 0; c <= j; ++c) {\n                            if (grid[i][c] == 'x') count++;\n                        }\n                    } else { // right\n                        for (int c = j; c < n; ++c) {\n                            if (grid[i][c] == 'x') count++;\n                        }\n                    }\n                    \n                    double ratio = static_cast<double>(count) / cost;\n                    candidates.push_back({i, j, dir, cost, count, ratio});\n                }\n            }\n        }\n        \n        // Sort by ratio descending, then by cost ascending\n        sort(candidates.begin(), candidates.end(), [](const Candidate& a, const Candidate& b) {\n            if (a.ratio != b.ratio) return a.ratio > b.ratio;\n            return a.cost < b.cost;\n        });\n        \n        // Keep only top TOP_K candidates\n        if (candidates.size() > TOP_K) {\n            candidates.resize(TOP_K);\n        }\n        \n        double best_combined_ratio = -1.0;\n        Candidate best_first = {-1, -1, -1, 0, 0, -1.0};\n        \n        for (const auto& first : candidates) {\n            // Apply first operation\n            vector<vector<char>> grid1 = apply_op(grid, first);\n            \n            // Find best second operation on grid1\n            Candidate second = best_op(grid1);\n            if (second.count == 0) {\n                double combined_ratio = static_cast<double>(first.count) / first.cost;\n                if (combined_ratio > best_combined_ratio || \n                    (combined_ratio == best_combined_ratio && first.count > best_first.count) ||\n                    (combined_ratio == best_combined_ratio && first.count == best_first.count && first.cost < best_first.cost)) {\n                    best_combined_ratio = combined_ratio;\n                    best_first = first;\n                }\n                continue;\n            }\n            \n            // Apply second operation\n            vector<vector<char>> grid2 = apply_op(grid1, second);\n            \n            // Find best third operation on grid2\n            Candidate third = best_op(grid2);\n            if (third.count == 0) {\n                double combined_ratio = static_cast<double>(first.count + second.count) / (first.cost + second.cost);\n                if (combined_ratio > best_combined_ratio || \n                    (combined_ratio == best_combined_ratio && first.count > best_first.count) ||\n                    (combined_ratio == best_combined_ratio && first.count == best_first.count && first.cost < best_first.cost)) {\n                    best_combined_ratio = combined_ratio;\n                    best_first = first;\n                }\n                continue;\n            }\n            \n            // Apply third operation\n            vector<vector<char>> grid3 = apply_op(grid2, third);\n            \n            // Find best fourth operation on grid3\n            Candidate fourth = best_op(grid3);\n            if (fourth.count == 0) {\n                double combined_ratio = static_cast<double>(first.count + second.count + third.count) / \n                                       (first.cost + second.cost + third.cost);\n                if (combined_ratio > best_combined_ratio || \n                    (combined_ratio == best_combined_ratio && first.count > best_first.count) ||\n                    (combined_ratio == best_combined_ratio && first.count == best_first.count && first.cost < best_first.cost)) {\n                    best_combined_ratio = combined_ratio;\n                    best_first = first;\n                }\n                continue;\n            }\n            \n            // Apply fourth operation\n            vector<vector<char>> grid4 = apply_op(grid3, fourth);\n            \n            // Find best fifth operation on grid4\n            Candidate fifth = best_op(grid4);\n            if (fifth.count == 0) {\n                double combined_ratio = static_cast<double>(first.count + second.count + third.count + fourth.count) / \n                                       (first.cost + second.cost + third.cost + fourth.cost);\n                if (combined_ratio > best_combined_ratio || \n                    (combined_ratio == best_combined_ratio && first.count > best_first.count) ||\n                    (combined_ratio == best_combined_ratio && first.count == best_first.count && first.cost < best_first.cost)) {\n                    best_combined_ratio = combined_ratio;\n                    best_first = first;\n                }\n                continue;\n            }\n            \n            // Apply fifth operation\n            vector<vector<char>> grid5 = apply_op(grid4, fifth);\n            \n            // Find best sixth operation on grid5\n            Candidate sixth = best_op(grid5);\n            if (sixth.count == 0) {\n                double combined_ratio = static_cast<double>(first.count + second.count + third.count + fourth.count + fifth.count) / \n                                       (first.cost + second.cost + third.cost + fourth.cost + fifth.cost);\n                if (combined_ratio > best_combined_ratio || \n                    (combined_ratio == best_combined_ratio && first.count > best_first.count) ||\n                    (combined_ratio == best_combined_ratio && first.count == best_first.count && first.cost < best_first.cost)) {\n                    best_combined_ratio = combined_ratio;\n                    best_first = first;\n                }\n                continue;\n            }\n            \n            // Apply sixth operation\n            vector<vector<char>> grid6 = apply_op(grid5, sixth);\n            \n            // Find best seventh operation on grid6\n            Candidate seventh = best_op(grid6);\n            double combined_ratio;\n            if (seventh.count == 0) {\n                combined_ratio = static_cast<double>(first.count + second.count + third.count + fourth.count + fifth.count + sixth.count) / \n                                 (first.cost + second.cost + third.cost + fourth.cost + fifth.cost + sixth.cost);\n            } else {\n                combined_ratio = static_cast<double>(first.count + second.count + third.count + fourth.count + fifth.count + sixth.count + seventh.count) / \n                                 (first.cost + second.cost + third.cost + fourth.cost + fifth.cost + sixth.cost + seventh.cost);\n            }\n            \n            if (combined_ratio > best_combined_ratio || \n                (combined_ratio == best_combined_ratio && first.count > best_first.count) ||\n                (combined_ratio == best_combined_ratio && first.count == best_first.count && first.cost < best_first.cost)) {\n                best_combined_ratio = combined_ratio;\n                best_first = first;\n            }\n        }\n        \n        // Apply the chosen first operation\n        if (best_first.dir == 0) { // up\n            int k = best_first.i + 1;\n            ops.push_back({0, best_first.j, k});\n            for (int r = 0; r <= best_first.i; ++r) grid[r][best_first.j] = '.';\n        } else if (best_first.dir == 1) { // down\n            int k = n - best_first.i;\n            ops.push_back({1, best_first.j, k});\n            for (int r = best_first.i; r < n; ++r) grid[r][best_first.j] = '.';\n        } else if (best_first.dir == 2) { // left\n            int k = best_first.j + 1;\n            ops.push_back({2, best_first.i, k});\n            for (int c = 0; c <= best_first.j; ++c) grid[best_first.i][c] = '.';\n        } else { // right\n            int k = n - best_first.j;\n            ops.push_back({3, best_first.i, k});\n            for (int c = best_first.j; c < n; ++c) grid[best_first.i][c] = '.';\n        }\n    }\n    \n    // Merge operations\n    unordered_map<int, int> up_ops;   // column -> max k\n    unordered_map<int, int> down_ops; // column -> max k\n    unordered_map<int, int> left_ops; // row -> max k\n    unordered_map<int, int> right_ops; // row -> max k\n    \n    for (const auto& op : ops) {\n        if (op.type == 0) { // U\n            if (up_ops.find(op.idx) == up_ops.end() || op.k > up_ops[op.idx]) {\n                up_ops[op.idx] = op.k;\n            }\n        } else if (op.type == 1) { // D\n            if (down_ops.find(op.idx) == down_ops.end() || op.k > down_ops[op.idx]) {\n                down_ops[op.idx] = op.k;\n            }\n        } else if (op.type == 2) { // L\n            if (left_ops.find(op.idx) == left_ops.end() || op.k > left_ops[op.idx]) {\n                left_ops[op.idx] = op.k;\n            }\n        } else { // R\n            if (right_ops.find(op.idx) == right_ops.end() || op.k > right_ops[op.idx]) {\n                right_ops[op.idx] = op.k;\n            }\n        }\n    }\n    \n    // Output merged operations\n    for (const auto& [col, k] : up_ops) {\n        for (int t = 0; t < k; ++t) cout << \"U \" << col << \"\\n\";\n        for (int t = 0; t < k; ++t) cout << \"D \" << col << \"\\n\";\n    }\n    for (const auto& [col, k] : down_ops) {\n        for (int t = 0; t < k; ++t) cout << \"D \" << col << \"\\n\";\n        for (int t = 0; t < k; ++t) cout << \"U \" << col << \"\\n\";\n    }\n    for (const auto& [row, k] : left_ops) {\n        for (int t = 0; t < k; ++t) cout << \"L \" << row << \"\\n\";\n        for (int t = 0; t < k; ++t) cout << \"R \" << row << \"\\n\";\n    }\n    for (const auto& [row, k] : right_ops) {\n        for (int t = 0; t < k; ++t) cout << \"R \" << row << \"\\n\";\n        for (int t = 0; t < k; ++t) cout << \"L \" << row << \"\\n\";\n    }\n    \n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, L;\n    cin >> N >> L;\n    vector<int> T(N);\n    for (int i = 0; i < N; ++i) cin >> T[i];\n\n    // Fast random generator\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    // ---------- Improved flow-based initialization ----------\n    vector<int> a(N), b(N);\n    vector<int> need(N);\n    need[0] = max(0, T[0] - 1);\n    for (int i = 1; i < N; ++i) need[i] = T[i];\n\n    // Create supplies with refined weights\n    vector<tuple<int, int, int>> supplies;\n    for (int i = 0; i < N; ++i) {\n        // Adjust weights based on position in walk\n        int odd = (T[i] + 1) / 2;\n        int even = T[i] / 2;\n        supplies.emplace_back(odd, i, 0);\n        supplies.emplace_back(even, i, 1);\n    }\n    sort(supplies.begin(), supplies.end(),\n         [](const auto& x, const auto& y) { return get<0>(x) > get<0>(y); });\n\n    priority_queue<pair<int, int>> pq;\n    for (int j = 0; j < N; ++j) {\n        if (need[j] > 0) pq.emplace(need[j], j);\n    }\n\n    for (const auto& [weight, i, type] : supplies) {\n        if (pq.empty()) break;\n        auto [rem, j] = pq.top();\n        pq.pop();\n        if (type == 0) a[i] = j;\n        else b[i] = j;\n        rem -= weight;\n        if (rem > 0) pq.emplace(rem, j);\n    }\n\n    // ---------- Build transition table ----------\n    array<array<int, 2>, 100> nxt;\n    for (int i = 0; i < N; ++i) {\n        nxt[i][0] = b[i];\n        nxt[i][1] = a[i];\n    }\n\n    // ---------- Simulation function ----------\n    auto simulate = [&]() {\n        int cnt[100] = {0};\n        cnt[0] = 1;\n        int cur = 0;\n        int steps = L - 1;\n        while (steps--) {\n            int parity = cnt[cur] & 1;\n            int next_emp = nxt[cur][parity];\n            ++cnt[next_emp];\n            cur = next_emp;\n        }\n        int error = 0;\n        for (int i = 0; i < N; ++i) {\n            error += abs(cnt[i] - T[i]);\n        }\n        return error;\n    };\n\n    // ---------- Refine initial solution with short SA ----------\n    auto start_time = chrono::steady_clock::now();\n    double temp = 100.0;\n    const double cooling = 0.95;\n    uniform_real_distribution<double> dist(0.0, 1.0);\n    \n    int cur_error = simulate();\n    int best_error = cur_error;\n    vector<int> best_a = a, best_b = b;\n    \n    // Quick initial refinement (0.3 seconds)\n    for (int iter = 0; iter < 200; ++iter) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > 0.3) break;\n        \n        int i = rng() % N;\n        int type = rng() % 2;\n        int old_val = (type == 0) ? a[i] : b[i];\n        int new_val = rng() % N;\n        if (new_val == old_val) continue;\n\n        if (type == 0) {\n            a[i] = new_val;\n            nxt[i][1] = new_val;\n        } else {\n            b[i] = new_val;\n            nxt[i][0] = new_val;\n        }\n\n        int new_error = simulate();\n        int delta = new_error - cur_error;\n\n        bool accept = false;\n        if (delta < 0) {\n            accept = true;\n        } else {\n            double prob = exp(-delta / temp);\n            if (dist(rng) < prob) accept = true;\n        }\n\n        if (accept) {\n            cur_error = new_error;\n            if (cur_error < best_error) {\n                best_error = cur_error;\n                best_a = a;\n                best_b = b;\n            }\n        } else {\n            if (type == 0) {\n                a[i] = old_val;\n                nxt[i][1] = old_val;\n            } else {\n                b[i] = old_val;\n                nxt[i][0] = old_val;\n            }\n        }\n        temp *= cooling;\n    }\n\n    // Reset to best and continue with main SA\n    a = best_a;\n    b = best_b;\n    for (int i = 0; i < N; ++i) {\n        nxt[i][0] = b[i];\n        nxt[i][1] = a[i];\n    }\n    cur_error = simulate();\n    best_error = cur_error;\n\n    // ---------- Main SA with intelligent mutations ----------\n    temp = 1000.0;\n    const double main_cooling = 0.998;\n    const double time_limit = 1.5; // Main SA time limit\n\n    int no_improve = 0;\n    int iter = 0;\n    while (true) {\n        if ((iter & 63) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > time_limit) break;\n        }\n        ++iter;\n\n        // Choose mutation type\n        int mut_type = rng() % 100;\n        if (mut_type < 80) {\n            // Standard single-edge mutation\n            int i = rng() % N;\n            int type = rng() % 2;\n            int old_val = (type == 0) ? a[i] : b[i];\n            int new_val = rng() % N;\n            if (new_val == old_val) continue;\n\n            if (type == 0) {\n                a[i] = new_val;\n                nxt[i][1] = new_val;\n            } else {\n                b[i] = new_val;\n                nxt[i][0] = new_val;\n            }\n        } else if (mut_type < 90) {\n            // Swap a_i and b_i for random employee\n            int i = rng() % N;\n            swap(a[i], b[i]);\n            nxt[i][0] = b[i];\n            nxt[i][1] = a[i];\n        } else {\n            // Targeted mutation: change edge for employee with highest error\n            // First compute current counts\n            int cnt[100] = {0};\n            cnt[0] = 1;\n            int cur = 0;\n            int steps = L - 1;\n            while (steps--) {\n                int parity = cnt[cur] & 1;\n                int next_emp = nxt[cur][parity];\n                ++cnt[next_emp];\n                cur = next_emp;\n            }\n            \n            // Find employee with highest error\n            int worst_i = 0;\n            int worst_err = abs(cnt[0] - T[0]);\n            for (int i = 1; i < N; ++i) {\n                int err = abs(cnt[i] - T[i]);\n                if (err > worst_err) {\n                    worst_err = err;\n                    worst_i = i;\n                }\n            }\n            \n            // Change one of its edges to a random employee\n            int type = rng() % 2;\n            int old_val = (type == 0) ? a[worst_i] : b[worst_i];\n            int new_val = rng() % N;\n            if (new_val == old_val) continue;\n            \n            if (type == 0) {\n                a[worst_i] = new_val;\n                nxt[worst_i][1] = new_val;\n            } else {\n                b[worst_i] = new_val;\n                nxt[worst_i][0] = new_val;\n            }\n        }\n\n        int new_error = simulate();\n        int delta = new_error - cur_error;\n\n        bool accept = false;\n        if (delta < 0) {\n            accept = true;\n        } else {\n            double prob = exp(-delta / temp);\n            if (dist(rng) < prob) accept = true;\n        }\n\n        if (accept) {\n            cur_error = new_error;\n            if (cur_error < best_error) {\n                best_error = cur_error;\n                best_a = a;\n                best_b = b;\n                no_improve = 0;\n                if (best_error == 0) break;\n            } else {\n                ++no_improve;\n            }\n        } else {\n            // Revert changes - need to know what was changed\n            // For simplicity, revert to best when rejected\n            a = best_a;\n            b = best_b;\n            for (int i = 0; i < N; ++i) {\n                nxt[i][0] = b[i];\n                nxt[i][1] = a[i];\n            }\n            ++no_improve;\n        }\n\n        // If stuck, do intelligent restart\n        if (no_improve > 300) {\n            // Keep best solution but perturb 3-5 edges intelligently\n            a = best_a;\n            b = best_b;\n            for (int i = 0; i < N; ++i) {\n                nxt[i][0] = b[i];\n                nxt[i][1] = a[i];\n            }\n            \n            // Find top 3 employees with highest error\n            int cnt[100] = {0};\n            cnt[0] = 1;\n            int cur = 0;\n            int steps = L - 1;\n            while (steps--) {\n                int parity = cnt[cur] & 1;\n                int next_emp = nxt[cur][parity];\n                ++cnt[next_emp];\n                cur = next_emp;\n            }\n            \n            vector<pair<int, int>> errors;\n            for (int i = 0; i < N; ++i) {\n                errors.emplace_back(abs(cnt[i] - T[i]), i);\n            }\n            sort(errors.rbegin(), errors.rend());\n            \n            // Change edges for top 3 employees\n            for (int k = 0; k < 3; ++k) {\n                int i = errors[k].second;\n                int type = rng() % 2;\n                int new_val = rng() % N;\n                if (type == 0) {\n                    a[i] = new_val;\n                    nxt[i][1] = new_val;\n                } else {\n                    b[i] = new_val;\n                    nxt[i][0] = new_val;\n                }\n            }\n            \n            cur_error = simulate();\n            no_improve = 0;\n        }\n\n        // Cool down\n        temp *= main_cooling;\n    }\n\n    // ---------- Final quick optimization ----------\n    auto now = chrono::steady_clock::now();\n    double elapsed = chrono::duration<double>(now - start_time).count();\n    if (elapsed < 1.9) {\n        // Try a few more targeted improvements\n        for (int attempt = 0; attempt < 50; ++attempt) {\n            int i = rng() % N;\n            int type = rng() % 2;\n            int old_val = (type == 0) ? a[i] : b[i];\n            int new_val = rng() % N;\n            if (new_val == old_val) continue;\n            \n            if (type == 0) {\n                a[i] = new_val;\n                nxt[i][1] = new_val;\n            } else {\n                b[i] = new_val;\n                nxt[i][0] = new_val;\n            }\n            \n            int new_error = simulate();\n            if (new_error < cur_error) {\n                cur_error = new_error;\n                if (cur_error < best_error) {\n                    best_error = cur_error;\n                    best_a = a;\n                    best_b = b;\n                }\n            } else {\n                if (type == 0) {\n                    a[i] = old_val;\n                    nxt[i][1] = old_val;\n                } else {\n                    b[i] = old_val;\n                    nxt[i][0] = old_val;\n                }\n            }\n        }\n    }\n\n    // ---------- Output ----------\n    for (int i = 0; i < N; ++i) {\n        cout << best_a[i] << \" \" << best_b[i] << \"\\n\";\n    }\n\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Hilbert curve computation without external libraries\nuint64_t hilbertOrder(int x, int y, int order = 16) {\n    uint64_t d = 0;\n    for (int s = 1 << (order - 1); s > 0; s >>= 1) {\n        bool rx = (x & s) > 0;\n        bool ry = (y & s) > 0;\n        d = (d << 2) | ((rx ? 1 : 0) * 3) ^ (ry ? 1 : 0);\n        if (!ry) {\n            if (rx) {\n                x = (1 << order) - 1 - x;\n                y = (1 << order) - 1 - y;\n            }\n            swap(x, y);\n        }\n    }\n    return d;\n}\n\n// Lower bound distance between two rectangles\ndouble lowerBoundDist(int lx1, int rx1, int ly1, int ry1, \n                      int lx2, int rx2, int ly2, int ry2) {\n    double dx = max(0, max(lx1 - rx2, lx2 - rx1));\n    double dy = max(0, max(ly1 - ry2, ly2 - ry1));\n    return sqrt(dx*dx + dy*dy);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, Q, L, W;\n    cin >> N >> M >> Q >> L >> W;\n\n    vector<int> G(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> G[i];\n    }\n\n    vector<int> lx(N), rx(N), ly(N), ry(N);\n    vector<double> cx(N), cy(N);\n    vector<double> uncertainty(N);\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.0;\n        cy[i] = (ly[i] + ry[i]) / 2.0;\n        uncertainty[i] = (rx[i] - lx[i]) * (ry[i] - ly[i]);\n    }\n\n    // Compute Hilbert values for ordering\n    vector<uint64_t> hilbert_vals(N);\n    for (int i = 0; i < N; ++i) {\n        int xi = static_cast<int>((cx[i] / 10000.0) * (1 << 16));\n        int yi = static_cast<int>((cy[i] / 10000.0) * (1 << 16));\n        hilbert_vals[i] = hilbertOrder(xi, yi, 16);\n    }\n\n    // Sort by Hilbert curve\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), \n         [&](int i, int j) { return hilbert_vals[i] < hilbert_vals[j]; });\n\n    // Partition into groups\n    vector<vector<int>> groups(M);\n    int idx = 0;\n    for (int k = 0; k < M; ++k) {\n        for (int i = 0; i < G[k]; ++i) {\n            groups[k].push_back(order[idx++]);\n        }\n        // Sort group by Hilbert curve for better locality\n        sort(groups[k].begin(), groups[k].end(),\n             [&](int i, int j) { return hilbert_vals[i] < hilbert_vals[j]; });\n    }\n\n    vector<vector<pair<int, int>>> group_edges(M);\n    vector<vector<tuple<double, int, int>>> group_edges_with_weights(M);\n    int query_count = 0;\n\n    // Process groups in order of size (largest first)\n    vector<int> group_indices(M);\n    iota(group_indices.begin(), group_indices.end(), 0);\n    sort(group_indices.begin(), group_indices.end(),\n         [&](int a, int b) { return groups[a].size() > groups[b].size(); });\n\n    // First pass: Use fixed windows with step = L-1 (guaranteed <= Q queries)\n    for (int k : group_indices) {\n        if (query_count >= Q) break;\n        \n        const vector<int>& cities = groups[k];\n        int g = cities.size();\n        if (g == 1) continue;\n        \n        if (g <= L) {\n            // Query entire group\n            cout << \"? \" << g;\n            for (int city : cities) cout << \" \" << city;\n            cout << endl;\n            cout.flush();\n            \n            for (int i = 0; i < g - 1; ++i) {\n                int a, b;\n                cin >> a >> b;\n                double w = lowerBoundDist(lx[a], rx[a], ly[a], ry[a],\n                                         lx[b], rx[b], ly[b], ry[b]);\n                group_edges_with_weights[k].push_back(make_tuple(w, a, b));\n            }\n            query_count++;\n        } else {\n            // Sliding windows with step = L-1\n            int step = L - 1;\n            int windows = (g - 1 + step - 1) / step; // ceil((g-1)/step)\n            \n            for (int w = 0; w < windows && query_count < Q; ++w) {\n                int start = w * step;\n                int end = min(start + L, g);\n                int sz = end - start;\n                \n                cout << \"? \" << sz;\n                for (int i = start; i < end; ++i) {\n                    cout << \" \" << cities[i];\n                }\n                cout << endl;\n                cout.flush();\n                \n                for (int i = 0; i < sz - 1; ++i) {\n                    int a, b;\n                    cin >> a >> b;\n                    double w = lowerBoundDist(lx[a], rx[a], ly[a], ry[a],\n                                             lx[b], rx[b], ly[b], ry[b]);\n                    group_edges_with_weights[k].push_back(make_tuple(w, a, b));\n                }\n                query_count++;\n            }\n        }\n        \n        // Run Kruskal on collected edges\n        if (!group_edges_with_weights[k].empty()) {\n            sort(group_edges_with_weights[k].begin(), \n                 group_edges_with_weights[k].end());\n            \n            vector<int> parent(g);\n            iota(parent.begin(), parent.end(), 0);\n            vector<int> rank(g, 0);\n            \n            // Map city index to local index\n            unordered_map<int, int> city_to_idx;\n            for (int i = 0; i < g; ++i) {\n                city_to_idx[cities[i]] = i;\n            }\n            \n            auto find = [&](int x) {\n                while (parent[x] != x) {\n                    parent[x] = parent[parent[x]];\n                    x = parent[x];\n                }\n                return x;\n            };\n            \n            auto unite = [&](int x, int y) {\n                x = find(x), y = find(y);\n                if (x == y) return false;\n                if (rank[x] < rank[y]) swap(x, y);\n                parent[y] = x;\n                if (rank[x] == rank[y]) rank[x]++;\n                return true;\n            };\n            \n            group_edges[k].clear();\n            for (const auto& edge : group_edges_with_weights[k]) {\n                double w;\n                int a, b;\n                tie(w, a, b) = edge;\n                int idx_a = city_to_idx[a];\n                int idx_b = city_to_idx[b];\n                if (unite(idx_a, idx_b)) {\n                    group_edges[k].push_back(make_pair(a, b));\n                    if (group_edges[k].size() == g - 1) break;\n                }\n            }\n        }\n    }\n\n    // Complete trees if needed\n    for (int k = 0; k < M; ++k) {\n        const vector<int>& cities = groups[k];\n        int g = cities.size();\n        if (g == 1) continue;\n        \n        if (group_edges[k].size() < g - 1) {\n            // Use simple path as fallback\n            group_edges[k].clear();\n            for (int i = 1; i < g; ++i) {\n                group_edges[k].push_back(make_pair(cities[i-1], cities[i]));\n            }\n        }\n    }\n\n    // Output answer\n    cout << \"!\" << endl;\n    for (int k = 0; k < M; ++k) {\n        // Output cities\n        for (int i = 0; i < (int)groups[k].size(); ++i) {\n            if (i > 0) cout << \" \";\n            cout << groups[k][i];\n        }\n        cout << endl;\n        \n        // Output edges\n        for (const auto& edge : group_edges[k]) {\n            cout << edge.first << \" \" << edge.second << endl;\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n    vector<pair<int, int>> pts(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> pts[i].first >> pts[i].second;\n    }\n\n    vector<string> actions;\n\n    for (int i = 0; i < M - 1; ++i) {\n        int r1 = pts[i].first, c1 = pts[i].second;\n        int r2 = pts[i + 1].first, c2 = pts[i + 1].second;\n\n        // ----- compute costs of the nine possible plans -----\n        int direct = abs(r1 - r2) + abs(c1 - c2);\n\n        int costU = (r1 > 0 ? 1 : 0) + abs(c1 - c2) + r2;\n        int costD = (r1 < N - 1 ? 1 : 0) + abs(c1 - c2) + (N - 1 - r2);\n        int costL = (c1 > 0 ? 1 : 0) + abs(r1 - r2) + c2;\n        int costR = (c1 < N - 1 ? 1 : 0) + abs(r1 - r2) + (N - 1 - c2);\n\n        // Corner plans\n        int costTL = (r1 > 0 ? 1 : 0) + (c1 > 0 ? 1 : 0) + r2 + c2;\n        int costTR = (r1 > 0 ? 1 : 0) + (c1 < N - 1 ? 1 : 0) + r2 + (N - 1 - c2);\n        int costBL = (r1 < N - 1 ? 1 : 0) + (c1 > 0 ? 1 : 0) + (N - 1 - r2) + c2;\n        int costBR = (r1 < N - 1 ? 1 : 0) + (c1 < N - 1 ? 1 : 0) + (N - 1 - r2) + (N - 1 - c2);\n\n        // ----- choose the cheapest plan -----\n        int best = direct;\n        int option = 0; // 0:direct, 1:up, 2:down, 3:left, 4:right, 5:TL, 6:TR, 7:BL, 8:BR\n        if (costU < best) { best = costU; option = 1; }\n        if (costD < best) { best = costD; option = 2; }\n        if (costL < best) { best = costL; option = 3; }\n        if (costR < best) { best = costR; option = 4; }\n        if (costTL < best) { best = costTL; option = 5; }\n        if (costTR < best) { best = costTR; option = 6; }\n        if (costBL < best) { best = costBL; option = 7; }\n        if (costBR < best) { best = costBR; option = 8; }\n\n        // ----- generate the actions for the chosen plan -----\n        switch (option) {\n            case 0: // direct moves\n                if (r2 > r1) {\n                    for (int k = 0; k < r2 - r1; ++k) actions.push_back(\"M D\");\n                } else if (r2 < r1) {\n                    for (int k = 0; k < r1 - r2; ++k) actions.push_back(\"M U\");\n                }\n                if (c2 > c1) {\n                    for (int k = 0; k < c2 - c1; ++k) actions.push_back(\"M R\");\n                } else if (c2 < c1) {\n                    for (int k = 0; k < c1 - c2; ++k) actions.push_back(\"M L\");\n                }\n                break;\n\n            case 1: // Up\n                if (r1 > 0) actions.push_back(\"S U\");\n                if (c2 > c1) {\n                    for (int k = 0; k < c2 - c1; ++k) actions.push_back(\"M R\");\n                } else if (c2 < c1) {\n                    for (int k = 0; k < c1 - c2; ++k) actions.push_back(\"M L\");\n                }\n                if (r2 > 0) {\n                    for (int k = 0; k < r2; ++k) actions.push_back(\"M D\");\n                }\n                break;\n\n            case 2: // Down\n                if (r1 < N - 1) actions.push_back(\"S D\");\n                if (c2 > c1) {\n                    for (int k = 0; k < c2 - c1; ++k) actions.push_back(\"M R\");\n                } else if (c2 < c1) {\n                    for (int k = 0; k < c1 - c2; ++k) actions.push_back(\"M L\");\n                }\n                if (r2 < N - 1) {\n                    int steps = N - 1 - r2;\n                    for (int k = 0; k < steps; ++k) actions.push_back(\"M U\");\n                }\n                break;\n\n            case 3: // Left\n                if (c1 > 0) actions.push_back(\"S L\");\n                if (r2 > r1) {\n                    for (int k = 0; k < r2 - r1; ++k) actions.push_back(\"M D\");\n                } else if (r2 < r1) {\n                    for (int k = 0; k < r1 - r2; ++k) actions.push_back(\"M U\");\n                }\n                if (c2 > 0) {\n                    for (int k = 0; k < c2; ++k) actions.push_back(\"M R\");\n                }\n                break;\n\n            case 4: // Right\n                if (c1 < N - 1) actions.push_back(\"S R\");\n                if (r2 > r1) {\n                    for (int k = 0; k < r2 - r1; ++k) actions.push_back(\"M D\");\n                } else if (r2 < r1) {\n                    for (int k = 0; k < r1 - r2; ++k) actions.push_back(\"M U\");\n                }\n                if (c2 < N - 1) {\n                    int steps = N - 1 - c2;\n                    for (int k = 0; k < steps; ++k) actions.push_back(\"M L\");\n                }\n                break;\n\n            case 5: // Top-left corner\n                if (r1 > 0) actions.push_back(\"S U\");\n                if (c1 > 0) actions.push_back(\"S L\");\n                // now at (0,0)\n                if (c2 > 0) {\n                    for (int k = 0; k < c2; ++k) actions.push_back(\"M R\");\n                }\n                if (r2 > 0) {\n                    for (int k = 0; k < r2; ++k) actions.push_back(\"M D\");\n                }\n                break;\n\n            case 6: // Top-right corner\n                if (r1 > 0) actions.push_back(\"S U\");\n                if (c1 < N - 1) actions.push_back(\"S R\");\n                // now at (0,N-1)\n                if (r2 > 0) {\n                    for (int k = 0; k < r2; ++k) actions.push_back(\"M D\");\n                }\n                if (c2 < N - 1) {\n                    int steps = N - 1 - c2;\n                    for (int k = 0; k < steps; ++k) actions.push_back(\"M L\");\n                }\n                break;\n\n            case 7: // Bottom-left corner\n                if (r1 < N - 1) actions.push_back(\"S D\");\n                if (c1 > 0) actions.push_back(\"S L\");\n                // now at (N-1,0)\n                if (r2 < N - 1) {\n                    int steps = N - 1 - r2;\n                    for (int k = 0; k < steps; ++k) actions.push_back(\"M U\");\n                }\n                if (c2 > 0) {\n                    for (int k = 0; k < c2; ++k) actions.push_back(\"M R\");\n                }\n                break;\n\n            case 8: // Bottom-right corner\n                if (r1 < N - 1) actions.push_back(\"S D\");\n                if (c1 < N - 1) actions.push_back(\"S R\");\n                // now at (N-1,N-1)\n                if (r2 < N - 1) {\n                    int steps = N - 1 - r2;\n                    for (int k = 0; k < steps; ++k) actions.push_back(\"M U\");\n                }\n                if (c2 < N - 1) {\n                    int steps = N - 1 - c2;\n                    for (int k = 0; k < steps; ++k) actions.push_back(\"M L\");\n                }\n                break;\n        }\n    }\n\n    // ----- output all actions -----\n    for (const string& act : actions) {\n        cout << act << '\\n';\n    }\n\n    return 0;\n}"}}}