{"model_name":"gemini-2.5-pro-thinking","codes":{"1":{"ahc001":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <cfloat>\n\nstruct Company {\n    int id;\n    int x, y;\n    long long r;\n};\n\nstruct Rect {\n    int x1, y1, x2, y2;\n};\n\nstd::vector<Company> companies;\nstd::vector<Rect> result;\nstd::vector<bool> is_in_partition1;\n\nvoid solve(int x1, int y1, int x2, int y2, std::vector<int>& indices_by_x, std::vector<int>& indices_by_y) {\n    int n = indices_by_x.size();\n    if (n == 0) {\n        return;\n    }\n    if (n == 1) {\n        result[indices_by_x[0]] = {x1, y1, x2, y2};\n        return;\n    }\n\n    // --- Try vertical split ---\n    int best_k_v = -1;\n    int best_x_split = -1;\n    double min_badness_v = DBL_MAX;\n    \n    bool can_split_vert = companies[indices_by_x.front()].x < companies[indices_by_x.back()].x;\n\n    if (can_split_vert) {\n        long long total_r = 0;\n        for (int idx : indices_by_x) total_r += companies[idx].r;\n\n        long long current_r_sum = 0;\n        for (int k = 1; k < n; ++k) {\n            current_r_sum += companies[indices_by_x[k - 1]].r;\n            if (companies[indices_by_x[k - 1]].x < companies[indices_by_x[k]].x) {\n                double target_ratio = (double)current_r_sum / total_r;\n                double ideal_x_split = x1 + (double)(x2 - x1) * target_ratio;\n\n                long long lower_bound = companies[indices_by_x[k - 1]].x + 1;\n                long long upper_bound = companies[indices_by_x[k]].x;\n                \n                int x_split = round(ideal_x_split);\n                x_split = std::max((int)lower_bound, std::min((int)upper_bound, x_split));\n\n                double actual_ratio = (double)(x_split - x1) / (x2 - x1);\n                double diff = actual_ratio - target_ratio;\n                double badness = diff * diff;\n\n                if (badness < min_badness_v) {\n                    min_badness_v = badness;\n                    best_k_v = k;\n                    best_x_split = x_split;\n                }\n            }\n        }\n    }\n\n    // --- Try horizontal split ---\n    int best_k_h = -1;\n    int best_y_split = -1;\n    double min_badness_h = DBL_MAX;\n    \n    bool can_split_horiz = companies[indices_by_y.front()].y < companies[indices_by_y.back()].y;\n    \n    if (can_split_horiz) {\n        long long total_r = 0;\n        for (int idx : indices_by_y) total_r += companies[idx].r;\n\n        long long current_r_sum = 0;\n        for (int k = 1; k < n; ++k) {\n            current_r_sum += companies[indices_by_y[k - 1]].r;\n            if (companies[indices_by_y[k - 1]].y < companies[indices_by_y[k]].y) {\n                double target_ratio = (double)current_r_sum / total_r;\n                double ideal_y_split = y1 + (double)(y2 - y1) * target_ratio;\n\n                long long lower_bound = companies[indices_by_y[k - 1]].y + 1;\n                long long upper_bound = companies[indices_by_y[k]].y;\n\n                int y_split = round(ideal_y_split);\n                y_split = std::max((int)lower_bound, std::min((int)upper_bound, y_split));\n\n                double actual_ratio = (double)(y_split - y1) / (y2 - y1);\n                double diff = actual_ratio - target_ratio;\n                double badness = diff * diff;\n                \n                if (badness < min_badness_h) {\n                    min_badness_h = badness;\n                    best_k_h = k;\n                    best_y_split = y_split;\n                }\n            }\n        }\n    }\n    \n    // --- Decide and perform split ---\n    bool perform_vertical_split;\n    if (!can_split_vert) {\n        perform_vertical_split = false;\n    } else if (!can_split_horiz) {\n        perform_vertical_split = true;\n    } else {\n        if (min_badness_v < min_badness_h) {\n            perform_vertical_split = true;\n        } else if (min_badness_h < min_badness_v) {\n            perform_vertical_split = false;\n        } else {\n            // Tie-break by splitting the longer side\n            perform_vertical_split = (x2 - x1) >= (y2 - y1);\n        }\n    }\n\n    if (perform_vertical_split) {\n        int k = best_k_v;\n        for (int i = 0; i < k; ++i) is_in_partition1[indices_by_x[i]] = true;\n        for (int i = k; i < n; ++i) is_in_partition1[indices_by_x[i]] = false;\n\n        std::vector<int> left_indices_by_x(indices_by_x.begin(), indices_by_x.begin() + k);\n        std::vector<int> right_indices_by_x(indices_by_x.begin() + k, indices_by_x.end());\n\n        std::vector<int> left_indices_by_y, right_indices_by_y;\n        left_indices_by_y.reserve(k);\n        right_indices_by_y.reserve(n - k);\n        for (int idx : indices_by_y) {\n            if (is_in_partition1[idx]) {\n                left_indices_by_y.push_back(idx);\n            } else {\n                right_indices_by_y.push_back(idx);\n            }\n        }\n        solve(x1, y1, best_x_split, y2, left_indices_by_x, left_indices_by_y);\n        solve(best_x_split, y1, x2, y2, right_indices_by_x, right_indices_by_y);\n    } else { // Horizontal split\n        int k = best_k_h;\n        for (int i = 0; i < k; ++i) is_in_partition1[indices_by_y[i]] = true;\n        for (int i = k; i < n; ++i) is_in_partition1[indices_by_y[i]] = false;\n\n        std::vector<int> bottom_indices_by_y(indices_by_y.begin(), indices_by_y.begin() + k);\n        std::vector<int> top_indices_by_y(indices_by_y.begin() + k, indices_by_y.end());\n\n        std::vector<int> bottom_indices_by_x, top_indices_by_x;\n        bottom_indices_by_x.reserve(k);\n        top_indices_by_x.reserve(n - k);\n\n        for (int idx : indices_by_x) {\n            if (is_in_partition1[idx]) {\n                bottom_indices_by_x.push_back(idx);\n            } else {\n                top_indices_by_x.push_back(idx);\n            }\n        }\n        solve(x1, y1, x2, best_y_split, bottom_indices_by_x, bottom_indices_by_y);\n        solve(x1, best_y_split, x2, y2, top_indices_by_x, top_indices_by_y);\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int n;\n    std::cin >> n;\n    companies.resize(n);\n    result.resize(n);\n    is_in_partition1.resize(n);\n\n    std::vector<int> indices_by_x(n), indices_by_y(n);\n    for (int i = 0; i < n; ++i) {\n        companies[i].id = i;\n        std::cin >> companies[i].x >> companies[i].y >> companies[i].r;\n        indices_by_x[i] = i;\n        indices_by_y[i] = i;\n    }\n\n    std::sort(indices_by_x.begin(), indices_by_x.end(), [&](int a, int b) {\n        if (companies[a].x != companies[b].x) return companies[a].x < companies[b].x;\n        return companies[a].y < companies[b].y;\n    });\n    std::sort(indices_by_y.begin(), indices_by_y.end(), [&](int a, int b) {\n        if (companies[a].y != companies[b].y) return companies[a].y < companies[b].y;\n        return companies[a].x < companies[b].x;\n    });\n\n    solve(0, 0, 10000, 10000, indices_by_x, indices_by_y);\n\n    for (int i = 0; i < n; ++i) {\n        std::cout << result[i].x1 << \" \" << result[i].y1 << \" \" << result[i].x2 << \" \" << result[i].y2 << \"\\n\";\n    }\n\n    return 0;\n}","ahc002":"#include <iostream>\n#include <vector>\n#include <string>\n#include <map>\n#include <utility>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n\n// Fast I/O\nvoid fast_io() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n}\n\n// Timer\nstruct Timer {\n    std::chrono::steady_clock::time_point start_time;\n    Timer() : start_time(std::chrono::steady_clock::now()) {}\n    long long get_ms() {\n        return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count();\n    }\n};\n\nconstexpr int N = 50;\n\n#ifdef LOCAL_TEST\nconstexpr int TIME_LIMIT_MS = 1980;\nconstexpr int BEAM_WIDTH = 200;\n#else\nconstexpr int TIME_LIMIT_MS = 1980;\nconstexpr int BEAM_WIDTH = 2000;\n#endif\n\nint si, sj;\nint t[N][N];\nint p[N][N];\n\nstruct Tile {\n    int id;\n    std::vector<std::pair<int, int>> squares;\n};\n\nint tile_id_map[N][N];\nstd::vector<Tile> tiles;\nint M; // number of tiles\n\nstruct State {\n    long long score;\n    std::pair<int, int> pos;\n    std::vector<bool> visited_tiles;\n\n    int prev_idx_in_history;\n    std::string path_segment;\n};\n\nchar get_move_char(const std::pair<int, int>& from, const std::pair<int, int>& to) {\n    if (to.first == from.first - 1 && to.second == from.second) return 'U';\n    if (to.first == from.first + 1 && to.second == from.second) return 'D';\n    if (to.second == from.second - 1 && to.first == from.first) return 'L';\n    if (to.second == from.second + 1 && to.first == from.first) return 'R';\n    return ' '; // Should not happen\n}\n\nvoid solve() {\n    Timer timer;\n\n    std::cin >> si >> sj;\n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) std::cin >> t[i][j];\n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) std::cin >> p[i][j];\n\n    std::map<int, int> raw_id_to_my_id;\n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) {\n        if (raw_id_to_my_id.find(t[i][j]) == raw_id_to_my_id.end()) {\n            raw_id_to_my_id[t[i][j]] = raw_id_to_my_id.size();\n        }\n    }\n    M = raw_id_to_my_id.size();\n    tiles.resize(M);\n    for (int i=0; i<M; ++i) tiles[i].id = i;\n\n    for (int i=0; i<N; ++i) for(int j=0; j<N; ++j) {\n        int my_id = raw_id_to_my_id[t[i][j]];\n        tile_id_map[i][j] = my_id;\n        tiles[my_id].squares.push_back({i,j});\n    }\n\n    State initial_state;\n    int start_tile_id = tile_id_map[si][sj];\n    const auto& start_tile = tiles[start_tile_id];\n    \n    initial_state.score = 0;\n    initial_state.visited_tiles.assign(M, false);\n    initial_state.visited_tiles[start_tile_id] = true;\n    initial_state.prev_idx_in_history = -1;\n\n    std::pair<int, int> current_pos = {si, sj};\n    initial_state.score += p[si][sj];\n\n    if (start_tile.squares.size() == 2) {\n        std::pair<int, int> other_pos = (start_tile.squares[0] == current_pos) ? start_tile.squares[1] : start_tile.squares[0];\n        char move = get_move_char(current_pos, other_pos);\n        initial_state.path_segment += move;\n        initial_state.score += p[other_pos.first][other_pos.second];\n        current_pos = other_pos;\n    }\n    initial_state.pos = current_pos;\n\n    long long best_score = initial_state.score;\n    std::pair<int, int> best_state_locus = {0, 0};\n\n    std::vector<std::vector<State>> history;\n    std::vector<State> beam;\n    beam.push_back(std::move(initial_state));\n    history.push_back(std::move(beam));\n    \n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n    char move_chars[] = {'U', 'D', 'L', 'R'};\n\n    while (timer.get_ms() < TIME_LIMIT_MS) {\n        const auto& current_beam = history.back();\n        std::vector<State> candidates;\n        \n        for (int i = 0; i < current_beam.size(); ++i) {\n            const auto& s = current_beam[i];\n            int r = s.pos.first;\n            int c = s.pos.second;\n\n            for (int k = 0; k < 4; ++k) {\n                int nr = r + dr[k];\n                int nc = c + dc[k];\n\n                if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n\n                int next_tile_id = tile_id_map[nr][nc];\n                if (s.visited_tiles[next_tile_id]) continue;\n\n                State new_s;\n                new_s.visited_tiles = s.visited_tiles;\n                new_s.visited_tiles[next_tile_id] = true;\n\n                std::string path_ext;\n                long long score_ext = 0;\n                std::pair<int, int> next_pos = {nr, nc};\n\n                path_ext += move_chars[k];\n                score_ext += p[nr][nc];\n\n                const auto& next_tile = tiles[next_tile_id];\n                if (next_tile.squares.size() == 2) {\n                    std::pair<int, int> other_pos = (next_tile.squares[0] == next_pos) ? next_tile.squares[1] : next_tile.squares[0];\n                    char move = get_move_char(next_pos, other_pos);\n                    path_ext += move;\n                    score_ext += p[other_pos.first][other_pos.second];\n                    next_pos = other_pos;\n                }\n                \n                new_s.score = s.score + score_ext;\n                new_s.pos = next_pos;\n                new_s.path_segment = path_ext;\n                new_s.prev_idx_in_history = i;\n                candidates.push_back(std::move(new_s));\n            }\n        }\n\n        if (candidates.empty()) break;\n\n        size_t sort_end_idx = std::min((size_t)candidates.size(), (size_t)BEAM_WIDTH);\n        std::partial_sort(candidates.begin(), candidates.begin() + sort_end_idx, candidates.end(), \n            [](const State& a, const State& b){ return a.score > b.score; });\n\n        std::vector<State> next_beam;\n        next_beam.reserve(sort_end_idx);\n        for (int i = 0; i < sort_end_idx; ++i) {\n            next_beam.push_back(std::move(candidates[i]));\n        }\n        \n        if (next_beam[0].score > best_score) {\n            best_score = next_beam[0].score;\n            best_state_locus = {(int)history.size(), 0};\n        }\n        history.push_back(std::move(next_beam));\n    }\n    \n    std::string final_path = \"\";\n    int hist_idx = best_state_locus.first;\n    int beam_idx = best_state_locus.second;\n    while (hist_idx >= 0) {\n        const auto& s = history[hist_idx][beam_idx];\n        final_path = s.path_segment + final_path;\n        if (s.prev_idx_in_history == -1) break;\n        beam_idx = s.prev_idx_in_history;\n        hist_idx--;\n    }\n    std::cout << final_path << std::endl;\n}\n\nint main() {\n    fast_io();\n    solve();\n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <numeric>\n#include <random>\n#include <algorithm>\n#include <iomanip>\n#include <chrono>\n\n// Constants\nconstexpr int GRID_SIZE = 30;\nconstexpr int NUM_QUERIES = 1000;\n\n// Grid coordinates\nstruct Point {\n    int r, c;\n    bool operator==(const Point& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Point& other) const {\n        return !(*this == other);\n    }\n};\n\n// For priority queue in Dijkstra\nstruct State {\n    Point pos;\n    double dist;\n\n    bool operator>(const State& other) const {\n        return dist > other.dist;\n    }\n};\n\n// Global state for our estimates and models\ndouble est_h[GRID_SIZE][GRID_SIZE - 1]; // Raw estimates\ndouble est_v[GRID_SIZE - 1][GRID_SIZE];\ndouble model_h[GRID_SIZE][GRID_SIZE - 1]; // Smoothed/model-based estimates\ndouble model_v[GRID_SIZE - 1][GRID_SIZE];\nint updates_h[GRID_SIZE][GRID_SIZE - 1];\nint updates_v[GRID_SIZE - 1][GRID_SIZE];\n\n// Randomness\nstd::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// Helper function to check bounds\nbool is_valid(int r, int c) {\n    return r >= 0 && r < GRID_SIZE && c >= 0 && c < GRID_SIZE;\n}\n\n// Dijkstra's algorithm\nPoint parent[GRID_SIZE][GRID_SIZE];\nchar move_char[GRID_SIZE][GRID_SIZE];\ndouble dist[GRID_SIZE][GRID_SIZE];\n\nstd::string find_path(Point start, Point goal, int k) {\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            dist[i][j] = 1e18;\n        }\n    }\n\n    std::priority_queue<State, std::vector<State>, std::greater<State>> pq;\n\n    dist[start.r][start.c] = 0;\n    pq.push({start, 0.0});\n\n    double C_k = 0.3 * (1.0 - static_cast<double>(k) / (NUM_QUERIES - 1));\n    if (k > NUM_QUERIES - 50) C_k = 0; // No exploration in the end\n\n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n    char moves[] = {'U', 'D', 'L', 'R'};\n\n    while (!pq.empty()) {\n        State current = pq.top();\n        pq.pop();\n\n        Point pos = current.pos;\n\n        if (current.dist > dist[pos.r][pos.c]) {\n            continue;\n        }\n\n        if (pos == goal) {\n            break;\n        }\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = pos.r + dr[i];\n            int nc = pos.c + dc[i];\n\n            if (!is_valid(nr, nc)) {\n                continue;\n            }\n\n            double edge_cost;\n            if (i == 0) { // Up\n                edge_cost = model_v[nr][nc];\n            } else if (i == 1) { // Down\n                edge_cost = model_v[pos.r][pos.c];\n            } else if (i == 2) { // Left\n                edge_cost = model_h[nr][nc];\n            } else { // Right\n                edge_cost = model_h[pos.r][pos.c];\n            }\n            \n            std::uniform_real_distribution<double> dist_expl(1.0 - C_k, 1.0 + C_k);\n            double noisy_cost = edge_cost * dist_expl(rng);\n            \n            if (dist[pos.r][pos.c] + noisy_cost < dist[nr][nc]) {\n                dist[nr][nc] = dist[pos.r][pos.c] + noisy_cost;\n                parent[nr][nc] = pos;\n                move_char[nr][nc] = moves[i];\n                pq.push({{nr, nc}, dist[nr][nc]});\n            }\n        }\n    }\n\n    std::string path_str = \"\";\n    Point current = goal;\n    while (current != start) {\n        path_str += move_char[current.r][current.c];\n        current = parent[current.r][current.c];\n    }\n    std::reverse(path_str.begin(), path_str.end());\n    return path_str;\n}\n\nvoid update_estimates(const std::string& path_str, Point start, long long noisy_path_length, int k) {\n    double estimated_length = 0;\n\n    Point current = start;\n    for (char move : path_str) {\n        Point next = current;\n        if (move == 'U') {\n            next.r--;\n            estimated_length += est_v[next.r][next.c];\n        } else if (move == 'D') {\n            estimated_length += est_v[current.r][current.c];\n            next.r++;\n        } else if (move == 'L') {\n            next.c--;\n            estimated_length += est_h[next.r][next.c];\n        } else if (move == 'R') {\n            estimated_length += est_h[current.r][current.c];\n            next.c++;\n        }\n        current = next;\n    }\n    \n    double error = static_cast<double>(noisy_path_length) - estimated_length;\n    double alpha_k = 0.5 * std::pow(0.01, static_cast<double>(k) / (NUM_QUERIES - 1));\n    if (!path_str.empty()) {\n        double update_val = alpha_k * error / path_str.length();\n        current = start;\n        for (char move : path_str) {\n            Point next = current;\n            if (move == 'U') {\n                next.r--;\n                est_v[next.r][next.c] += update_val;\n                est_v[next.r][next.c] = std::clamp(est_v[next.r][next.c], 100.0, 15000.0);\n                updates_v[next.r][next.c]++;\n            } else if (move == 'D') {\n                est_v[current.r][current.c] += update_val;\n                est_v[current.r][current.c] = std::clamp(est_v[current.r][current.c], 100.0, 15000.0);\n                updates_v[current.r][current.c]++;\n                next.r++;\n            } else if (move == 'L') {\n                next.c--;\n                est_h[next.r][next.c] += update_val;\n                est_h[next.r][next.c] = std::clamp(est_h[next.r][next.c], 100.0, 15000.0);\n                updates_h[next.r][next.c]++;\n            } else if (move == 'R') {\n                est_h[current.r][current.c] += update_val;\n                est_h[current.r][current.c] = std::clamp(est_h[current.r][current.c], 100.0, 15000.0);\n                updates_h[current.r][current.c]++;\n                next.c++;\n            }\n            current = next;\n        }\n    }\n}\n\nvoid update_model() {\n    // Horizontal edges\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        double sum1=0, sum_sq1=0; int count1=0;\n        for (int j=0; j<GRID_SIZE-1; ++j) {\n            if (updates_h[i][j] > 0) {\n                sum1 += est_h[i][j];\n                sum_sq1 += est_h[i][j] * est_h[i][j];\n                count1++;\n            }\n        }\n\n        if (count1 < 6) {\n            if (count1 > 0) {\n                double mean = sum1/count1;\n                for (int j=0; j<GRID_SIZE-1; ++j) model_h[i][j] = mean;\n            }\n            continue;\n        }\n\n        double mean1 = sum1/count1;\n        double sse1 = sum_sq1 - sum1 * mean1;\n\n        double best_sse2 = 1e18;\n        int best_split = -1;\n        double best_mean_l=0, best_mean_r=0;\n\n        for (int split=1; split < GRID_SIZE-1; ++split) {\n            double sum_l=0, sum_sq_l=0; int count_l=0;\n            for (int j=0; j<split; ++j) if (updates_h[i][j] > 0) {\n                sum_l += est_h[i][j]; sum_sq_l += est_h[i][j]*est_h[i][j]; count_l++;\n            }\n            if (count_l == 0) continue;\n            \n            double sum_r = sum1 - sum_l;\n            double sum_sq_r = sum_sq1 - sum_sq_l;\n            int count_r = count1 - count_l;\n            if (count_r == 0) continue;\n\n            double mean_l = sum_l / count_l;\n            double sse_l = sum_sq_l - sum_l * mean_l;\n            double mean_r = sum_r / count_r;\n            double sse_r = sum_sq_r - sum_r * mean_r;\n            \n            if (sse_l + sse_r < best_sse2) {\n                best_sse2 = sse_l + sse_r;\n                best_split = split;\n                best_mean_l = mean_l;\n                best_mean_r = mean_r;\n            }\n        }\n        \n        if (best_split != -1 && best_sse2 < sse1 * 0.7) {\n            for (int j = 0; j < best_split; ++j) model_h[i][j] = best_mean_l;\n            for (int j = best_split; j < GRID_SIZE - 1; ++j) model_h[i][j] = best_mean_r;\n        } else {\n            for (int j = 0; j < GRID_SIZE - 1; ++j) model_h[i][j] = mean1;\n        }\n    }\n\n    // Vertical edges\n    for (int j = 0; j < GRID_SIZE; ++j) {\n        double sum1=0, sum_sq1=0; int count1=0;\n        for (int i=0; i<GRID_SIZE-1; ++i) if (updates_v[i][j] > 0) {\n            sum1 += est_v[i][j]; sum_sq1 += est_v[i][j]*est_v[i][j]; count1++;\n        }\n\n        if (count1 < 6) {\n            if (count1 > 0) {\n                double mean = sum1/count1;\n                for (int i=0; i<GRID_SIZE-1; ++i) model_v[i][j] = mean;\n            }\n            continue;\n        }\n\n        double mean1 = sum1/count1;\n        double sse1 = sum_sq1 - sum1 * mean1;\n\n        double best_sse2 = 1e18;\n        int best_split = -1;\n        double best_mean_u=0, best_mean_d=0;\n\n        for (int split=1; split < GRID_SIZE-1; ++split) {\n            double sum_u=0, sum_sq_u=0; int count_u=0;\n            for (int i=0; i<split; ++i) if (updates_v[i][j] > 0) {\n                sum_u += est_v[i][j]; sum_sq_u += est_v[i][j]*est_v[i][j]; count_u++;\n            }\n            if (count_u == 0) continue;\n\n            double sum_d = sum1 - sum_u;\n            double sum_sq_d = sum_sq1 - sum_sq_u;\n            int count_d = count1 - count_u;\n            if (count_d == 0) continue;\n\n            double mean_u = sum_u / count_u;\n            double sse_u = sum_sq_u - sum_u * mean_u;\n            double mean_d = sum_d / count_d;\n            double sse_d = sum_sq_d - sum_d * mean_d;\n            \n            if (sse_u + sse_d < best_sse2) {\n                best_sse2 = sse_u + sse_d;\n                best_split = split;\n                best_mean_u = mean_u;\n                best_mean_d = mean_d;\n            }\n        }\n        \n        if (best_split != -1 && best_sse2 < sse1 * 0.7) {\n            for (int i = 0; i < best_split; ++i) model_v[i][j] = best_mean_u;\n            for (int i = best_split; i < GRID_SIZE - 1; ++i) model_v[i][j] = best_mean_d;\n        } else {\n            for (int i = 0; i < GRID_SIZE - 1; ++i) model_v[i][j] = mean1;\n        }\n    }\n}\n\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE - 1; ++j) {\n            est_h[i][j] = model_h[i][j] = 5000.0;\n            updates_h[i][j] = 0;\n        }\n    }\n    for (int i = 0; i < GRID_SIZE - 1; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            est_v[i][j] = model_v[i][j] = 5000.0;\n            updates_v[i][j] = 0;\n        }\n    }\n\n    for (int k = 0; k < NUM_QUERIES; ++k) {\n        Point start, goal;\n        std::cin >> start.r >> start.c >> goal.r >> goal.c;\n\n        std::string path = find_path(start, goal, k);\n        std::cout << path << std::endl;\n\n        long long noisy_path_length;\n        std::cin >> noisy_path_length;\n\n        update_estimates(path, start, noisy_path_length, k);\n        update_model();\n    }\n\n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <chrono>\n#include <random>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <map>\n\n// --- Constants and Globals ---\nconstexpr int N_CONST = 20;\nconstexpr int NUM_CHARS = 8;\nconstexpr long long W_CONFLICT = 10000;\n\nint N_in, M;\nstd::vector<std::string> S;\nstd::vector<int> S_len;\nstd::vector<std::vector<int>> S_int;\n\nstd::mt19937 rng;\nstd::chrono::steady_clock::time_point start_time;\n\nstruct Placement {\n    int r, c, dir; // dir=0: horizontal, dir=1: vertical\n    bool operator==(const Placement& other) const {\n        return r == other.r && c == other.c && dir == other.dir;\n    }\n};\n\n// --- State Representation ---\nstd::vector<Placement> current_placements;\nstd::vector<Placement> best_placements;\nlong long current_energy;\nlong long best_energy;\n\nint counts[N_CONST][N_CONST][NUM_CHARS];\nint covered_count[N_CONST][N_CONST];\n\n// --- Utilities ---\nint ctoi(char c) { return c - 'A'; }\n\n// --- Core Logic ---\nstd::pair<long long, int> get_cell_energy_contrib(int r, int c) {\n    if (covered_count[r][c] == 0) {\n        return {0, 0};\n    }\n    int max_c = 0;\n    for (int k = 0; k < NUM_CHARS; ++k) max_c = std::max(max_c, counts[r][c][k]);\n    long long conflict_contrib = covered_count[r][c] - max_c;\n    int covered_contrib = 1;\n    return {conflict_contrib, covered_contrib};\n}\n\nlong long calculate_full_energy() {\n    long long total_conflicts = 0;\n    int total_covered = 0;\n    for (int r = 0; r < N_CONST; ++r) {\n        for (int c = 0; c < N_CONST; ++c) {\n            auto [conflicts, covered] = get_cell_energy_contrib(r, c);\n            total_conflicts += conflicts;\n            total_covered += covered;\n        }\n    }\n    return total_conflicts * W_CONFLICT + total_covered;\n}\n\nvoid update_state_for_move(int str_idx, const Placement& p, int sign) {\n    const auto& s = S_int[str_idx];\n    int len = S_len[str_idx];\n    if (p.dir == 0) { // Horizontal\n        for (int i = 0; i < len; ++i) {\n            int r = p.r;\n            int c = (p.c + i) % N_CONST;\n            counts[r][c][s[i]] += sign;\n            covered_count[r][c] += sign;\n        }\n    } else { // Vertical\n        for (int i = 0; i < len; ++i) {\n            int r = (p.r + i) % N_CONST;\n            int c = p.c;\n            counts[r][c][s[i]] += sign;\n            covered_count[r][c] += sign;\n        }\n    }\n}\n\nlong long calculate_delta_energy(int str_idx, const Placement& old_p, const Placement& new_p) {\n    long long delta = 0;\n    const auto& s = S_int[str_idx];\n    int len = S_len[str_idx];\n    \n    std::map<std::pair<int, int>, std::vector<int>> cell_deltas;\n\n    // Subtract old placement\n    if (old_p.dir == 0) for (int i=0; i<len; ++i) {\n        auto cell = std::make_pair(old_p.r, (old_p.c+i)%N_CONST);\n        if (cell_deltas.find(cell) == cell_deltas.end()) cell_deltas[cell].assign(NUM_CHARS, 0);\n        cell_deltas[cell][s[i]]--;\n    } else for (int i=0; i<len; ++i) {\n        auto cell = std::make_pair((old_p.r+i)%N_CONST, old_p.c);\n        if (cell_deltas.find(cell) == cell_deltas.end()) cell_deltas[cell].assign(NUM_CHARS, 0);\n        cell_deltas[cell][s[i]]--;\n    }\n    \n    // Add new placement\n    if (new_p.dir == 0) for (int i=0; i<len; ++i) {\n        auto cell = std::make_pair(new_p.r, (new_p.c+i)%N_CONST);\n        if (cell_deltas.find(cell) == cell_deltas.end()) cell_deltas[cell].assign(NUM_CHARS, 0);\n        cell_deltas[cell][s[i]]++;\n    } else for (int i=0; i<len; ++i) {\n        auto cell = std::make_pair((new_p.r+i)%N_CONST, new_p.c);\n        if (cell_deltas.find(cell) == cell_deltas.end()) cell_deltas[cell].assign(NUM_CHARS, 0);\n        cell_deltas[cell][s[i]]++;\n    }\n\n    for (auto const& [cell, char_delta_vec] : cell_deltas) {\n        int r = cell.first;\n        int c = cell.second;\n\n        auto [conflicts_before, covered_before] = get_cell_energy_contrib(r, c);\n        delta -= (conflicts_before * W_CONFLICT + covered_before);\n\n        int net_coverage_change = 0;\n        for(int k=0; k<NUM_CHARS; ++k) net_coverage_change += char_delta_vec[k];\n        int new_covered_total = covered_count[r][c] + net_coverage_change;\n        \n        if (new_covered_total > 0) {\n            int max_c = 0;\n            for (int k=0; k<NUM_CHARS; ++k) max_c = std::max(max_c, counts[r][c][k] + char_delta_vec[k]);\n            long long conflicts_after = new_covered_total - max_c;\n            delta += (conflicts_after * W_CONFLICT + 1);\n        }\n    }\n    return delta;\n}\n\nvoid greedy_initialization() {\n    current_placements.resize(M);\n    std::vector<int> p(M);\n    std::iota(p.begin(), p.end(), 0);\n    std::sort(p.begin(), p.end(), [&](int i, int j){\n        return S_len[i] > S_len[j];\n    });\n\n    std::vector<std::vector<int>> grid(N_CONST, std::vector<int>(N_CONST, -1));\n\n    for (int str_idx : p) {\n        Placement best_p;\n        int min_conflicts = 1e9;\n\n        for (int r = 0; r < N_CONST; ++r) {\n        for (int c = 0; c < N_CONST; ++c) {\n        for (int dir = 0; dir < 2; ++dir) {\n            int current_conflicts = 0;\n            const auto& s = S_int[str_idx];\n            int len = S_len[str_idx];\n            if (dir == 0) {\n                for (int i = 0; i < len; ++i) {\n                    if (grid[r][(c + i) % N_CONST] != -1 && grid[r][(c + i) % N_CONST] != s[i]) {\n                        current_conflicts++;\n                    }\n                }\n            } else {\n                for (int i = 0; i < len; ++i) {\n                    if (grid[(r + i) % N_CONST][c] != -1 && grid[(r + i) % N_CONST][c] != s[i]) {\n                        current_conflicts++;\n                    }\n                }\n            }\n            if (current_conflicts < min_conflicts) {\n                min_conflicts = current_conflicts;\n                best_p = {r, c, dir};\n            }\n        }}}\n        current_placements[str_idx] = best_p;\n        const auto& s = S_int[str_idx];\n        int len = S_len[str_idx];\n        if (best_p.dir == 0) for(int i=0; i<len; ++i) grid[best_p.r][(best_p.c+i)%N_CONST] = s[i];\n        else for(int i=0; i<len; ++i) grid[(best_p.r+i)%N_CONST][best_p.c] = s[i];\n    }\n\n    for (int i = 0; i < M; ++i) {\n        update_state_for_move(i, current_placements[i], +1);\n    }\n}\n\nvoid solve() {\n    start_time = std::chrono::steady_clock::now();\n    rng.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    S_int.resize(M); S_len.resize(M);\n    for (int i = 0; i < M; ++i) {\n        S_len[i] = S[i].length();\n        S_int[i].resize(S_len[i]);\n        for (int j = 0; j < S_len[i]; ++j) S_int[i][j] = ctoi(S[i][j]);\n    }\n\n    greedy_initialization();\n    \n    current_energy = calculate_full_energy();\n    best_energy = current_energy;\n    best_placements = current_placements;\n\n    double time_limit = 2.95;\n    double start_temp = 100.0;\n    double end_temp = 0.1;\n\n    while (true) {\n        auto now = std::chrono::steady_clock::now();\n        double elapsed_time = std::chrono::duration_cast<std::chrono::duration<double>>(now - start_time).count();\n        if (elapsed_time > time_limit) break;\n\n        double temp = start_temp * std::pow(end_temp / start_temp, elapsed_time / time_limit);\n\n        int str_idx = std::uniform_int_distribution<int>(0, M - 1)(rng);\n        Placement old_p = current_placements[str_idx];\n        Placement new_p;\n\n        if (std::uniform_real_distribution<>(0.0, 1.0)(rng) < 0.1) {\n             new_p = old_p;\n             int move_type = std::uniform_int_distribution<int>(0, 2)(rng);\n             if (move_type == 0) new_p.r = (new_p.r + std::uniform_int_distribution<int>(-2, 2)(rng) + N_CONST) % N_CONST;\n             else if (move_type == 1) new_p.c = (new_p.c + std::uniform_int_distribution<int>(-2, 2)(rng) + N_CONST) % N_CONST;\n             else new_p.dir = 1 - new_p.dir;\n        } else {\n            new_p = {\n                std::uniform_int_distribution<int>(0, N_CONST - 1)(rng),\n                std::uniform_int_distribution<int>(0, N_CONST - 1)(rng),\n                std::uniform_int_distribution<int>(0, 1)(rng)\n            };\n        }\n\n        if (old_p == new_p) continue;\n        \n        long long delta_energy = calculate_delta_energy(str_idx, old_p, new_p);\n\n        if (delta_energy <= 0 || std::uniform_real_distribution<double>(0.0, 1.0)(rng) < std::exp(-delta_energy / temp)) {\n            current_energy += delta_energy;\n            update_state_for_move(str_idx, old_p, -1);\n            update_state_for_move(str_idx, new_p, +1);\n            current_placements[str_idx] = new_p;\n\n            if (current_energy < best_energy) {\n                best_energy = current_energy;\n                best_placements = current_placements;\n            }\n        }\n    }\n\n    std::vector<std::string> final_grid(N_CONST, std::string(N_CONST, '.'));\n    for (int i = 0; i < M; ++i) {\n        Placement p = best_placements[i];\n        const auto& s = S[i];\n        int len = S_len[i];\n        if (p.dir == 0) for (int j = 0; j < len; ++j) final_grid[p.r][(p.c + j) % N_CONST] = s[j];\n        else for (int j = 0; j < len; ++j) final_grid[(p.r + j) % N_CONST][p.c] = s[j];\n    }\n\n    for (int i = 0; i < N_CONST; ++i) {\n        std::cout << final_grid[i] << std::endl;\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    std::cin >> N_in >> M;\n    S.resize(M);\n    for (int i = 0; i < M; ++i) std::cin >> S[i];\n    solve();\n    return 0;\n}","ahc005":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <map>\n#include <set>\n#include <algorithm>\n#include <chrono>\n#include <random>\n\nusing namespace std;\n\n// Timer\nchrono::high_resolution_clock::time_point start_time;\n\n// Constants\nconst int INF = 1e9;\nconst int DR[] = {-1, 1, 0, 0};\nconst int DC[] = {0, 0, -1, 1};\nconst char MOVES[] = {'U', 'D', 'L', 'R'};\n\n// Globals\nint N, si, sj;\nvector<string> grid;\nvector<pair<int, int>> road_squares;\nmap<pair<int, int>, int> coord_to_id;\nvector<vector<pair<int, int>>> adj;\n\nstruct Segment {\n    int id;\n    vector<pair<int, int>> squares;\n};\nvector<Segment> segments;\n\n// Pre-computation functions\nvoid find_road_squares_and_build_graph() {\n    int current_id = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != '#') {\n                road_squares.push_back({i, j});\n                coord_to_id[{i, j}] = current_id++;\n            }\n        }\n    }\n\n    adj.resize(road_squares.size());\n    for (size_t i = 0; i < road_squares.size(); ++i) {\n        auto [r, c] = road_squares[i];\n        for (int move = 0; move < 4; ++move) {\n            int nr = r + DR[move];\n            int nc = c + DC[move];\n            if (nr >= 0 && nr < N && nc >= 0 && nc < N && grid[nr][nc] != '#') {\n                int neighbor_id = coord_to_id.at({nr, nc});\n                int cost = grid[nr][nc] - '0';\n                adj[i].push_back({neighbor_id, cost});\n            }\n        }\n    }\n}\n\nvoid find_segments() {\n    map<pair<int, int>, bool> visited_horz, visited_vert;\n    int seg_id_counter = 0;\n    for (const auto& p : road_squares) {\n        int r = p.first;\n        int c = p.second;\n\n        if (visited_horz.find(p) == visited_horz.end()) {\n            Segment seg;\n            seg.id = seg_id_counter++;\n            int c_start = c;\n            while (c_start > 0 && grid[r][c_start - 1] != '#') {\n                c_start--;\n            }\n            int c_end = c;\n            while (c_end < N - 1 && grid[r][c_end + 1] != '#') {\n                c_end++;\n            }\n            for (int j = c_start; j <= c_end; ++j) {\n                seg.squares.push_back({r, j});\n                visited_horz[{r, j}] = true;\n            }\n            segments.push_back(seg);\n        }\n\n        if (visited_vert.find(p) == visited_vert.end()) {\n            Segment seg;\n            seg.id = seg_id_counter++;\n            int r_start = r;\n            while (r_start > 0 && grid[r_start - 1][c] != '#') {\n                r_start--;\n            }\n            int r_end = r;\n            while (r_end < N - 1 && grid[r_end + 1][c] != '#') {\n                r_end++;\n            }\n            for (int i = r_start; i <= r_end; ++i) {\n                seg.squares.push_back({i, c});\n                visited_vert[{i, c}] = true;\n            }\n            segments.push_back(seg);\n        }\n    }\n}\n\n\n// Dijkstra for APSP\npair<vector<int>, vector<int>> dijkstra(int start_node_id) {\n    int n = road_squares.size();\n    vector<int> dist(n, INF);\n    vector<int> parent(n, -1);\n    dist[start_node_id] = 0;\n\n    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;\n    pq.push({0, start_node_id});\n\n    while (!pq.empty()) {\n        auto [d, u] = pq.top();\n        pq.pop();\n\n        if (d > dist[u]) continue;\n\n        for (auto& edge : adj[u]) {\n            int v = edge.first;\n            int weight = edge.second;\n            if (dist[u] + weight < dist[v]) {\n                dist[v] = dist[u] + weight;\n                parent[v] = u;\n                pq.push({dist[v], v});\n            }\n        }\n    }\n    return {dist, parent};\n}\n\n// Main logic\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    start_time = chrono::high_resolution_clock::now();\n\n    cin >> N >> si >> sj;\n    grid.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> grid[i];\n    }\n\n    find_road_squares_and_build_graph();\n    find_segments();\n    \n    // Step 3: Define Key Points and Solve Set Cover\n    set<pair<int, int>> key_points_set;\n    key_points_set.insert({si, sj});\n\n    for (const auto& seg : segments) {\n        key_points_set.insert(seg.squares.front());\n        if(seg.squares.size() > 1) {\n            key_points_set.insert(seg.squares.back());\n        }\n    }\n\n    for (int r = 0; r < N; r+=1) {\n        for (int c = 0; c < N; c+=1) {\n            if (grid[r][c] != '#') {\n                bool has_horz = false, has_vert = false;\n                if (c > 0 && grid[r][c-1] != '#') has_horz = true;\n                if (c < N-1 && grid[r][c+1] != '#') has_horz = true;\n                if (r > 0 && grid[r-1][c] != '#') has_vert = true;\n                if (r < N-1 && grid[r+1][c] != '#') has_vert = true;\n                if(has_horz && has_vert) {\n                     bool is_straight = (c > 0 && grid[r][c-1] != '#' && c < N-1 && grid[r][c+1] != '#') && !(r > 0 && grid[r-1][c] != '#') && !(r < N-1 && grid[r+1][c] != '#');\n                     is_straight |= (r > 0 && grid[r-1][c] != '#' && r < N-1 && grid[r+1][c] != '#') && !(c > 0 && grid[r][c-1] != '#') && !(c < N-1 && grid[r][c+1] != '#');\n                     if(!is_straight) key_points_set.insert({r,c});\n                }\n            }\n        }\n    }\n    \n    vector<pair<int, int>> key_points(key_points_set.begin(), key_points_set.end());\n    map<pair<int, int>, int> kp_to_idx;\n    for(size_t i=0; i<key_points.size(); ++i) kp_to_idx[key_points[i]] = i;\n\n    vector<vector<int>> kp_covers(key_points.size());\n    vector<vector<int>> seg_covered_by(segments.size());\n\n    for(size_t i=0; i<key_points.size(); ++i) {\n        for(const auto& seg : segments) {\n            for(const auto& sq : seg.squares) {\n                if(sq == key_points[i]) {\n                    kp_covers[i].push_back(seg.id);\n                    seg_covered_by[seg.id].push_back(i);\n                    break;\n                }\n            }\n        }\n    }\n    \n    set<int> segments_to_cover;\n    for (size_t i = 0; i < segments.size(); ++i) segments_to_cover.insert(i);\n\n    vector<int> kp_uncovered_count(key_points.size());\n    for(size_t i=0; i<key_points.size(); ++i) {\n        kp_uncovered_count[i] = kp_covers[i].size();\n    }\n    \n    set<pair<int, int>> target_kps_set;\n    while(!segments_to_cover.empty()) {\n        int best_kp_idx = -1;\n        int max_cover = -1;\n        \n        for(size_t i=0; i<key_points.size(); ++i) {\n            if(kp_uncovered_count[i] > max_cover) {\n                max_cover = kp_uncovered_count[i];\n                best_kp_idx = i;\n            }\n        }\n        \n        if (best_kp_idx == -1) break;\n\n        pair<int,int> best_kp_coord = key_points[best_kp_idx];\n        target_kps_set.insert(best_kp_coord);\n        \n        vector<int> segs_just_covered;\n        for(int seg_id : kp_covers[best_kp_idx]) {\n            if(segments_to_cover.count(seg_id)) {\n                segs_just_covered.push_back(seg_id);\n            }\n        }\n\n        for(int seg_id : segs_just_covered) {\n            segments_to_cover.erase(seg_id);\n            for(int kp_idx : seg_covered_by[seg_id]) {\n                kp_uncovered_count[kp_idx]--;\n            }\n        }\n    }\n\n    target_kps_set.insert({si, sj});\n    vector<pair<int, int>> V_tsp_coords(target_kps_set.begin(), target_kps_set.end());\n    int num_tsp_nodes = V_tsp_coords.size();\n    map<pair<int, int>, int> tsp_coord_to_idx;\n    for(int i=0; i<num_tsp_nodes; ++i) tsp_coord_to_idx[V_tsp_coords[i]] = i;\n\n    // Step 4: APSP\n    vector<vector<int>> dist_matrix(num_tsp_nodes, vector<int>(num_tsp_nodes));\n    vector<vector<int>> parents_matrix(num_tsp_nodes, vector<int>(road_squares.size()));\n\n    for(int i=0; i<num_tsp_nodes; ++i) {\n        int start_node_id = coord_to_id.at(V_tsp_coords[i]);\n        auto [dist, parent] = dijkstra(start_node_id);\n        parents_matrix[i] = parent;\n        for(int j=0; j<num_tsp_nodes; ++j) {\n            int end_node_id = coord_to_id.at(V_tsp_coords[j]);\n            dist_matrix[i][j] = dist[end_node_id];\n        }\n    }\n\n    // Step 5: Solve TSP\n    int start_tsp_idx = tsp_coord_to_idx.at({si, sj});\n    vector<int> tour;\n    tour.push_back(start_tsp_idx);\n    vector<bool> visited(num_tsp_nodes, false);\n    visited[start_tsp_idx] = true;\n\n    int current_tsp_idx = start_tsp_idx;\n    while(tour.size() < (size_t)num_tsp_nodes) {\n        int next_tsp_idx = -1;\n        int min_dist = INF;\n        for(int i=0; i<num_tsp_nodes; ++i) {\n            if(!visited[i]) {\n                if(dist_matrix[current_tsp_idx][i] < min_dist) {\n                    min_dist = dist_matrix[current_tsp_idx][i];\n                    next_tsp_idx = i;\n                }\n            }\n        }\n        if (next_tsp_idx == -1) break; // All remaining are unreachable\n        tour.push_back(next_tsp_idx);\n        visited[next_tsp_idx] = true;\n        current_tsp_idx = next_tsp_idx;\n    }\n    \n    // 2-opt\n    bool improved = true;\n    while(improved) {\n        auto elapsed_time = chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count();\n        if (elapsed_time > 2800) break;\n        improved = false;\n        for(int i=0; i<num_tsp_nodes; ++i) {\n            for(int j=i+2; j<num_tsp_nodes; ++j) {\n                if (i == 0 && j == num_tsp_nodes - 1) continue;\n                \n                int u1 = tour[i], v1 = tour[(i+1)%num_tsp_nodes];\n                int u2 = tour[j], v2 = tour[(j+1)%num_tsp_nodes];\n                \n                long long current_dist = dist_matrix[u1][v1] + dist_matrix[u2][v2];\n                long long new_dist = dist_matrix[u1][u2] + dist_matrix[v1][v2];\n                \n                if(new_dist < current_dist) {\n                    reverse(tour.begin() + i + 1, tour.begin() + j + 1);\n                    improved = true;\n                }\n            }\n        }\n    }\n    \n    auto it = find(tour.begin(), tour.end(), start_tsp_idx);\n    rotate(tour.begin(), it, tour.end());\n\n    // Step 6: Generate Output\n    string path_str = \"\";\n    for(size_t i=0; i<tour.size(); ++i) {\n        int u_tsp_idx = tour[i];\n        int v_tsp_idx = tour[(i+1)%tour.size()];\n        \n        int u_node_id = coord_to_id.at(V_tsp_coords[u_tsp_idx]);\n        int v_node_id = coord_to_id.at(V_tsp_coords[v_tsp_idx]);\n\n        vector<int> path;\n        int curr = v_node_id;\n        while(curr != -1 && curr != u_node_id) {\n            path.push_back(curr);\n            curr = parents_matrix[u_tsp_idx][curr];\n        }\n        reverse(path.begin(), path.end());\n        \n        pair<int, int> last_coord = V_tsp_coords[u_tsp_idx];\n        for(int node_id : path) {\n            auto [r, c] = road_squares[node_id];\n            if(r < last_coord.first) path_str += 'U';\n            else if(r > last_coord.first) path_str += 'D';\n            else if(c < last_coord.second) path_str += 'L';\n            else if(c > last_coord.second) path_str += 'R';\n            last_coord = {r, c};\n        }\n    }\n\n    cout << path_str << endl;\n\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <string>\n#include <sstream>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <functional>\n\n#include <atcoder/mincostflow>\n\n// Constants\nconstexpr int N_TASKS = 1000;\nconstexpr int M_MEMBERS = 20;\nconstexpr int MAX_DAYS = 2000;\n\n// Hyperparameters\nconst double INITIAL_SKILL_ESTIMATE = 0.0;\nconst double SKILL_UPDATE_LEARNING_RATE = 0.1;\nconst double EXPLORATION_DECAY_DAYS = 600.0;\nconst double EXPLORATION_LAMBDA_0 = 0.5;\nconst double OVERESTIMATE_CORRECTION_FACTOR = 0.1;\nconst int CANDIDATE_TASK_POOL_SIZE = 2 * M_MEMBERS;\n\n// Problem data\nint K, R;\nstd::vector<std::vector<int>> D; // Task difficulties\nstd::vector<std::vector<int>> adj; // Task dependencies\nstd::vector<std::vector<int>> rev_adj; // Reverse dependencies\n\n// State\nenum class TaskStatus { NOT_STARTED, IN_PROGRESS, COMPLETED };\nstd::vector<TaskStatus> task_status;\nint completed_task_count;\n\nstruct Member {\n    bool is_busy = false;\n    int task_id = -1;\n    int start_day = -1;\n};\nstd::vector<Member> members;\n\nstd::vector<std::vector<double>> estimated_skills;\nstd::vector<std::vector<int>> skill_lower_bounds;\nstd::vector<std::vector<int>> max_d_seen;\n\nstd::vector<int> cph; // Critical path heuristic value\n\n// Function to calculate estimated work for a task by a member\ndouble estimate_work(int task_id, int member_id) {\n    double work = 0;\n    for (int k = 0; k < K; ++k) {\n        work += std::max(0.0, (double)D[task_id][k] - estimated_skills[member_id][k]);\n    }\n    return work;\n}\n\n// Function to calculate estimated time\ndouble estimate_time(int task_id, int member_id) {\n    double work = estimate_work(task_id, member_id);\n    if (work < 1e-9) {\n        return 1.0;\n    }\n    return std::max(1.0, work);\n}\n\nvoid read_initial_input() {\n    std::cin >> K >> R; // N and M are constants\n    D.resize(N_TASKS, std::vector<int>(K));\n    for (int i = 0; i < N_TASKS; ++i) {\n        for (int j = 0; j < K; ++j) {\n            std::cin >> D[i][j];\n        }\n    }\n    adj.assign(N_TASKS, std::vector<int>());\n    rev_adj.assign(N_TASKS, std::vector<int>());\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        std::cin >> u >> v;\n        --u; --v;\n        adj[u].push_back(v);\n        rev_adj[v].push_back(u);\n    }\n}\n\nvoid compute_cph() {\n    cph.assign(N_TASKS, -1);\n    std::function<int(int)> dfs = [&](int u) {\n        if (cph[u] != -1) {\n            return cph[u];\n        }\n        int max_len = 0;\n        for (int v : adj[u]) {\n            max_len = std::max(max_len, dfs(v));\n        }\n        return cph[u] = 1 + max_len;\n    };\n    for (int i = 0; i < N_TASKS; ++i) {\n        dfs(i);\n    }\n}\n\nvoid initialize_state() {\n    task_status.assign(N_TASKS, TaskStatus::NOT_STARTED);\n    completed_task_count = 0;\n    members.resize(M_MEMBERS);\n    estimated_skills.assign(M_MEMBERS, std::vector<double>(K, INITIAL_SKILL_ESTIMATE));\n    skill_lower_bounds.assign(M_MEMBERS, std::vector<int>(K, 0));\n    max_d_seen.assign(M_MEMBERS, std::vector<int>(K, 0));\n}\n\nvoid update_skills(int member_id, int task_id, int duration) {\n    for (int k = 0; k < K; ++k) {\n        max_d_seen[member_id][k] = std::max(max_d_seen[member_id][k], D[task_id][k]);\n    }\n\n    if (duration == 1) {\n        for (int k = 0; k < K; ++k) {\n            skill_lower_bounds[member_id][k] = std::max(skill_lower_bounds[member_id][k], D[task_id][k]);\n            estimated_skills[member_id][k] = std::max(estimated_skills[member_id][k], (double)skill_lower_bounds[member_id][k]);\n        }\n    } else {\n        double predicted_w = estimate_work(task_id, member_id);\n        double observed_w = duration;\n        \n        if (predicted_w < 1e-6) {\n            std::vector<int> candidate_k;\n            for(int k=0; k<K; ++k) if(D[task_id][k] > 0) candidate_k.push_back(k);\n\n            if (!candidate_k.empty()) {\n                std::vector<double> blame_weights;\n                double total_blame = 0;\n                for (int k : candidate_k) {\n                    double weight = std::exp(-OVERESTIMATE_CORRECTION_FACTOR * (estimated_skills[member_id][k] - D[task_id][k]));\n                    blame_weights.push_back(weight);\n                    total_blame += weight;\n                }\n\n                for (size_t i = 0; i < candidate_k.size(); ++i) {\n                    int k = candidate_k[i];\n                    double blamed_deficiency = observed_w * blame_weights[i] / total_blame;\n                    double target_s_k = D[task_id][k] - blamed_deficiency;\n                    estimated_skills[member_id][k] = (1.0 - SKILL_UPDATE_LEARNING_RATE) * estimated_skills[member_id][k] + SKILL_UPDATE_LEARNING_RATE * target_s_k;\n                }\n            }\n        } else {\n            double target_w = observed_w;\n            for (int k=0; k<K; ++k) {\n                 if (D[task_id][k] - estimated_skills[member_id][k] > 0) {\n                    double current_deficiency = D[task_id][k] - estimated_skills[member_id][k];\n                    double target_deficiency = current_deficiency * target_w / predicted_w;\n                    double target_s_k = D[task_id][k] - target_deficiency;\n                    estimated_skills[member_id][k] = (1.0 - SKILL_UPDATE_LEARNING_RATE) * estimated_skills[member_id][k] + SKILL_UPDATE_LEARNING_RATE * target_s_k;\n                }\n            }\n        }\n    }\n\n    for (int k = 0; k < K; ++k) {\n        estimated_skills[member_id][k] = std::max((double)skill_lower_bounds[member_id][k], estimated_skills[member_id][k]);\n        estimated_skills[member_id][k] = std::max(0.0, estimated_skills[member_id][k]);\n    }\n    \n    std::cout << \"#s \" << member_id + 1;\n    for (int k = 0; k < K; ++k) {\n        std::cout << \" \" << static_cast<int>(round(estimated_skills[member_id][k]));\n    }\n    std::cout << std::endl;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int N_dummy, M_dummy;\n    std::cin >> N_dummy >> M_dummy;\n    \n    read_initial_input();\n    compute_cph();\n    initialize_state();\n\n    for (int day = 1; day <= MAX_DAYS; ++day) {\n        std::vector<int> free_members_ids;\n        for (int i = 0; i < M_MEMBERS; ++i) {\n            if (!members[i].is_busy) {\n                free_members_ids.push_back(i);\n            }\n        }\n\n        std::vector<int> schedulable_tasks_ids;\n        for (int i = 0; i < N_TASKS; ++i) {\n            if (task_status[i] == TaskStatus::NOT_STARTED) {\n                bool all_deps_done = true;\n                for (int dep : rev_adj[i]) {\n                    if (task_status[dep] != TaskStatus::COMPLETED) {\n                        all_deps_done = false;\n                        break;\n                    }\n                }\n                if (all_deps_done) {\n                    schedulable_tasks_ids.push_back(i);\n                }\n            }\n        }\n\n        std::vector<std::pair<int, int>> assignments;\n        if (!free_members_ids.empty() && !schedulable_tasks_ids.empty()) {\n            std::sort(schedulable_tasks_ids.begin(), schedulable_tasks_ids.end(), [&](int a, int b) {\n                if (cph[a] != cph[b]) return cph[a] > cph[b];\n                return a < b;\n            });\n            if (schedulable_tasks_ids.size() > CANDIDATE_TASK_POOL_SIZE) {\n                schedulable_tasks_ids.resize(CANDIDATE_TASK_POOL_SIZE);\n            }\n\n            int num_free_members = free_members_ids.size();\n            int num_cand_tasks = schedulable_tasks_ids.size();\n            atcoder::mcf_graph<int, long long> graph(num_free_members + num_cand_tasks + 2);\n            int s = num_free_members + num_cand_tasks;\n            int t = s + 1;\n\n            double lambda = EXPLORATION_LAMBDA_0 * std::max(0.0, (EXPLORATION_DECAY_DAYS - day) / EXPLORATION_DECAY_DAYS);\n\n            for (int i = 0; i < num_free_members; ++i) graph.add_edge(s, i, 1, 0);\n            for (int i = 0; i < num_cand_tasks; ++i) graph.add_edge(num_free_members + i, t, 1, 0);\n\n            for (int i = 0; i < num_free_members; ++i) {\n                int member_id = free_members_ids[i];\n                for (int j = 0; j < num_cand_tasks; ++j) {\n                    int task_id = schedulable_tasks_ids[j];\n                    double t_est = estimate_time(task_id, member_id);\n                    double novelty = 0;\n                    for (int k = 0; k < K; ++k) {\n                        novelty += std::max(0, D[task_id][k] - max_d_seen[member_id][k]);\n                    }\n                    long long cost = static_cast<long long>(round(100.0 * t_est - 100.0 * lambda * novelty));\n                    graph.add_edge(i, num_free_members + j, 1, cost);\n                }\n            }\n\n            graph.flow(s, t, std::min(num_free_members, num_cand_tasks));\n            for (const auto& edge : graph.edges()) {\n                if (edge.from < num_free_members && edge.to >= num_free_members && edge.to < s && edge.flow > 0) {\n                    int member_idx = edge.from;\n                    int task_idx = edge.to - num_free_members;\n                    assignments.emplace_back(free_members_ids[member_idx], schedulable_tasks_ids[task_idx]);\n                }\n            }\n        }\n        \n        std::cout << assignments.size();\n        for (const auto& p : assignments) {\n            int member_id = p.first;\n            int task_id = p.second;\n            std::cout << \" \" << member_id + 1 << \" \" << task_id + 1;\n            members[member_id] = {true, task_id, day};\n            task_status[task_id] = TaskStatus::IN_PROGRESS;\n        }\n        std::cout << std::endl;\n\n        int n_finished;\n        std::cin >> n_finished;\n        if (n_finished == -1) break;\n        \n        for (int i = 0; i < n_finished; ++i) {\n            int finished_member_id;\n            std::cin >> finished_member_id;\n            --finished_member_id;\n\n            int task_id = members[finished_member_id].task_id;\n            int start_day = members[finished_member_id].start_day;\n            int duration = day - start_day + 1;\n\n            members[finished_member_id] = {false, -1, -1};\n            task_status[task_id] = TaskStatus::COMPLETED;\n            completed_task_count++;\n            \n            update_skills(finished_member_id, task_id, duration);\n        }\n    }\n    return 0;\n}","ahc006":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n#include <chrono>\n#include <random>\n\n// A fast random number generator\nclass Xoshiro256pp {\npublic:\n    using result_type = uint64_t;\n    static constexpr result_type min() { return std::numeric_limits<result_type>::min(); }\n    static constexpr result_type max() { return std::numeric_limits<result_type>::max(); }\n\n    Xoshiro256pp() : Xoshiro256pp(std::random_device{}()) {}\n    explicit Xoshiro256pp(uint64_t seed) {\n        s[0] = seed; s[1] = 0; s[2] = 0; s[3] = 0;\n    }\n\n    result_type operator()() {\n        const uint64_t result = rotl(s[0] + s[3], 23) + s[0];\n        const uint64_t t = s[1] << 17;\n        s[2] ^= s[0]; s[3] ^= s[1]; s[1] ^= s[2]; s[0] ^= s[3];\n        s[2] ^= t; s[3] = rotl(s[3], 45);\n        return result;\n    }\n\n    int next_int(int min, int max) {\n        return min + operator()() % (uint64_t)(max - min + 1);\n    }\n\n    double next_double() {\n        return (operator()() >> 11) * (1.0 / (1ULL << 53));\n    }\n\nprivate:\n    static inline uint64_t rotl(const uint64_t x, int k) {\n        return (x << k) | (x >> (64 - k));\n    }\n    uint64_t s[4];\n};\n\nXoshiro256pp rng;\n\nstruct Point {\n    int x, y;\n};\n\nstruct Order {\n    int id;\n    Point p, d;\n};\n\nconst int NUM_ORDERS_TOTAL = 1000;\nconst int ORDERS_TO_DELIVER = 50;\nconst Point OFFICE = {400, 400};\nstd::vector<Order> ALL_ORDERS;\n\nint manhattan(Point p1, Point p2) {\n    return std::abs(p1.x - p2.x) + std::abs(p1.y - p2.y);\n}\n\nstruct State {\n    std::vector<int> selected_g_indices;\n    std::vector<int> path;\n    long long cost;\n};\n\nPoint get_coord(int node_id, const std::vector<int>& selected_g_indices) {\n    if (node_id < ORDERS_TO_DELIVER) {\n        return ALL_ORDERS[selected_g_indices[node_id]].p;\n    } else {\n        return ALL_ORDERS[selected_g_indices[node_id - ORDERS_TO_DELIVER]].d;\n    }\n}\n\nlong long calculate_cost(const std::vector<int>& path, const std::vector<int>& selected_g_indices) {\n    if (path.empty()) return 0;\n    long long total_dist = 0;\n    total_dist += manhattan(OFFICE, get_coord(path[0], selected_g_indices));\n    for (size_t i = 0; i < path.size() - 1; ++i) {\n        total_dist += manhattan(get_coord(path[i], selected_g_indices), get_coord(path[i + 1], selected_g_indices));\n    }\n    total_dist += manhattan(get_coord(path.back(), selected_g_indices), OFFICE);\n    return total_dist;\n}\n\nvoid solve() {\n    auto start_time = std::chrono::steady_clock::now();\n\n    ALL_ORDERS.resize(NUM_ORDERS_TOTAL);\n    for (int i = 0; i < NUM_ORDERS_TOTAL; ++i) {\n        ALL_ORDERS[i].id = i + 1;\n        std::cin >> ALL_ORDERS[i].p.x >> ALL_ORDERS[i].p.y >> ALL_ORDERS[i].d.x >> ALL_ORDERS[i].d.y;\n    }\n\n    // --- Initial Solution ---\n    State current_state;\n    // 1. Select initial 50 orders based on proximity to office\n    std::vector<int> order_indices(NUM_ORDERS_TOTAL);\n    std::iota(order_indices.begin(), order_indices.end(), 0);\n    std::sort(order_indices.begin(), order_indices.end(), [&](int a, int b) {\n        Point center_a = {(ALL_ORDERS[a].p.x + ALL_ORDERS[a].d.x) / 2, (ALL_ORDERS[a].p.y + ALL_ORDERS[a].d.y) / 2};\n        Point center_b = {(ALL_ORDERS[b].p.x + ALL_ORDERS[b].d.x) / 2, (ALL_ORDERS[b].p.y + ALL_ORDERS[b].d.y) / 2};\n        return manhattan(OFFICE, center_a) < manhattan(OFFICE, center_b);\n    });\n    current_state.selected_g_indices.assign(order_indices.begin(), order_indices.begin() + ORDERS_TO_DELIVER);\n\n    // 2. Build initial path (Sequential greedy insertion)\n    for (int i = 0; i < ORDERS_TO_DELIVER; ++i) {\n        int p_node = i;\n        int d_node = i + ORDERS_TO_DELIVER;\n        \n        long long min_p_cost_increase = -1;\n        int best_p_pos = 0;\n        for (int j = 0; j <= (int)current_state.path.size(); ++j) {\n            Point prev = (j == 0) ? OFFICE : get_coord(current_state.path[j - 1], current_state.selected_g_indices);\n            Point next = (j == (int)current_state.path.size()) ? OFFICE : get_coord(current_state.path[j], current_state.selected_g_indices);\n            Point current = get_coord(p_node, current_state.selected_g_indices);\n            long long cost_increase = manhattan(prev, current) + manhattan(current, next) - manhattan(prev, next);\n            if (min_p_cost_increase == -1 || cost_increase < min_p_cost_increase) {\n                min_p_cost_increase = cost_increase;\n                best_p_pos = j;\n            }\n        }\n        current_state.path.insert(current_state.path.begin() + best_p_pos, p_node);\n\n        long long min_d_cost_increase = -1;\n        int best_d_pos = 0;\n        for (int j = best_p_pos + 1; j <= (int)current_state.path.size(); ++j) {\n            Point prev = get_coord(current_state.path[j - 1], current_state.selected_g_indices);\n            Point next = (j == (int)current_state.path.size()) ? OFFICE : get_coord(current_state.path[j], current_state.selected_g_indices);\n            Point current = get_coord(d_node, current_state.selected_g_indices);\n            long long cost_increase = manhattan(prev, current) + manhattan(current, next) - manhattan(prev, next);\n            if (min_d_cost_increase == -1 || cost_increase < min_d_cost_increase) {\n                min_d_cost_increase = cost_increase;\n                best_d_pos = j;\n            }\n        }\n        current_state.path.insert(current_state.path.begin() + best_d_pos, d_node);\n    }\n    \n    current_state.cost = calculate_cost(current_state.path, current_state.selected_g_indices);\n    State best_state = current_state;\n\n    // Prepare for SA\n    std::vector<bool> is_selected_flags(NUM_ORDERS_TOTAL, false);\n    for(int g_idx : current_state.selected_g_indices) is_selected_flags[g_idx] = true;\n    std::vector<int> not_selected_g_indices;\n    not_selected_g_indices.reserve(NUM_ORDERS_TOTAL - ORDERS_TO_DELIVER);\n    for(int i=0; i<NUM_ORDERS_TOTAL; ++i) if(!is_selected_flags[i]) not_selected_g_indices.push_back(i);\n\n    // --- Simulated Annealing ---\n    double T_start = 5000;\n    double T_end = 1;\n    double time_limit = 1.95;\n    std::vector<int> pos(ORDERS_TO_DELIVER * 2);\n    \n    while (true) {\n        auto current_time = std::chrono::steady_clock::now();\n        double elapsed_time = std::chrono::duration<double>(current_time - start_time).count();\n        if (elapsed_time > time_limit) break;\n        double T = T_start + (T_end - T_start) * elapsed_time / time_limit;\n\n        if (rng.next_int(0, 1) == 0) { // Move 1: Replace Order\n            int local_idx = rng.next_int(0, ORDERS_TO_DELIVER - 1);\n            int g_idx_to_remove = current_state.selected_g_indices[local_idx];\n            int not_selected_vec_idx = rng.next_int(0, not_selected_g_indices.size() - 1);\n            int new_g_idx = not_selected_g_indices[not_selected_vec_idx];\n\n            for (size_t i = 0; i < current_state.path.size(); ++i) pos[current_state.path[i]] = i;\n            \n            int p_node = local_idx;\n            int d_node = local_idx + ORDERS_TO_DELIVER;\n            int p_pos = pos[p_node];\n            int d_pos = pos[d_node];\n\n            Point p_old = ALL_ORDERS[g_idx_to_remove].p;\n            Point d_old = ALL_ORDERS[g_idx_to_remove].d;\n            Point p_new = ALL_ORDERS[new_g_idx].p;\n            Point d_new = ALL_ORDERS[new_g_idx].d;\n            long long delta = 0;\n            \n            Point p_prev = (p_pos == 0) ? OFFICE : get_coord(current_state.path[p_pos-1], current_state.selected_g_indices);\n            Point p_next = (p_pos == current_state.path.size()-1) ? OFFICE : get_coord(current_state.path[p_pos+1], current_state.selected_g_indices);\n            Point d_prev = (d_pos == 0) ? OFFICE : get_coord(current_state.path[d_pos-1], current_state.selected_g_indices);\n            Point d_next = (d_pos == current_state.path.size()-1) ? OFFICE : get_coord(current_state.path[d_pos+1], current_state.selected_g_indices);\n\n            if (d_pos == p_pos + 1) { // adjacent\n                delta -= manhattan(p_prev, p_old) + manhattan(p_old, d_old) + manhattan(d_old, d_next);\n                delta += manhattan(p_prev, p_new) + manhattan(p_new, d_new) + manhattan(d_new, d_next);\n            } else {\n                delta -= manhattan(p_prev, p_old) + manhattan(p_old, p_next);\n                delta += manhattan(p_prev, p_new) + manhattan(p_new, p_next);\n                delta -= manhattan(d_prev, d_old) + manhattan(d_old, d_next);\n                delta += manhattan(d_prev, d_new) + manhattan(d_new, d_next);\n            }\n\n            if (delta < 0 || rng.next_double() < std::exp(-delta / T)) {\n                current_state.selected_g_indices[local_idx] = new_g_idx;\n                not_selected_g_indices[not_selected_vec_idx] = g_idx_to_remove;\n                current_state.cost += delta;\n                if (current_state.cost < best_state.cost) {\n                    best_state = current_state;\n                }\n            }\n        } else { // Move 2: 2-opt\n            int i = rng.next_int(0, current_state.path.size() - 1);\n            int j = rng.next_int(0, current_state.path.size() - 1);\n            if (i == j) continue;\n            if (i > j) std::swap(i, j);\n            if (j <= i + 1) continue;\n            \n            for (size_t k = 0; k < current_state.path.size(); ++k) pos[current_state.path[k]] = k;\n            bool possible = true;\n            for (int k = 0; k < ORDERS_TO_DELIVER; ++k) {\n                if (pos[k] >= i && pos[k] <= j && pos[k + ORDERS_TO_DELIVER] >= i && pos[k + ORDERS_TO_DELIVER] <= j) {\n                    possible = false;\n                    break;\n                }\n            }\n            if (!possible) continue;\n            \n            Point p_i = get_coord(current_state.path[i], current_state.selected_g_indices);\n            Point p_j = get_coord(current_state.path[j], current_state.selected_g_indices);\n            Point p_i_prev = (i > 0) ? get_coord(current_state.path[i - 1], current_state.selected_g_indices) : OFFICE;\n            Point p_j_next = (j < (int)current_state.path.size() - 1) ? get_coord(current_state.path[j + 1], current_state.selected_g_indices) : OFFICE;\n\n            long long delta = manhattan(p_i_prev, p_j) + manhattan(p_i, p_j_next) - manhattan(p_i_prev, p_i) - manhattan(p_j, p_j_next);\n\n            if (delta < 0 || rng.next_double() < std::exp(-delta / T)) {\n                std::reverse(current_state.path.begin() + i, current_state.path.begin() + j + 1);\n                current_state.cost += delta;\n                if (current_state.cost < best_state.cost) {\n                    best_state = current_state;\n                }\n            }\n        }\n    }\n    \n    // Output best found solution\n    std::cout << ORDERS_TO_DELIVER;\n    for (int g_idx : best_state.selected_g_indices) {\n        std::cout << \" \" << ALL_ORDERS[g_idx].id;\n    }\n    std::cout << std::endl;\n\n    std::cout << best_state.path.size() + 2;\n    std::cout << \" \" << OFFICE.x << \" \" << OFFICE.y;\n    for (int node_id : best_state.path) {\n        Point p = get_coord(node_id, best_state.selected_g_indices);\n        std::cout << \" \" << p.x << \" \" << p.y;\n    }\n    std::cout << \" \" << OFFICE.x << \" \" << OFFICE.y;\n    std::cout << std::endl;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <map>\n#include <tuple>\n\n// Using AtCoder Library's DSU\n#include <atcoder/dsu>\n\nstruct Point {\n    int x, y;\n};\n\nstruct Edge {\n    int u, v, id;\n    int original_d;\n};\n\nlong long dist_sq(const Point& p1, const Point& p2) {\n    long long dx = p1.x - p2.x;\n    long long dy = p1.y - p2.y;\n    return dx * dx + dy * dy;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    const int N = 400;\n    const int M = 1995;\n\n    std::vector<Point> vertices(N);\n    for (int i = 0; i < N; ++i) {\n        std::cin >> vertices[i].x >> vertices[i].y;\n    }\n\n    std::vector<Edge> edges(M);\n    std::map<std::pair<int, int>, int> edge_to_id;\n    for (int i = 0; i < M; ++i) {\n        edges[i].id = i;\n        std::cin >> edges[i].u >> edges[i].v;\n        edges[i].original_d = std::round(std::sqrt(dist_sq(vertices[edges[i].u], vertices[edges[i].v])));\n        edge_to_id[{edges[i].u, edges[i].v}] = i;\n    }\n\n    // --- Preprocessing ---\n\n    // 1. Calculate importance levels\n    std::vector<int> importance(M, 0);\n    {\n        std::vector<std::tuple<int, int, int>> all_possible_edges;\n        all_possible_edges.reserve(N * (N - 1) / 2);\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) {\n                int d = std::round(std::sqrt(dist_sq(vertices[i], vertices[j])));\n                all_possible_edges.emplace_back(d, i, j);\n            }\n        }\n        std::sort(all_possible_edges.begin(), all_possible_edges.end());\n\n        std::vector<bool> used_in_mst(all_possible_edges.size(), false);\n        for (int k = 1; k <= 5; ++k) {\n            atcoder::dsu dsu_mst(N);\n            int edges_in_tree = 0;\n            for (size_t i = 0; i < all_possible_edges.size(); ++i) {\n                if (used_in_mst[i]) continue;\n                auto [d, u, v] = all_possible_edges[i];\n                if (dsu_mst.same(u, v)) continue;\n\n                dsu_mst.unite(u, v);\n                used_in_mst[i] = true;\n                \n                if (edge_to_id.count({u, v})) {\n                    int original_id = edge_to_id.at({u, v});\n                    if (importance[original_id] == 0) {\n                        importance[original_id] = k;\n                    }\n                }\n                edges_in_tree++;\n                if (edges_in_tree == N - 1) break;\n            }\n        }\n    }\n\n    // 2. Group edges by vertex pairs for quick lookup\n    std::map<std::pair<int, int>, std::vector<int>> edges_by_pair;\n    for (int i = 0; i < M; ++i) {\n        edges_by_pair[{edges[i].u, edges[i].v}].push_back(i);\n    }\n    for (auto& pair_vec : edges_by_pair) {\n        std::sort(pair_vec.second.begin(), pair_vec.second.end());\n    }\n\n    // --- Main Loop ---\n    atcoder::dsu dsu_main(N);\n    std::vector<std::vector<int>> component_members(N);\n    for(int i = 0; i < N; ++i) {\n        component_members[i] = {i};\n    }\n\n    for (int i = 0; i < M; ++i) {\n        int l;\n        std::cin >> l;\n\n        int u = edges[i].u;\n        int v = edges[i].v;\n\n        if (dsu_main.same(u, v)) {\n            std::cout << 0 << std::endl;\n            continue;\n        }\n\n        bool has_alternative = false;\n        int root_u = dsu_main.leader(u);\n        int root_v = dsu_main.leader(v);\n\n        auto check_alternatives = [&](const std::vector<int>& comp1, const std::vector<int>& comp2) {\n            for (int member1 : comp1) {\n                for (int member2 : comp2) {\n                    int p1 = std::min(member1, member2);\n                    int p2 = std::max(member1, member2);\n                    if (edges_by_pair.count({p1, p2})) {\n                        auto const& candidates = edges_by_pair.at({p1, p2});\n                        auto it = std::upper_bound(candidates.begin(), candidates.end(), i);\n                        if (it != candidates.end()) {\n                            return true;\n                        }\n                    }\n                }\n            }\n            return false;\n        };\n\n        if (component_members[root_u].size() < component_members[root_v].size()) {\n            has_alternative = check_alternatives(component_members[root_u], component_members[root_v]);\n        } else {\n            has_alternative = check_alternatives(component_members[root_v], component_members[root_u]);\n        }\n        \n        bool take_edge = false;\n        if (!has_alternative) {\n            take_edge = true;\n        } else {\n            int imp = importance[i];\n            if (imp == 0) imp = 6; // Fallback for edges not in top 5 MSTs\n            \n            double threshold_multiplier;\n            switch(imp) {\n                case 1: threshold_multiplier = 3.1; break;\n                case 2: threshold_multiplier = 2.6; break;\n                case 3: threshold_multiplier = 2.2; break;\n                case 4: threshold_multiplier = 1.8; break;\n                case 5: threshold_multiplier = 1.4; break;\n                default: threshold_multiplier = 1.0; break;\n            }\n\n            if (l < threshold_multiplier * edges[i].original_d) {\n                take_edge = true;\n            }\n        }\n        \n        if (take_edge) {\n            std::cout << 1 << std::endl;\n            \n            int old_root_u = dsu_main.leader(u);\n            int old_root_v = dsu_main.leader(v);\n            \n            dsu_main.unite(u, v);\n            int new_root = dsu_main.leader(u);\n\n            if (new_root == old_root_u) { // v merged into u\n                component_members[old_root_u].insert(component_members[old_root_u].end(),\n                    std::make_move_iterator(component_members[old_root_v].begin()),\n                    std::make_move_iterator(component_members[old_root_v].end()));\n                component_members[old_root_v].clear();\n            } else { // u merged into v\n                component_members[old_root_v].insert(component_members[old_root_v].end(),\n                    std::make_move_iterator(component_members[old_root_u].begin()),\n                    std::make_move_iterator(component_members[old_root_u].end()));\n                component_members[old_root_u].clear();\n            }\n        } else {\n            std::cout << 0 << std::endl;\n        }\n    }\n\n    return 0;\n}","ahc008":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <queue>\n#include <map>\n#include <chrono>\n#include <tuple>\n#include <numeric>\n\nusing namespace std;\n\n// --- Utilities ---\nstruct Point {\n    int r, c;\n\n    bool operator==(const Point& other) const { return r == other.r && c == other.c; }\n    bool operator!=(const Point& other) const { return !(*this == other); }\n    bool operator<(const Point& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n};\n\nnamespace std {\n    template <> struct hash<Point> {\n        size_t operator()(const Point& p) const { return hash<int>()(p.r * 31 + p.c); }\n    };\n}\n\nconst int H = 30, W = 30;\nconst int DR[] = {-1, 1, 0, 0};\nconst int DC[] = {0, 0, -1, 1};\nconst char MOVE_CH[] = {'U', 'D', 'L', 'R'};\nconst char BUILD_CH[] = {'u', 'd', 'l', 'r'};\n\nint N, M;\nvector<Point> pet_pos;\nvector<int> pet_type;\nvector<Point> human_pos;\nbool is_impassable[H][W];\n\nint dist(Point p1, Point p2) {\n    return abs(p1.r - p2.r) + abs(p1.c - p2.c);\n}\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < H && c >= 0 && c < W;\n}\n\n// --- Game State & Strategy ---\nPoint rendezvous_point;\nbool is_safe[H][W];\nvector<double> danger_map(H * W, 0.0);\nint current_turn = 0;\n\nenum Phase { EXPANSION, SEALING, CONSOLIDATION };\n\n// --- A* Pathfinder ---\nstruct Node {\n    Point p;\n    int g;\n    double h;\n    double cost;\n    bool operator>(const Node& other) const { return cost > other.cost; }\n};\n\nvector<Point> find_path(Point start, Point end, const vector<Point>& temp_impassable) {\n    priority_queue<Node, vector<Node>, greater<Node>> pq;\n    map<Point, Point> parent;\n    map<Point, int> g_score;\n\n    g_score[start] = 0;\n    pq.push({start, 0, (double)dist(start, end), (double)dist(start, end)});\n\n    bool found = false;\n    while (!pq.empty()) {\n        Node current = pq.top();\n        pq.pop();\n\n        if (current.p == end) {\n            found = true;\n            break;\n        }\n\n        if (g_score.count(current.p) && current.g > g_score[current.p]) continue;\n\n        for (int i = 0; i < 4; ++i) {\n            Point next_p = {current.p.r + DR[i], current.p.c + DC[i]};\n\n            if (!is_valid(next_p.r, next_p.c) || is_impassable[next_p.r][next_p.c]) continue;\n            bool is_temp_impassable = false;\n            for(const auto& obs : temp_impassable) if(obs == next_p) is_temp_impassable = true;\n            if(is_temp_impassable) continue;\n\n            int new_g = current.g + 1;\n            if (!g_score.count(next_p) || new_g < g_score[next_p]) {\n                g_score[next_p] = new_g;\n                parent[next_p] = current.p;\n                double h_val = dist(next_p, end);\n                const double DANGER_WEIGHT = 10.0;\n                double cost = new_g + h_val + DANGER_WEIGHT * danger_map[next_p.r * W + next_p.c];\n                pq.push({next_p, new_g, h_val, cost});\n            }\n        }\n    }\n\n    if (!found) return {};\n    vector<Point> path;\n    Point curr = end;\n    while (curr != start) {\n        path.push_back(curr);\n        curr = parent[curr];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nvoid initial_plan() {\n    double pet_com_r = 0, pet_com_c = 0;\n    for (const auto& p : pet_pos) { pet_com_r += p.r; pet_com_c += p.c; }\n    pet_com_r /= N;\n    pet_com_c /= N;\n\n    vector<Point> corners = {{0, 0}, {0, W - 1}, {H - 1, 0}, {H - 1, W - 1}};\n    double max_dist = -1;\n    for (const auto& corner : corners) {\n        double d = pow(corner.r - pet_com_r, 2) + pow(corner.c - pet_com_c, 2);\n        if (d > max_dist) {\n            max_dist = d;\n            rendezvous_point = corner;\n        }\n    }\n    fill(&is_safe[0][0], &is_safe[0][0] + H * W, false);\n}\n\nvoid update_danger_map() {\n    fill(danger_map.begin(), danger_map.end(), 0.0);\n    int pet_moves[] = {0, 1, 2, 3, 2, 2}; \n    for (int i = 0; i < N; ++i) {\n        int radius = pet_moves[pet_type[i]] + 1;\n        for (int r = 0; r < H; ++r) {\n            for (int c = 0; c < W; ++c) {\n                if (dist(pet_pos[i], {r, c}) < radius) {\n                    danger_map[r * W + c] += 1.0;\n                }\n            }\n        }\n    }\n}\n\nvoid update_safe_zone() {\n    bool new_safe[H][W];\n    fill(&new_safe[0][0], &new_safe[0][0] + H * W, false);\n    queue<Point> q;\n    \n    Point start_node = rendezvous_point;\n    if(is_impassable[start_node.r][start_node.c]) {\n        bool found_any_passable = false;\n        for(int r=0; r<H && !found_any_passable; ++r) for(int c=0; c<W; ++c) {\n            if(!is_impassable[r][c]) {\n                start_node = {r,c};\n                found_any_passable = true;\n                break;\n            }\n        }\n        if(!found_any_passable) {\n            copy(&new_safe[0][0], &new_safe[0][0] + H*W, &is_safe[0][0]);\n            return;\n        }\n    }\n    q.push(start_node);\n    new_safe[start_node.r][start_node.c] = true;\n\n    while (!q.empty()) {\n        Point curr = q.front(); q.pop();\n        for (int i = 0; i < 4; ++i) {\n            Point next_p = {curr.r + DR[i], curr.c + DC[i]};\n            if (is_valid(next_p.r, next_p.c) && !is_impassable[next_p.r][next_p.c] && !new_safe[next_p.r][next_p.c]) {\n                new_safe[next_p.r][next_p.c] = true;\n                q.push(next_p);\n            }\n        }\n    }\n    copy(&new_safe[0][0], &new_safe[0][0] + H*W, &is_safe[0][0]);\n}\n\nvoid check_and_reset_plan() {\n    if (current_turn > 50 && current_turn % 20 == 0) {\n        int safe_zone_size = 0;\n        for(int r=0; r<H; ++r) for(int c=0; c<W; ++c) if(is_safe[r][c]) safe_zone_size++;\n\n        bool pet_in_safe_zone = false;\n        for (const auto& p_pos : pet_pos) {\n            if (is_safe[p_pos.r][p_pos.c]) {\n                pet_in_safe_zone = true;\n                break;\n            }\n        }\n        if (pet_in_safe_zone && safe_zone_size > 20) initial_plan();\n    }\n}\n\nstring solve() {\n    const int PHASE1_END = 260;\n    const int PHASE2_END = 290;\n    \n    if (current_turn == 0) initial_plan();\n    else check_and_reset_plan();\n\n    Phase current_phase = EXPANSION;\n    if (current_turn >= PHASE1_END) current_phase = SEALING;\n    if (current_turn >= PHASE2_END) current_phase = CONSOLIDATION;\n\n    update_danger_map();\n    update_safe_zone();\n    \n    vector<bool> can_build(H * W, true);\n    for(int r=0; r<H; ++r) for(int c=0; c<W; ++c) {\n        if (is_impassable[r][c]) can_build[r*W+c] = false;\n    }\n    for (const auto& p : human_pos) can_build[p.r*W+p.c] = false;\n    for (const auto& p : pet_pos) {\n        can_build[p.r*W+p.c] = false;\n        for (int i=0; i<4; ++i) {\n            Point adj = {p.r+DR[i], p.c+DC[i]};\n            if (is_valid(adj.r, adj.c)) can_build[adj.r*W+adj.c] = false;\n        }\n    }\n\n    vector<Point> tasks;\n    if (current_phase == EXPANSION || current_phase == SEALING) {\n        for (int r=0; r<H; ++r) for (int c=0; c<W; ++c) {\n            if (!is_safe[r][c] && !is_impassable[r][c]) {\n                for (int i=0; i<4; ++i) {\n                    Point adj = {r+DR[i], c+DC[i]};\n                    if (is_valid(adj.r, adj.c) && is_safe[adj.r][adj.c]) {\n                        tasks.push_back({r,c});\n                        break;\n                    }\n                }\n            }\n        }\n    } else { // CONSOLIDATION\n        double center_r=0, center_c=0; int count=0;\n        for (int r=0; r<H; ++r) for (int c=0; c<W; ++c) if (is_safe[r][c]) { center_r+=r; center_c+=c; count++; }\n        if (count > 0) tasks.push_back({(int)round(center_r/count), (int)round(center_c/count)});\n        else tasks.push_back(rendezvous_point);\n    }\n    \n    vector<int> human_task(M, -1);\n    using AssignmentCand = tuple<int, int, int>;\n    vector<AssignmentCand> candidates;\n    if (!tasks.empty()){\n        for (int i=0; i<M; ++i) {\n            for (int j=0; j<(int)tasks.size(); ++j) {\n                if (current_phase == CONSOLIDATION) {\n                    candidates.emplace_back(dist(human_pos[i], tasks[j]), i, j);\n                } else {\n                    int min_build_site_dist = 1e9;\n                    for(int k=0; k<4; ++k) {\n                        Point site = {tasks[j].r+DR[k], tasks[j].c+DC[k]};\n                        if(is_valid(site.r, site.c) && is_safe[site.r][site.c])\n                             min_build_site_dist = min(min_build_site_dist, dist(human_pos[i], site));\n                    }\n                    if(min_build_site_dist != 1e9) candidates.emplace_back(min_build_site_dist, i, j);\n                }\n            }\n        }\n    }\n    sort(candidates.begin(), candidates.end());\n    vector<bool> task_assigned(tasks.size(), false); vector<bool> human_assigned(M, false);\n    for(const auto& cand : candidates){\n        int d, h_id, t_id; tie(d, h_id, t_id) = cand;\n        if(!human_assigned[h_id] && !task_assigned[t_id]){\n            human_task[h_id] = t_id; human_assigned[h_id] = true; task_assigned[t_id] = true;\n        }\n    }\n    \n    string actions_str(M, '.'); vector<Point> planned_walls;\n    for (int i=0; i<M; ++i) {\n        Point current_pos = human_pos[i];\n        if (!is_safe[current_pos.r][current_pos.c] && current_phase != CONSOLIDATION) {\n            Point closest_safe_spot = {-1,-1}; int min_dist_to_safe = 1e9;\n            for(int r=0; r<H; ++r) for(int c=0; c<W; ++c) if(is_safe[r][c]) {\n                int d = dist(current_pos, {r,c});\n                if(d < min_dist_to_safe) {min_dist_to_safe = d; closest_safe_spot = {r,c};}\n            }\n            if(closest_safe_spot.r != -1) {\n                vector<Point> path = find_path(current_pos, closest_safe_spot, planned_walls);\n                if (!path.empty()) {\n                    Point next_pos = path[0];\n                    for (int d=0; d<4; ++d) if (current_pos.r+DR[d]==next_pos.r && current_pos.c+DC[d]==next_pos.c) { actions_str[i] = MOVE_CH[d]; break; }\n                }\n            }\n            continue;\n        }\n\n        if (human_task[i] == -1) continue;\n        Point task_pos = tasks[human_task[i]];\n        \n        if (current_phase == CONSOLIDATION) {\n            vector<Point> path = find_path(current_pos, task_pos, planned_walls);\n            if (!path.empty()) {\n                Point next_pos = path[0];\n                for (int d=0; d<4; ++d) if (current_pos.r+DR[d]==next_pos.r && current_pos.c+DC[d]==next_pos.c) { actions_str[i] = MOVE_CH[d]; break;}\n            }\n        } else {\n            Point best_build_site = {-1,-1}; int min_dist = 1e9;\n            for (int d=0; d<4; ++d) {\n                Point site = {task_pos.r+DR[d], task_pos.c+DC[d]};\n                if (is_valid(site.r, site.c) && is_safe[site.r][site.c]) {\n                    if (dist(current_pos, site) < min_dist) { min_dist = dist(current_pos, site); best_build_site = site;}\n                }\n            }\n            if(best_build_site.r == -1) continue;\n            \n            if (current_pos == best_build_site) {\n                if (can_build[task_pos.r*W+task_pos.c]) {\n                    for (int d=0; d<4; ++d) if (current_pos.r+DR[d]==task_pos.r && current_pos.c+DC[d]==task_pos.c) {\n                        actions_str[i] = BUILD_CH[d]; planned_walls.push_back(task_pos); break;\n                    }\n                } else {\n                    double max_flee_score = -1e9; int best_dir = -1;\n                    for (int d=0; d<4; ++d) {\n                        Point next_p = {current_pos.r+DR[d], current_pos.c+DC[d]};\n                        if (is_valid(next_p.r, next_p.c) && !is_impassable[next_p.r][next_p.c] && is_safe[next_p.r][next_p.c]) {\n                            double min_dist_to_pet = 1e9;\n                            for(const auto& p : pet_pos) min_dist_to_pet = min(min_dist_to_pet, (double)dist(p, next_p));\n                            double score = min_dist_to_pet - danger_map[next_p.r * W + next_p.c];\n                            if (score > max_flee_score) { max_flee_score = score; best_dir = d; }\n                        }\n                    }\n                    if (best_dir != -1) actions_str[i] = MOVE_CH[best_dir];\n                }\n            } else {\n                vector<Point> path = find_path(current_pos, best_build_site, planned_walls);\n                if (!path.empty()) {\n                    Point next_pos = path[0];\n                    for (int d=0; d<4; ++d) if (current_pos.r+DR[d]==next_pos.r && current_pos.c+DC[d]==next_pos.c) { actions_str[i] = MOVE_CH[d]; break;}\n                }\n            }\n        }\n    }\n    return actions_str;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false); cin.tie(NULL);\n    cin >> N;\n    pet_pos.resize(N); pet_type.resize(N);\n    for (int i=0; i<N; ++i) { cin >> pet_pos[i].r >> pet_pos[i].c >> pet_type[i]; pet_pos[i].r--; pet_pos[i].c--; }\n    cin >> M;\n    human_pos.resize(M);\n    for (int i=0; i<M; ++i) { cin >> human_pos[i].r >> human_pos[i].c; human_pos[i].r--; human_pos[i].c--; }\n    fill(&is_impassable[0][0], &is_impassable[0][0]+H*W, false);\n\n    for (int t=0; t<300; ++t) {\n        current_turn = t;\n        string actions = solve();\n        cout << actions << endl;\n        \n        vector<Point> planned_walls;\n        for(int i=0; i<M; ++i) {\n            char act = actions[i]; Point p = human_pos[i];\n            if (act == 'u') planned_walls.push_back({p.r-1, p.c}); else if (act == 'd') planned_walls.push_back({p.r+1, p.c});\n            else if (act == 'l') planned_walls.push_back({p.r, p.c-1}); else if (act == 'r') planned_walls.push_back({p.r, p.c+1});\n        }\n        for(int i=0; i<M; ++i) {\n            char act = actions[i]; Point& p = human_pos[i]; Point next_p = p;\n            if (act == 'U') next_p.r--; else if (act == 'D') next_p.r++; else if (act == 'L') next_p.c--; else if (act == 'R') next_p.c++;\n            bool blocked = false; for(const auto& w : planned_walls) if(next_p == w) blocked = true;\n            if (act >= 'A' && act <= 'Z' && !blocked) p = next_p;\n            else if (act >= 'a' && act <= 'z') {\n                if (act == 'u') is_impassable[p.r-1][p.c] = true; else if (act == 'd') is_impassable[p.r+1][p.c] = true;\n                else if (act == 'l') is_impassable[p.r][p.c-1] = true; else if (act == 'r') is_impassable[p.r][p.c+1] = true;\n            }\n        }\n        for (int i=0; i<N; ++i) {\n            string move_str; cin >> move_str;\n            for (char move : move_str) {\n                if (move == 'U') pet_pos[i].r--; else if (move == 'D') pet_pos[i].r++;\n                else if (move == 'L') pet_pos[i].c--; else if (move == 'R') pet_pos[i].c++;\n            }\n        }\n    }\n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <array>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\n// Using long double for better precision\nusing ld = long double;\n\nconstexpr int N = 20;\nconstexpr int MAX_TURNS = 200;\nconstexpr int BEAM_WIDTH = 30; // Tunable parameter\n\nstruct State {\n    int r, c;\n    bool operator==(const State& other) const {\n        return r == other.r && c == other.c;\n    }\n};\n\nState start_pos, target_pos;\nld forget_prob;\narray<array<bool, N - 1>, N> h_walls;\narray<array<bool, N>, N - 1> v_walls;\narray<array<int, N>, N> dist_to_target;\n\nconst int DR[] = {-1, 1, 0, 0}; // U, D, L, R\nconst int DC[] = {0, 0, -1, 1};\nconst char DIRS[] = \"UDLR\";\nconst int DIRS_ORDER[] = {1, 3, 0, 2}; // D, R, U, L\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N;\n}\n\nState move_state(State s, int dir_idx) {\n    int nr = s.r + DR[dir_idx];\n    int nc = s.c + DC[dir_idx];\n\n    if (!is_valid(nr, nc)) {\n        return s;\n    }\n\n    if (DR[dir_idx] == -1 && v_walls[s.r - 1][s.c]) return s; // U\n    if (DR[dir_idx] == 1 && v_walls[s.r][s.c]) return s;    // D\n    if (DC[dir_idx] == -1 && h_walls[s.r][s.c - 1]) return s; // L\n    if (DC[dir_idx] == 1 && h_walls[s.r][s.c]) return s;    // R\n\n    return {nr, nc};\n}\n\nvoid bfs_from_target() {\n    for (auto& row : dist_to_target) row.fill(-1);\n    \n    queue<State> q;\n    q.push(target_pos);\n    dist_to_target[target_pos.r][target_pos.c] = 0;\n    \n    while (!q.empty()) {\n        State u = q.front();\n        q.pop();\n        \n        for (int i = 0; i < 4; ++i) {\n            State neighbor = {u.r + DR[i], u.c + DC[i]};\n            if (!is_valid(neighbor.r, neighbor.c)) continue;\n            \n            State moved = move_state(u, i);\n            if (moved == u) continue; // Wall between u and neighbor, cannot reach it\n            \n            if (dist_to_target[neighbor.r][neighbor.c] == -1) {\n                dist_to_target[neighbor.r][neighbor.c] = dist_to_target[u.r][u.c] + 1;\n                q.push(neighbor);\n            }\n        }\n    }\n}\n\nusing ProbDist = array<array<ld, N>, N>;\n\nstruct Candidate {\n    string moves;\n    ProbDist prob;\n    ld accumulated_score;\n    ld heuristic_score;\n\n    void calculate_heuristic_score(int turn) {\n        ld expected_dist = 0;\n        ld remaining_prob = 0;\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                if (prob[r][c] > 1e-25) { // Pruning small probabilities\n                    expected_dist += prob[r][c] * dist_to_target[r][c];\n                    remaining_prob += prob[r][c];\n                }\n            }\n        }\n\n        if (remaining_prob < 1e-18) {\n            heuristic_score = accumulated_score;\n            return;\n        }\n        \n        ld avg_dist = expected_dist / remaining_prob;\n        ld expected_turns_to_reach = avg_dist / (1.0L - forget_prob);\n        \n        ld future_score = remaining_prob * max((ld)0.0, 401.0L - (turn + expected_turns_to_reach));\n        heuristic_score = accumulated_score + future_score;\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> start_pos.r >> start_pos.c >> target_pos.r >> target_pos.c;\n    double p_double;\n    cin >> p_double;\n    forget_prob = p_double;\n\n    for (int i = 0; i < N; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < N - 1; ++j) {\n            h_walls[i][j] = (row[j] == '1');\n        }\n    }\n    for (int i = 0; i < N - 1; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < N; ++j) {\n            v_walls[i][j] = (row[j] == '1');\n        }\n    }\n\n    bfs_from_target();\n\n    vector<Candidate> beam;\n    {\n        Candidate initial_candidate;\n        initial_candidate.moves = \"\";\n        for(auto& row : initial_candidate.prob) row.fill(0.0L);\n        initial_candidate.prob[start_pos.r][start_pos.c] = 1.0L;\n        initial_candidate.accumulated_score = 0.0L;\n        initial_candidate.calculate_heuristic_score(1);\n        beam.push_back(initial_candidate);\n    }\n    \n    for (int t = 1; t <= MAX_TURNS; ++t) {\n        vector<Candidate> next_candidates;\n        next_candidates.reserve(beam.size() * 4);\n\n        for (const auto& cand : beam) {\n            ld total_prob_mass = 0;\n             for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    total_prob_mass += cand.prob[r][c];\n                }\n            }\n            if(total_prob_mass < 1e-18) {\n                next_candidates.push_back(cand);\n                continue;\n            }\n\n            for (int dir_idx : DIRS_ORDER) {\n                Candidate next_cand;\n                next_cand.moves = cand.moves + DIRS[dir_idx];\n                for(auto& row : next_cand.prob) row.fill(0.0L);\n                \n                ld prob_reaching_this_turn = 0.0L;\n\n                for (int r = 0; r < N; ++r) {\n                    for (int c = 0; c < N; ++c) {\n                        if (cand.prob[r][c] < 1e-25) continue; // Pruning\n                        \n                        // Forgotten move\n                        next_cand.prob[r][c] += cand.prob[r][c] * forget_prob;\n\n                        // Successful move\n                        State next_pos = move_state({r, c}, dir_idx);\n                        if (next_pos == target_pos) {\n                            prob_reaching_this_turn += cand.prob[r][c] * (1.0L - forget_prob);\n                        } else {\n                            next_cand.prob[next_pos.r][next_pos.c] += cand.prob[r][c] * (1.0L - forget_prob);\n                        }\n                    }\n                }\n                \n                next_cand.accumulated_score = cand.accumulated_score + prob_reaching_this_turn * (401 - t);\n                next_cand.calculate_heuristic_score(t + 1);\n                next_candidates.push_back(move(next_cand));\n            }\n        }\n\n        sort(next_candidates.begin(), next_candidates.end(), [](const Candidate& a, const Candidate& b) {\n            return a.heuristic_score > b.heuristic_score;\n        });\n\n        if (next_candidates.size() > BEAM_WIDTH) {\n            next_candidates.resize(BEAM_WIDTH);\n        }\n        beam = move(next_candidates);\n    }\n\n    Candidate best_candidate;\n    ld max_score = -1.0;\n    for (const auto& cand : beam) {\n        if (cand.accumulated_score > max_score) {\n            max_score = cand.accumulated_score;\n            best_candidate = cand;\n        }\n    }\n\n    cout << best_candidate.moves << endl;\n\n    return 0;\n}","ahc010":"#include <iostream>\n#include <vector>\n#include <string>\n#include <array>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <cmath>\n#include <tuple>\n\n// --- Utilities ---\n\nclass Timer {\n    std::chrono::time_point<std::chrono::high_resolution_clock> start_time;\npublic:\n    Timer() {\n        start_time = std::chrono::high_resolution_clock::now();\n    }\n    double get_elapsed_sec() {\n        auto now = std::chrono::high_resolution_clock::now();\n        return std::chrono::duration<double>(now - start_time).count();\n    }\n};\n\nstruct Rng {\n    std::mt19937 mt;\n    Rng() : mt(1337) {} // Fixed seed for deterministic runs\n    int get_int(int min, int max) {\n        std::uniform_int_distribution<int> dist(min, max);\n        return dist(mt);\n    }\n    double get_double(double min, double max) {\n        std::uniform_real_distribution<double> dist(min, max);\n        return dist(mt);\n    }\n};\n\n// --- Problem Constants & Globals ---\nconstexpr int N = 30;\nconstexpr int di[] = {0, -1, 0, 1}; // L, U, R, D\nconstexpr int dj[] = {-1, 0, 1, 0};\n\nconst int to[8][4] = {\n\t{1, 0, -1, -1}, {3, -1, -1, 0}, {-1, -1, 3, 2}, {-1, 2, 1, -1},\n\t{1, 0, 3, 2},   {3, 2, 1, 0},   {2, -1, 0, -1}, {-1, 3, -1, 1},\n};\n\nint t_rot[8][4];\nstd::array<std::array<int, N>, N> initial_tiles;\n\nvoid precompute_rotations() {\n    for (int i = 0; i < 8; ++i) {\n        t_rot[i][0] = i;\n    }\n    for (int r = 1; r < 4; ++r) {\n        for (int i = 0; i < 8; ++i) {\n            int prev_t = t_rot[i][r - 1];\n            int next_t;\n            if (0 <= prev_t && prev_t <= 3) {\n                if (prev_t == 0) next_t = 1; else if (prev_t == 1) next_t = 2;\n                else if (prev_t == 2) next_t = 3; else next_t = 0;\n            } else if (prev_t == 4) next_t = 5;\n            else if (prev_t == 5) next_t = 4;\n            else if (prev_t == 6) next_t = 7;\n            else next_t = 6;\n            t_rot[i][r] = next_t;\n        }\n    }\n}\n\n// --- Core Logic ---\n\nusing RotationsGrid = std::array<std::array<int, N>, N>;\n\nlong long calculate_score(const RotationsGrid& rotations) {\n    std::array<std::array<int, N>, N> tiles;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            tiles[i][j] = t_rot[initial_tiles[i][j]][rotations[i][j]];\n        }\n    }\n\n    bool visited_edge[N][N][4] = {};\n    std::vector<int> loop_lengths;\n\n    for (int si = 0; si < N; ++si) {\n        for (int sj = 0; sj < N; ++sj) {\n            for (int sd = 0; sd < 4; ++sd) {\n                if (visited_edge[si][sj][sd]) continue;\n\n                int ci = si, cj = sj, cd = sd;\n                int length = 0;\n                \n                std::vector<std::tuple<int, int, int>> path_history;\n                bool is_loop = false;\n\n                for(int k=0; k < N*N*4; ++k) {\n                    if (visited_edge[ci][cj][cd]) {\n                        break;\n                    }\n                    path_history.emplace_back(ci, cj, cd);\n                    \n                    int d_out = to[tiles[ci][cj]][cd];\n                    if (d_out == -1) break;\n\n                    int ni = ci + di[d_out];\n                    int nj = cj + dj[d_out];\n                    \n                    if (ni < 0 || ni >= N || nj < 0 || nj >= N) break;\n                    \n                    length++;\n                    ci = ni; cj = nj; cd = (d_out + 2) % 4;\n\n                    if (ci == si && cj == sj && cd == sd) {\n                        is_loop = true;\n                        break;\n                    }\n                }\n                \n                if (is_loop) {\n                    loop_lengths.push_back(length);\n                }\n                \n                for (const auto& [pi, pj, pd] : path_history) {\n                    visited_edge[pi][pj][pd] = true;\n                }\n            }\n        }\n    }\n\n    if (loop_lengths.size() < 2) return 0;\n    std::sort(loop_lengths.rbegin(), loop_lengths.rend());\n    return static_cast<long long>(loop_lengths[0]) * loop_lengths[1];\n}\n\nvoid solve() {\n    Timer timer;\n    Rng rng;\n    \n    for (int i = 0; i < N; ++i) {\n        std::string row;\n        std::cin >> row;\n        for (int j = 0; j < N; ++j) {\n            initial_tiles[i][j] = row[j] - '0';\n        }\n    }\n\n    precompute_rotations();\n\n    RotationsGrid current_rotations;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            current_rotations[i][j] = rng.get_int(0, 3);\n        }\n    }\n\n    RotationsGrid best_rotations = current_rotations;\n    long long current_score = calculate_score(current_rotations);\n    long long best_score = current_score;\n\n    double T_start = 5000;\n    double T_end = 10;\n    double time_limit = 1.95;\n\n    int iter_count = 0;\n    while (timer.get_elapsed_sec() < time_limit) {\n        iter_count++;\n        \n        double progress = timer.get_elapsed_sec() / time_limit;\n        double T = T_start * std::pow(T_end / T_start, progress);\n\n        int r = rng.get_int(0, N - 1);\n        int c = rng.get_int(0, N - 1);\n\n        int old_rot = current_rotations[r][c];\n        int new_rot;\n        do {\n            new_rot = rng.get_int(0, 3);\n        } while (new_rot == old_rot);\n\n        current_rotations[r][c] = new_rot;\n        long long new_score = calculate_score(current_rotations);\n        \n        double delta = static_cast<double>(new_score - current_score);\n        \n        if (delta >= 0 || rng.get_double(0.0, 1.0) < std::exp(delta / T)) {\n            current_score = new_score;\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_rotations = current_rotations;\n            }\n        } else {\n            current_rotations[r][c] = old_rot;\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            std::cout << best_rotations[i][j];\n        }\n    }\n    std::cout << std::endl;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc011":"#include <iostream>\n#include <vector>\n#include <string>\n#include <array>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <cmath>\n#include <map>\n#include <queue>\n#include <unordered_map>\n\n#include <atcoder/mincostflow>\n\nusing namespace std;\n\n// --- Timer ---\nusing namespace std::chrono;\nauto start_time = high_resolution_clock::now();\ndouble time_limit = 2.95;\n\nbool is_time_over() {\n    auto current_time = high_resolution_clock::now();\n    duration<double> elapsed = current_time - start_time;\n    return elapsed.count() > time_limit;\n}\n\n// --- Random Number Generator ---\nmt19937 rng(0);\n\n// --- Constants and Type Definitions ---\nconstexpr int MAX_N = 10;\nconstexpr int MAX_N2 = 100;\n\nint N, T;\narray<int, 4> dr = {-1, 1, 0, 0}; // U, D, L, R\narray<int, 4> dc = {0, 0, -1, 1};\nstring move_chars = \"UDLR\";\narray<int, 4> opposite_move = {1, 0, 3, 2};\n\n// Directions bits: 1:left, 2:up, 4:right, 8:down\n// L:1, U:2, R:4, D:8\narray<int, 4> dir_bit = {1, 2, 4, 8}; // L, U, R, D mapped from my dc, dr\narray<int, 4> move_dir_map = {2, 8, 1, 4}; // U,D,L,R -> up,down,left,right bits\narray<int, 4> required_bit = {8, 2, 4, 1}; // Tile at (r,c) needs bit for move U, D, L, R from (r,c)\n\nint char_to_hex(char c) {\n    if (c >= '0' && c <= '9') return c - '0';\n    return c - 'a' + 10;\n}\n\nstruct DSU {\n    vector<int> parent;\n    vector<int> sz;\n    int num_sets;\n    DSU(int n) {\n        parent.resize(n);\n        sz.resize(n);\n        num_sets = n;\n        for (int i = 0; i < n; i++) {\n            parent[i] = i;\n            sz[i] = 1;\n        }\n    }\n    int find(int i) {\n        if (parent[i] == i) return i;\n        return parent[i] = find(parent[i]);\n    }\n    void unite(int i, int j) {\n        int root_i = find(i);\n        int root_j = find(j);\n        if (root_i != root_j) {\n            if (sz[root_i] < sz[root_j]) swap(root_i, root_j);\n            parent[root_j] = root_i;\n            sz[root_i] += sz[root_j];\n            num_sets--;\n        }\n    }\n};\n\nstruct Board {\n    array<int, MAX_N2> grid;\n    int empty_pos = -1;\n\n    Board() = default;\n\n    void find_empty() {\n        for (int i = 0; i < N * N; ++i) {\n            if (grid[i] == 0) {\n                empty_pos = i;\n                return;\n            }\n        }\n    }\n};\n\nstruct AStarState {\n    array<uint8_t, MAX_N2> board_config; // tile_id at pos\n    uint8_t empty_pos;\n    uint16_t g;\n    uint16_t h;\n    AStarState* parent;\n    char move_char;\n\n    int f() const { return g + h; }\n\n    bool operator>(const AStarState& other) const {\n        if (f() != other.f()) {\n            return f() > other.f();\n        }\n        return h > other.h;\n    }\n};\n\n// Custom hash for A* state\nstruct AStarStateHasher {\n    size_t operator()(const AStarState* s) const {\n        size_t h = 0;\n        for (int i = 0; i < N * N; ++i) {\n            h ^= hash<uint8_t>()(s->board_config[i]) + 0x9e3779b9 + (h << 6) + (h >> 2);\n        }\n        return h;\n    }\n};\n\nstruct AStarStateComparator {\n    bool operator()(const AStarState* a, const AStarState* b) const {\n        return std::equal(a->board_config.begin(), a->board_config.begin() + N*N, b->board_config.begin());\n    }\n};\n\n\n// --- Global state ---\nBoard initial_board;\narray<int, 16> initial_tile_counts{};\nvector<pair<int, int>> initial_pos_by_type[16];\n\n// --- Phase 1: SA for Target Configuration ---\narray<int, MAX_N2> best_target_grid;\nlong long best_dist_score = -1;\n\nvoid evaluate_target(const array<int, MAX_N2>& target_grid, long long& connectivity_score, long long& dist_score) {\n    DSU dsu(N * N);\n    int edges = 0;\n    int max_comp_size = 0;\n    \n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int pos = r * N + c;\n            if (target_grid[pos] == 0) continue;\n\n            // Down\n            if (r + 1 < N) {\n                int next_pos = (r + 1) * N + c;\n                if (target_grid[next_pos] != 0) {\n                    if ((target_grid[pos] & 8) && (target_grid[next_pos] & 2)) {\n                        if (dsu.find(pos) == dsu.find(next_pos)) { // cycle\n                            connectivity_score -= 10000000;\n                        } else {\n                            dsu.unite(pos, next_pos);\n                            edges++;\n                        }\n                    }\n                }\n            }\n            // Right\n            if (c + 1 < N) {\n                int next_pos = r * N + c + 1;\n                if (target_grid[next_pos] != 0) {\n                    if ((target_grid[pos] & 4) && (target_grid[next_pos] & 1)) {\n                         if (dsu.find(pos) == dsu.find(next_pos)) { // cycle\n                            connectivity_score -= 10000000;\n                        } else {\n                            dsu.unite(pos, next_pos);\n                            edges++;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    int non_empty_cells = N * N - 1;\n    for(int i = 0; i < N * N; ++i) {\n        if(target_grid[i] != 0 && dsu.parent[i] == i) {\n            max_comp_size = max(max_comp_size, dsu.sz[i]);\n        }\n    }\n    \n    connectivity_score += (long long)max_comp_size * 100000;\n    if (max_comp_size == non_empty_cells && edges == non_empty_cells - 1) {\n        connectivity_score += 100000000;\n    }\n\n    // Distance score calculation\n    vector<int> target_pos_by_type[16];\n    for(int i=0; i<N*N; ++i) {\n        if(target_grid[i] != 0) {\n            target_pos_by_type[target_grid[i]].push_back(i);\n        }\n    }\n    \n    dist_score = 0;\n    for (int type = 1; type <= 15; ++type) {\n        if (initial_tile_counts[type] == 0) continue;\n        \n        vector<pair<int, int>> s_coords, d_coords;\n        for (auto p : initial_pos_by_type[type]) s_coords.push_back({p.first, p.second});\n        for (auto pos : target_pos_by_type[type]) d_coords.push_back({pos / N, pos % N});\n\n        sort(s_coords.begin(), s_coords.end());\n        sort(d_coords.begin(), d_coords.end());\n        \n        for (size_t i = 0; i < s_coords.size(); ++i) {\n            dist_score += abs(s_coords[i].first - d_coords[i].first) + abs(s_coords[i].second - d_coords[i].second);\n        }\n    }\n}\n\nvoid run_sa() {\n    array<int, MAX_N2> current_grid;\n    vector<int> tiles;\n    int empty_final_pos = N*N - 1;\n\n    for (int type = 1; type <= 15; ++type) {\n        for (int i = 0; i < initial_tile_counts[type]; ++i) {\n            tiles.push_back(type);\n        }\n    }\n    \n    shuffle(tiles.begin(), tiles.end(), rng);\n    \n    int tile_idx = 0;\n    for(int i=0; i<N*N; ++i) {\n        if (i == empty_final_pos) {\n            current_grid[i] = 0;\n        } else {\n            current_grid[i] = tiles[tile_idx++];\n        }\n    }\n\n    long long current_conn_score=0, current_dist_score=0;\n    evaluate_target(current_grid, current_conn_score, current_dist_score);\n    long long best_conn_score = -1e18;\n\n    double start_temp = 1000, end_temp = 0.1;\n    int iter_count = 0;\n\n    while (!is_time_over()) {\n        iter_count++;\n        double temp = start_temp * pow(end_temp / start_temp, (double)(duration_cast<milliseconds>(high_resolution_clock::now() - start_time).count()) / (time_limit * 1000.0));\n        \n        int p1 = rng() % (N * N);\n        int p2 = rng() % (N * N);\n        if (p1 == p2 || current_grid[p1] == 0 || current_grid[p2] == 0) continue;\n\n        swap(current_grid[p1], current_grid[p2]);\n\n        long long new_conn_score=0, new_dist_score=0;\n        evaluate_target(current_grid, new_conn_score, new_dist_score);\n\n        long long current_score = current_conn_score - current_dist_score;\n        long long new_score = new_conn_score - new_dist_score;\n\n        if (new_score > current_score || uniform_real_distribution<>(0.0, 1.0)(rng) < exp((new_score - current_score) / temp)) {\n            current_conn_score = new_conn_score;\n            current_dist_score = new_dist_score;\n            if (current_conn_score > best_conn_score) {\n                best_conn_score = current_conn_score;\n                best_dist_score = current_dist_score;\n                best_target_grid = current_grid;\n            } else if (current_conn_score == best_conn_score && current_dist_score < best_dist_score) {\n                best_dist_score = current_dist_score;\n                best_target_grid = current_grid;\n            }\n        } else {\n            swap(current_grid[p1], current_grid[p2]);\n        }\n    }\n}\n\n\n// --- Phase 2: A* Search ---\nstring solve_puzzle() {\n    array<int, MAX_N2> tile_id_at_pos;\n    array<int, MAX_N2> type_of_tile_id;\n    array<int, MAX_N2> pos_of_tile_id;\n\n    int current_id = 0;\n    for(int r=0; r<N; ++r) {\n        for(int c=0; c<N; ++c) {\n            int pos = r*N+c;\n            int type = initial_board.grid[pos];\n            if (type != 0) {\n                tile_id_at_pos[pos] = current_id;\n                type_of_tile_id[current_id] = type;\n                pos_of_tile_id[current_id] = pos;\n                current_id++;\n            } else {\n                tile_id_at_pos[pos] = -1; // empty\n            }\n        }\n    }\n\n    // Assignment using min-cost-flow\n    array<int, MAX_N2> dest_of_tile_id;\n    vector<int> target_pos_by_type[16];\n    for (int i = 0; i < N * N; ++i) {\n        if (best_target_grid[i] != 0) {\n            target_pos_by_type[best_target_grid[i]].push_back(i);\n        }\n    }\n\n    vector<pair<int, int>> initial_id_pos_by_type[16];\n    for (int id = 0; id < N * N - 1; ++id) {\n        initial_id_pos_by_type[type_of_tile_id[id]].push_back({id, pos_of_tile_id[id]});\n    }\n\n    for (int type = 1; type <= 15; ++type) {\n        int count = initial_tile_counts[type];\n        if (count == 0) continue;\n\n        atcoder::mcf_graph<int, int> graph(2 * count + 2);\n        int s = 2 * count, t = 2 * count + 1;\n\n        for (int i = 0; i < count; ++i) {\n            graph.add_edge(s, i, 1, 0);\n            graph.add_edge(i + count, t, 1, 0);\n            for (int j = 0; j < count; ++j) {\n                int start_pos = initial_id_pos_by_type[type][i].second;\n                int target_pos = target_pos_by_type[type][j];\n                int dist = abs(start_pos / N - target_pos / N) + abs(start_pos % N - target_pos % N);\n                graph.add_edge(i, j + count, 1, dist);\n            }\n        }\n        graph.flow(s, t, count);\n        for (auto edge : graph.edges()) {\n            if (edge.from < count && edge.to >= count && edge.to < 2*count && edge.flow > 0) {\n                int tile_id = initial_id_pos_by_type[type][edge.from].first;\n                int dest_pos = target_pos_by_type[type][edge.to - count];\n                dest_of_tile_id[tile_id] = dest_pos;\n            }\n        }\n    }\n    \n    // A* search\n    priority_queue<AStarState*, vector<AStarState*>, greater<AStarState>> pq;\n    unordered_map<AStarState*, int, AStarStateHasher, AStarStateComparator> dist;\n    vector<AStarState> state_pool;\n    state_pool.reserve(2000000);\n\n    auto make_state = [&](const array<uint8_t, MAX_N2>& board, uint8_t empty, uint16_t g, uint16_t h, AStarState* p, char move) -> AStarState* {\n        state_pool.emplace_back(AStarState{board, empty, g, h, p, move});\n        return &state_pool.back();\n    };\n\n    AStarState* initial_state = new AStarState();\n    initial_state->g = 0;\n    initial_state->parent = nullptr;\n    initial_state->empty_pos = initial_board.empty_pos;\n    uint16_t initial_h = 0;\n    for (int i = 0; i < N * N; ++i) {\n        int tile_id = tile_id_at_pos[i];\n        if (tile_id != -1) {\n            initial_state->board_config[i] = tile_id;\n            initial_h += abs(i / N - dest_of_tile_id[tile_id] / N) + abs(i % N - dest_of_tile_id[tile_id] % N);\n        }\n    }\n    initial_state->h = initial_h;\n    \n    pq.push(initial_state);\n    dist[initial_state] = 0;\n\n    AStarState* final_state = nullptr;\n\n    int states_explored = 0;\n    while (!pq.empty()) {\n        if (is_time_over() || states_explored > 300000) {\n             break;\n        }\n        states_explored++;\n\n        AStarState* current = pq.top();\n        pq.pop();\n\n        if (dist.count(current) && dist[current] < current->g) {\n            continue;\n        }\n\n        if (current->h == 0) {\n            final_state = current;\n            break;\n        }\n\n        int r = current->empty_pos / N;\n        int c = current->empty_pos % N;\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n\n            if(current->parent != nullptr) {\n                if (nr*N+nc == current->parent->empty_pos) continue;\n            }\n\n            int next_empty_pos = nr * N + nc;\n            \n            array<uint8_t, MAX_N2> next_board = current->board_config;\n            swap(next_board[current->empty_pos], next_board[next_empty_pos]);\n\n            int moved_tile_id = current->board_config[next_empty_pos];\n            int moved_tile_dest = dest_of_tile_id[moved_tile_id];\n\n            uint16_t next_h = current->h;\n            next_h -= (abs(next_empty_pos / N - moved_tile_dest / N) + abs(next_empty_pos % N - moved_tile_dest % N));\n            next_h += (abs(current->empty_pos / N - moved_tile_dest / N) + abs(current->empty_pos % N - moved_tile_dest % N));\n            \n            AStarState temp_state;\n            temp_state.board_config = next_board;\n            auto it = dist.find(&temp_state);\n\n            if (it == dist.end() || it->second > current->g + 1) {\n                AStarState* next_state = make_state(next_board, next_empty_pos, current->g + 1, next_h, current, move_chars[i]);\n                pq.push(next_state);\n                dist[next_state] = current->g + 1;\n            }\n        }\n    }\n\n    if (final_state) {\n        string path = \"\";\n        AStarState* curr = final_state;\n        while (curr->parent != nullptr) {\n            path += curr->move_char;\n            curr = curr->parent;\n        }\n        reverse(path.begin(), path.end());\n        return path;\n    }\n\n    return \"\";\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N >> T;\n    for (int i = 0; i < N; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < N; ++j) {\n            int type = char_to_hex(row[j]);\n            initial_board.grid[i * N + j] = type;\n            if (type != 0) {\n                initial_tile_counts[type]++;\n                initial_pos_by_type[type].push_back({i, j});\n            }\n        }\n    }\n    initial_board.find_empty();\n\n    time_limit = (N<=7) ? 2.95 : 2.95;\n\n    run_sa();\n    \n    long long final_conn_score=0, final_dist_score=0;\n    evaluate_target(best_target_grid, final_conn_score, final_dist_score);\n\n    if (final_conn_score < 100000000) {\n        cout << \"\" << endl; // Failed to find a tree, output empty\n        return 0;\n    }\n\n    string solution = solve_puzzle();\n    cout << solution << endl;\n\n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <map>\n#include <unordered_map>\n\n// --- Utilities ---\nstruct XorShift {\n    unsigned int x, y, z, w;\n\n    XorShift() {\n        std::random_device rd;\n        x = rd();\n        y = rd();\n        z = rd();\n        w = rd();\n    }\n\n    unsigned int next() {\n        unsigned int t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));\n    }\n\n    double next_double() {\n        return next() / 4294967295.0;\n    }\n\n    int next_int(int max_val) { // [0, max_val-1]\n        return next() % max_val;\n    }\n};\n\nXorShift rnd;\nauto start_time = std::chrono::high_resolution_clock::now();\ndouble TIME_LIMIT = 2.95;\n\ndouble get_time() {\n    auto now = std::chrono::high_resolution_clock::now();\n    return std::chrono::duration_cast<std::chrono::duration<double>>(now - start_time).count();\n}\n\n// --- Data Structures ---\nconst long long INF_COORD = 1000000000;\nconst double PI = acos(-1.0L);\n\nstruct Point {\n    long long x, y;\n};\n\nstruct Line {\n    long double a, b, c; // ax+by+c=0\n};\n\nstruct LinePolar {\n    double theta, rho; // rho = x*cos(theta) + y*sin(theta)\n};\n\n\n// --- Problem Data ---\nint N, K;\nstd::vector<int> target_a;\nstd::vector<Point> strawberries;\n\n// --- Geometry ---\nLine points_to_line(Point p1, Point p2) {\n    long double a = (long double)p1.y - p2.y;\n    long double b = (long double)p2.x - p1.x;\n    long double c = -a * p1.x - b * p1.y;\n    return {a, b, c};\n}\n\nLine perturb_line(Line l, double amount) {\n    l.c += amount;\n    return l;\n}\n\nint get_side(const Line& l, const Point& p) {\n    long double val = l.a * p.x + l.b * p.y + l.c;\n    if (std::abs(val) < 1e-9) return 0;\n    return val > 0 ? 1 : -1;\n}\n\nLine to_cartesian(LinePolar lp) {\n    return {std::cos((long double)lp.theta), std::sin((long double)lp.theta), (long double)-lp.rho};\n}\n\nLinePolar to_polar(Line l) {\n    if (std::abs(l.a) < 1e-12 && std::abs(l.b) < 1e-12) return {0,0};\n    long double norm = std::sqrt(l.a * l.a + l.b * l.b);\n    long double a_ = l.a / norm;\n    long double b_ = l.b / norm;\n    long double c_ = l.c / norm;\n    \n    double rho = -c_;\n    double theta = std::atan2((double)b_, (double)a_);\n\n    if (theta < 0) theta += 2*PI;\n    if (theta >= PI) {\n        theta -= PI;\n        rho = -rho;\n    }\n    return {(double)theta, (double)rho};\n}\n\n\nstruct VectorHasher {\n    std::size_t operator()(const std::vector<int>& v) const {\n        std::size_t seed = v.size();\n        for (int i : v) {\n            seed ^= (std::size_t)i + 0x9e3779b9 + (seed << 6) + (seed >> 2);\n        }\n        return seed;\n    }\n};\n\nint calculate_score_val(const std::vector<Line>& lines) {\n    if (lines.empty()) return 0;\n    \n    std::unordered_map<std::vector<int>, int, VectorHasher> piece_counts;\n    for (int i = 0; i < N; ++i) {\n        std::vector<int> signature;\n        signature.reserve(lines.size());\n        bool on_line = false;\n        for (const auto& line : lines) {\n            int side = get_side(line, strawberries[i]);\n            if (side == 0) {\n                on_line = true;\n                break;\n            }\n            signature.push_back(side);\n        }\n        if (!on_line) {\n            piece_counts[signature]++;\n        }\n    }\n\n    std::vector<int> b(11, 0);\n    for (const auto& pair : piece_counts) {\n        if (pair.second >= 1 && pair.second <= 10) {\n            b[pair.second]++;\n        }\n    }\n\n    int score = 0;\n    for (int d = 1; d <= 10; ++d) {\n        score += std::min(target_a[d], b[d]);\n    }\n    return score;\n}\n\nstd::vector<std::vector<int>> perform_clustering() {\n    std::vector<int> target_sizes;\n    for (int d = 1; d <= 10; ++d) {\n        for (int i = 0; i < target_a[d]; ++i) {\n            target_sizes.push_back(d);\n        }\n    }\n    std::shuffle(target_sizes.begin(), target_sizes.end(), std::mt19937(rnd.next()));\n\n    std::vector<std::vector<int>> clusters;\n    std::vector<bool> assigned(N, false);\n    int assigned_count = 0;\n\n    for (int d : target_sizes) {\n        if (assigned_count + d > N) continue;\n\n        int seed_idx = -1;\n        int start_node = rnd.next_int(N);\n        for(int i = 0; i < N; ++i) {\n            int current_node = (start_node + i) % N;\n            if (!assigned[current_node]) {\n                seed_idx = current_node;\n                break;\n            }\n        }\n        if (seed_idx == -1) break;\n\n        std::vector<std::pair<long long, int>> dists;\n        for (int i = 0; i < N; ++i) {\n            if (!assigned[i]) {\n                long long dx = strawberries[seed_idx].x - strawberries[i].x;\n                long long dy = strawberries[seed_idx].y - strawberries[i].y;\n                dists.push_back({dx * dx + dy * dy, i});\n            }\n        }\n        \n        if (dists.size() > d) {\n            std::nth_element(dists.begin(), dists.begin() + d, dists.end());\n        }\n\n        std::vector<int> new_cluster;\n        for (int i = 0; i < std::min((int)dists.size(), d); ++i) {\n            int strawberry_idx = dists[i].second;\n            new_cluster.push_back(strawberry_idx);\n            assigned[strawberry_idx] = true;\n        }\n        clusters.push_back(new_cluster);\n        assigned_count += d;\n    }\n    return clusters;\n}\n\nvoid output_solution(const std::vector<Line>& lines) {\n    std::cout << lines.size() << std::endl;\n    for (const auto& l : lines) {\n        long long p1x, p1y, p2x, p2y;\n        if (std::abs(l.b) > std::abs(l.a)) {\n            p1x = -INF_COORD;\n            p1y = std::round(- (l.c + l.a * p1x) / l.b);\n            p2x = INF_COORD;\n            p2y = std::round(- (l.c + l.a * p2x) / l.b);\n        } else {\n            p1y = -INF_COORD;\n            p1x = std::round(- (l.c + l.b * p1y) / l.a);\n            p2y = INF_COORD;\n            p2x = std::round(- (l.c + l.b * p2y) / l.a);\n        }\n        std::cout << p1x << \" \" << p1y << \" \" << p2x << \" \" << p2y << std::endl;\n    }\n}\n\nvoid solve() {\n    std::cin >> N >> K;\n    target_a.resize(11);\n    for (int d = 1; d <= 10; ++d) {\n        std::cin >> target_a[d];\n    }\n    strawberries.resize(N);\n    for (int i = 0; i < N; ++i) {\n        std::cin >> strawberries[i].x >> strawberries[i].y;\n    }\n    \n    auto clusters = perform_clustering();\n    if (clusters.empty()) {\n        std::cout << 0 << std::endl;\n        return;\n    }\n\n    std::vector<Line> current_lines;\n    const int T_SEARCH = 15;\n    for (int k = 0; k < K; ++k) {\n        if (get_time() > 1.2) break;\n        Line best_line = {};\n        int best_score = -1;\n        \n        for (int i = 0; i < T_SEARCH; ++i) {\n            Line candidate_line;\n            if (clusters.size() >= 2) {\n                int c1_idx = rnd.next_int(clusters.size());\n                int c2_idx = rnd.next_int(clusters.size());\n                if (c1_idx == c2_idx) { i--; continue; }\n                int s1_idx = clusters[c1_idx][rnd.next_int(clusters[c1_idx].size())];\n                int s2_idx = clusters[c2_idx][rnd.next_int(clusters[c2_idx].size())];\n                candidate_line = points_to_line(strawberries[s1_idx], strawberries[s2_idx]);\n                candidate_line = perturb_line(candidate_line, (rnd.next_double() * 2 - 1) * 0.1);\n            } else {\n                 Point p1 = { (long long)rnd.next_int(20001) - 10000, (long long)rnd.next_int(20001) - 10000 };\n                 Point p2 = { (long long)rnd.next_int(20001) - 10000, (long long)rnd.next_int(20001) - 10000 };\n                 if(p1.x == p2.x && p1.y == p2.y) p2.x++;\n                 candidate_line = points_to_line(p1,p2);\n            }\n            \n            current_lines.push_back(candidate_line);\n            int score = calculate_score_val(current_lines);\n            if (score > best_score) {\n                best_score = score;\n                best_line = candidate_line;\n            }\n            current_lines.pop_back();\n        }\n        if (best_score != -1) {\n            current_lines.push_back(best_line);\n        } else {\n             Point p1 = { (long long)rnd.next_int(20001) - 10000, (long long)rnd.next_int(20001) - 10000 };\n             Point p2 = { (long long)rnd.next_int(20001) - 10000, (long long)rnd.next_int(20001) - 10000 };\n             if(p1.x == p2.x && p1.y == p2.y) p2.x++;\n             current_lines.push_back(points_to_line(p1, p2));\n        }\n    }\n    \n    std::vector<LinePolar> polar_lines;\n    for(const auto& l : current_lines) {\n        polar_lines.push_back(to_polar(l));\n    }\n\n    int current_score = calculate_score_val(current_lines);\n    std::vector<Line> best_lines = current_lines;\n    int best_score = current_score;\n\n    double T_start = 2.0;\n    double T_end = 0.01;\n    double time_start_sa = get_time();\n    double time_end_sa = TIME_LIMIT;\n\n    while(true) {\n        double current_time = get_time();\n        if (current_time > time_end_sa) break;\n\n        double progress = (current_time - time_start_sa) / (time_end_sa - time_start_sa);\n        double T = T_start * std::pow(T_end / T_start, progress);\n\n        if (polar_lines.empty()) break;\n        int line_idx = rnd.next_int(polar_lines.size());\n        \n        LinePolar old_polar = polar_lines[line_idx];\n        LinePolar new_polar = old_polar;\n        double angle_range = PI * 0.1 * (T/T_start);\n        double rho_range = 10000 * 0.1 * (T/T_start);\n        \n        new_polar.theta += (rnd.next_double() * 2 - 1) * angle_range;\n        new_polar.rho += (rnd.next_double() * 2 - 1) * rho_range;\n\n        if (new_polar.theta < 0) new_polar.theta += 2*PI;\n        if (new_polar.theta >= PI) {\n            new_polar.theta -= PI;\n            new_polar.rho *= -1;\n        }\n        \n        std::vector<Line> new_lines = current_lines;\n        new_lines[line_idx] = to_cartesian(new_polar);\n        \n        int new_score = calculate_score_val(new_lines);\n\n        double delta = new_score - current_score;\n\n        if (delta > 0 || std::exp(delta / T) > rnd.next_double()) {\n            current_score = new_score;\n            current_lines = new_lines;\n            polar_lines[line_idx] = new_polar;\n            if (new_score > best_score) {\n                best_score = new_score;\n                best_lines = new_lines;\n            }\n        }\n    }\n\n    output_solution(best_lines);\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <tuple>\n#include <chrono>\n#include <map>\n#include <queue>\n#include <array>\n\nusing namespace std;\n\n// Timer\nauto start_time = chrono::steady_clock::now();\ndouble time_limit = 4.9;\n\nbool is_time_over() {\n    auto now = chrono::steady_clock::now();\n    double elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count() / 1000.0;\n    return elapsed > time_limit;\n}\n\nint N, M;\nlong long C;\n\nstruct Point {\n    int x, y;\n\n    bool operator==(const Point& other) const {\n        return x == other.x && y == other.y;\n    }\n    bool operator<(const Point& other) const {\n        if (x != other.x) return x < other.x;\n        return y < other.y;\n    }\n    Point operator+(const Point& other) const {\n        return {x + other.x, y + other.y};\n    }\n    Point operator-(const Point& other) const {\n        return {x - other.x, y - other.y};\n    }\n};\n\nlong long dot_product(const Point& a, const Point& b) {\n    return (long long)a.x * b.x + (long long)a.y * b.y;\n}\n\nlong long get_weight(const Point& p) {\n    long long dx = p.x - C;\n    long long dy = p.y - C;\n    return dx * dx + dy * dy + 1;\n}\n\nstruct Candidate {\n    long long weight;\n    Point p_new, p_adj1, p_corner, p_adj2;\n\n    bool operator>(const Candidate& other) const {\n        return weight < other.weight;\n    }\n};\n\nbool has_dot[62][62];\nvector<Point> dots;\nvector<tuple<Point, Point, Point, Point>> solution_moves;\npriority_queue<Candidate, vector<Candidate>, greater<Candidate>> pq;\n\nmap<int, vector<pair<int, int>>> H_segs, V_segs, D1_segs, D2_segs;\n\nbool is_in_bounds(const Point& p) {\n    return p.x >= 0 && p.x < N && p.y >= 0 && p.y < N;\n}\n\nbool check_perimeter_clean(const Point& p_new, const Point& p_adj1, const Point& p_corner, const Point& p_adj2) {\n    auto check_segment = [&](const Point& a, const Point& b) {\n        int dx = b.x - a.x;\n        int dy = b.y - a.y;\n        int common_divisor = std::gcd(abs(dx), abs(dy));\n        if (common_divisor <= 1) return true;\n        int step_x = dx / common_divisor;\n        int step_y = dy / common_divisor;\n        for (int i = 1; i < common_divisor; ++i) {\n            Point p = {a.x + i * step_x, a.y + i * step_y};\n            if (has_dot[p.x][p.y]) return false;\n        }\n        return true;\n    };\n    \n    if (!check_segment(p_corner, p_adj1)) return false;\n    if (!check_segment(p_adj1, p_new)) return false;\n    if (!check_segment(p_new, p_adj2)) return false;\n    if (!check_segment(p_adj2, p_corner)) return false;\n    return true;\n}\n\nbool check_segment_overlap(map<int, vector<pair<int, int>>>& seg_map, int line_idx, int c1, int c2) {\n    if (c1 == c2) return false;\n    int min_c = min(c1, c2);\n    int max_c = max(c1, c2);\n\n    if (seg_map.find(line_idx) == seg_map.end()) return false;\n\n    const auto& intervals = seg_map.at(line_idx);\n    auto it = lower_bound(intervals.begin(), intervals.end(), make_pair(min_c, 0));\n\n    if (it != intervals.begin()) {\n        if (max(min_c, prev(it)->first) < min(max_c, prev(it)->second)) return true;\n    }\n    if (it != intervals.end()) {\n        if (max(min_c, it->first) < min(max_c, it->second)) return true;\n    }\n    return false;\n}\n\nvoid add_segment(map<int, vector<pair<int, int>>>& seg_map, int line_idx, int c1, int c2) {\n    if (c1 == c2) return;\n    int min_c = min(c1, c2);\n    int max_c = max(c1, c2);\n    \n    auto& intervals = seg_map[line_idx];\n    intervals.emplace_back(min_c, max_c);\n    sort(intervals.begin(), intervals.end());\n}\n\nvoid find_and_push_candidates(const Point& p_a, const Point& p_b, const Point& p_c) {\n    Point p_new = p_a + p_c - p_b;\n    if (is_in_bounds(p_new) && !has_dot[p_new.x][p_new.y]) {\n        if (check_perimeter_clean(p_new, p_a, p_b, p_c)) {\n            pq.push({get_weight(p_new), p_new, p_a, p_b, p_c});\n        }\n    }\n}\n\nvoid find_new_candidates(const Point& p_added) {\n    for (size_t i = 0; i < dots.size(); ++i) {\n        for (size_t j = i + 1; j < dots.size(); ++j) {\n            const Point &p_i = dots[i], &p_j = dots[j];\n            if (p_added == p_i || p_added == p_j) continue;\n            \n            if (dot_product(p_i - p_added, p_j - p_added) == 0) find_and_push_candidates(p_i, p_added, p_j);\n            if (dot_product(p_added - p_i, p_j - p_i) == 0) find_and_push_candidates(p_added, p_i, p_j);\n            if (dot_product(p_added - p_j, p_i - p_j) == 0) find_and_push_candidates(p_added, p_j, p_i);\n        }\n    }\n}\n\nvoid find_initial_candidates() {\n    for (size_t i = 0; i < dots.size(); ++i) {\n        for (size_t j = i + 1; j < dots.size(); ++j) {\n            for (size_t k = j + 1; k < dots.size(); ++k) {\n                Point p_i = dots[i], p_j = dots[j], p_k = dots[k];\n                if (dot_product(p_j - p_i, p_k - p_i) == 0) find_and_push_candidates(p_j, p_i, p_k);\n                if (dot_product(p_i - p_j, p_k - p_j) == 0) find_and_push_candidates(p_i, p_j, p_k);\n                if (dot_product(p_i - p_k, p_j - p_k) == 0) find_and_push_candidates(p_i, p_k, p_j);\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N >> M;\n    C = (N - 1) / 2;\n\n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        dots.push_back({x, y});\n        has_dot[x][y] = true;\n    }\n\n    find_initial_candidates();\n\n    while (!pq.empty() && !is_time_over()) {\n        Candidate c = pq.top();\n        pq.pop();\n\n        if (has_dot[c.p_new.x][c.p_new.y]) continue;\n\n        Point p_new = c.p_new, p_corner = c.p_corner, p_adj1 = c.p_adj1, p_adj2 = c.p_adj2;\n        if (!check_perimeter_clean(p_new, p_adj1, p_corner, p_adj2)) continue;\n\n        auto check_s = [&](const Point& u, const Point& v) {\n            if (u.y == v.y) return !check_segment_overlap(H_segs, u.y, u.x, v.x);\n            if (u.x == v.x) return !check_segment_overlap(V_segs, u.x, u.y, v.y);\n            if (u.x + u.y == v.x + v.y) return !check_segment_overlap(D1_segs, u.x + u.y, u.x, v.x);\n            if (u.x - u.y == v.x - v.y) return !check_segment_overlap(D2_segs, u.x - u.y, u.x, v.x);\n            return true;\n        };\n\n        if (!check_s(p_corner, p_adj1)) continue;\n        if (!check_s(p_adj1, p_new)) continue;\n        if (!check_s(p_new, p_adj2)) continue;\n        if (!check_s(p_adj2, p_corner)) continue;\n        \n        auto add_s = [&](const Point& u, const Point& v){\n            if (u.y == v.y) add_segment(H_segs, u.y, u.x, v.x);\n            else if (u.x == v.x) add_segment(V_segs, u.x, u.y, v.y);\n            else if (u.x + u.y == v.x + v.y) add_segment(D1_segs, u.x + u.y, u.x, v.x);\n            else add_segment(D2_segs, u.x - u.y, u.x, v.x);\n        };\n\n        add_s(p_corner, p_adj1);\n        add_s(p_adj1, p_new);\n        add_s(p_new, p_adj2);\n        add_s(p_adj2, p_corner);\n\n        solution_moves.emplace_back(p_new, p_adj1, p_corner, p_adj2);\n        dots.push_back(p_new);\n        has_dot[p_new.x][p_new.y] = true;\n        \n        find_new_candidates(p_new);\n    }\n\n    cout << solution_moves.size() << endl;\n    for (const auto& move : solution_moves) {\n        cout << get<0>(move).x << \" \" << get<0>(move).y << \" \"\n             << get<1>(move).x << \" \" << get<1>(move).y << \" \"\n             << get<2>(move).x << \" \" << get<2>(move).y << \" \"\n             << get<3>(move).x << \" \" << get<3>(move).y << endl;\n    }\n\n    return 0;\n}","ahc015":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <algorithm>\n#include <map>\n#include <cmath>\n\nconst int GRID_SIZE = 10;\n\n// Represents the state of the 10x10 grid.\nstruct Grid {\n    std::vector<std::vector<int>> board;\n\n    Grid() : board(GRID_SIZE, std::vector<int>(GRID_SIZE, 0)) {}\n\n    // Places a candy of a given flavor at the p-th empty cell (1-indexed).\n    void place(int p, int flavor) {\n        int empty_count = 0;\n        for (int i = 0; i < GRID_SIZE; ++i) {\n            for (int j = 0; j < GRID_SIZE; ++j) {\n                if (board[i][j] == 0) {\n                    empty_count++;\n                    if (empty_count == p) {\n                        board[i][j] = flavor;\n                        return;\n                    }\n                }\n            }\n        }\n    }\n};\n\n// Simulates a tilt operation on the grid and returns the new grid state.\nGrid simulate_tilt(const Grid& current_grid, char dir) {\n    Grid next_grid; // Initializes to an empty board.\n    \n    if (dir == 'F') { // Move Up\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            int current_row = 0;\n            for (int i = 0; i < GRID_SIZE; ++i) {\n                if (current_grid.board[i][j] != 0) {\n                    next_grid.board[current_row++][j] = current_grid.board[i][j];\n                }\n            }\n        }\n    } else if (dir == 'B') { // Move Down\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            int current_row = GRID_SIZE - 1;\n            for (int i = GRID_SIZE - 1; i >= 0; --i) {\n                if (current_grid.board[i][j] != 0) {\n                    next_grid.board[current_row--][j] = current_grid.board[i][j];\n                }\n            }\n        }\n    } else if (dir == 'L') { // Move Left\n        for (int i = 0; i < GRID_SIZE; ++i) {\n            int current_col = 0;\n            for (int j = 0; j < GRID_SIZE; ++j) {\n                if (current_grid.board[i][j] != 0) {\n                    next_grid.board[i][current_col++] = current_grid.board[i][j];\n                }\n            }\n        }\n    } else if (dir == 'R') { // Move Right\n        for (int i = 0; i < GRID_SIZE; ++i) {\n            int current_col = GRID_SIZE - 1;\n            for (int j = GRID_SIZE - 1; j >= 0; --j) {\n                if (current_grid.board[i][j] != 0) {\n                    next_grid.board[i][current_col--] = current_grid.board[i][j];\n                }\n            }\n        }\n    }\n    return next_grid;\n}\n\n// Calculates the sum of squares of connected component sizes using BFS.\nlong long calculate_conn_score(const Grid& grid) {\n    long long total_score = 0;\n    std::vector<std::vector<bool>> visited(GRID_SIZE, std::vector<bool>(GRID_SIZE, false));\n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            if (grid.board[i][j] != 0 && !visited[i][j]) {\n                int flavor = grid.board[i][j];\n                long long component_size = 0;\n                std::vector<std::pair<int, int>> q;\n                q.push_back({i, j});\n                visited[i][j] = true;\n                \n                int head = 0;\n                while(head < q.size()){\n                    auto [r, c] = q[head++];\n                    component_size++;\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 < GRID_SIZE && nc >= 0 && nc < GRID_SIZE &&\n                            !visited[nr][nc] && grid.board[nr][nc] == flavor) {\n                            visited[nr][nc] = true;\n                            q.push_back({nr, nc});\n                        }\n                    }\n                }\n                total_score += component_size * component_size;\n            }\n        }\n    }\n    return total_score;\n}\n\n// Global map from flavor to its target corner.\nstd::map<int, std::pair<int, int>> target_map;\n\n// Calculates the proximity score (negative sum of Manhattan distances to targets).\nlong long calculate_prox_score(const Grid& grid) {\n    long long total_dist = 0;\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            if (grid.board[i][j] != 0) {\n                int flavor = grid.board[i][j];\n                auto target = target_map.at(flavor);\n                total_dist += std::abs(i - target.first) + std::abs(j - target.second);\n            }\n        }\n    }\n    return -total_dist;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    std::vector<int> f(100);\n    std::map<int, int> flavor_counts;\n    for (int i = 0; i < 100; ++i) {\n        std::cin >> f[i];\n        flavor_counts[f[i]]++;\n    }\n    \n    std::vector<std::pair<int, int>> sorted_flavors;\n    for (int i = 1; i <= 3; ++i) {\n        sorted_flavors.push_back({flavor_counts.count(i) ? flavor_counts[i] : 0, i});\n    }\n    std::sort(sorted_flavors.rbegin(), sorted_flavors.rend());\n\n    // Assign targets to corners based on flavor frequency.\n    std::vector<std::pair<int, int>> targets = {{0, 0}, {0, GRID_SIZE - 1}, {GRID_SIZE - 1, 0}};\n    for (size_t i = 0; i < 3; ++i) {\n        target_map[sorted_flavors[i].second] = targets[i];\n    }\n\n    Grid current_grid;\n\n    for (int t = 1; t <= 100; ++t) {\n        int p;\n        std::cin >> p;\n        current_grid.place(p, f[t - 1]);\n\n        if (t == 100) {\n            // The last tilt doesn't affect the final state's score.\n            break;\n        }\n\n        char best_dir = 'F';\n        double best_score = -1e18;\n\n        const char dirs[] = {'F', 'B', 'L', 'R'};\n        for (char dir : dirs) {\n            Grid next_grid = simulate_tilt(current_grid, dir);\n            \n            long long conn_score = calculate_conn_score(next_grid);\n            long long prox_score = calculate_prox_score(next_grid);\n\n            // Time-dependent weights for the evaluation function.\n            double w_conn = static_cast<double>(t) * t;\n            double w_prox = static_cast<double>(101 - t) * (101 - t);\n            \n            double current_total_score = w_conn * conn_score + w_prox * prox_score;\n            \n            if (current_total_score > best_score) {\n                best_score = current_total_score;\n                best_dir = dir;\n            }\n        }\n        \n        std::cout << best_dir << std::endl;\n        current_grid = simulate_tilt(current_grid, best_dir);\n    }\n\n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <set>\n#include <chrono>\n\n// --- Globals ---\nint M;\ndouble EPS;\nint N;\nstd::vector<int> clique_sizes;\n\n// --- Graph representation and utilities ---\nstruct Graph {\n    int n_vertices;\n    std::vector<std::vector<int>> adj;\n    int n_edges;\n\n    Graph(int n) : n_vertices(n), adj(n), n_edges(0) {}\n\n    void add_edge(int u, int v) {\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n        n_edges++;\n    }\n\n    static Graph from_string(int n, const std::string& s) {\n        Graph g(n);\n        int k = 0;\n        for (int i = 0; i < n; ++i) {\n            for (int j = i + 1; j < n; ++j) {\n                if (s[k] == '1') {\n                    g.add_edge(i, j);\n                }\n                k++;\n            }\n        }\n        return g;\n    }\n};\n\n// --- Problem Logic ---\n\ndouble binary_entropy(double p) {\n    if (p <= 0.0 || p >= 1.0) {\n        return 0.0;\n    }\n    return -p * std::log2(p) - (1.0 - p) * std::log2(1.0 - p);\n}\n\nvoid determine_N() {\n    double alpha = 1.5 + 5.0 * EPS;\n    double capacity = std::max(0.01, 1.0 - binary_entropy(EPS));\n    double bits_needed = std::log2(M) * alpha;\n    double edges_needed = bits_needed / capacity;\n    double n_theory = (1.0 + std::sqrt(std::max(0.0, 1.0 + 8.0 * edges_needed))) / 2.0;\n    \n    N = static_cast<int>(std::ceil(n_theory));\n    // To have M distinct graphs of the chosen structure (cliques of size 0, 2, ..., M),\n    // we need N to be at least M.\n    N = std::max(N, M);\n    \n    N = std::min(100, std::max(4, N));\n}\n\n\nvoid generate_base_graphs() {\n    clique_sizes.resize(M);\n    if (M > 0) {\n        clique_sizes[0] = 0; // Empty graph\n    }\n    for (int i = 1; i < M; ++i) {\n        clique_sizes[i] = i + 1; // Cliques of size 2, 3, ..., M\n    }\n    \n    std::cout << N << std::endl;\n    for (int k = 0; k < M; ++k) {\n        int C = clique_sizes[k];\n        std::string s = \"\";\n        s.reserve(N * (N - 1) / 2);\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) {\n                if (i < C && j < C) {\n                    s += '1';\n                } else {\n                    s += '0';\n                }\n            }\n        }\n        std::cout << s << std::endl;\n    }\n}\n\n\nvoid solve() {\n    // Phase 1: Determine N and generate graphs\n    determine_N();\n    generate_base_graphs();\n    std::cout.flush();\n\n    // Precompute theoretical properties of base graphs\n    std::vector<long long> clique_edge_counts(N + 1);\n    for (int i = 0; i <= N; ++i) {\n        clique_edge_counts[i] = (long long)i * (i - 1) / 2;\n    }\n\n    // Phase 2: Process queries\n    for (int q = 0; q < 100; ++q) {\n        std::string H_str;\n        std::cin >> H_str;\n\n        Graph H = Graph::from_string(N, H_str);\n\n        // Heuristic for finding densest k-subgraph for all k using degeneracy order.\n        std::vector<int> degree(N);\n        for(int i = 0; i < N; ++i) degree[i] = H.adj[i].size();\n\n        std::vector<std::vector<int>> buckets(N);\n        for(int i = 0; i < N; ++i) buckets[degree[i]].push_back(i);\n\n        std::vector<int> pos(N);\n        for(int d = 0; d < N; ++d) {\n            for(size_t i = 0; i < buckets[d].size(); ++i) {\n                pos[buckets[d][i]] = i;\n            }\n        }\n\n        long long current_edges = H.n_edges;\n        std::vector<long long> edges_in_subgraph(N + 1, 0);\n        std::vector<bool> removed(N, false);\n        \n        int min_deg = 0;\n        for (int k = N; k > 0; --k) {\n            edges_in_subgraph[k] = current_edges;\n            \n            while(min_deg < N && buckets[min_deg].empty()) {\n                min_deg++;\n            }\n            if (min_deg == N) break;\n\n            int v = buckets[min_deg].back();\n            buckets[min_deg].pop_back();\n            removed[v] = true;\n\n            current_edges -= degree[v];\n\n            for (int u : H.adj[v]) {\n                if (!removed[u]) {\n                    int d_u = degree[u];\n                    int pos_u = pos[u];\n                    int last_v_in_bucket = buckets[d_u].back();\n                    \n                    buckets[d_u][pos_u] = last_v_in_bucket;\n                    pos[last_v_in_bucket] = pos_u;\n                    buckets[d_u].pop_back();\n\n                    degree[u]--;\n                    buckets[d_u-1].push_back(u);\n                    pos[u] = buckets[d_u-1].size() - 1;\n                }\n            }\n        }\n        \n        int best_idx = -1;\n        double min_flips = 1e18;\n\n        for (int i = 0; i < M; ++i) {\n            int C = clique_sizes[i];\n            if (C > N) continue;\n            \n            long long E_star = edges_in_subgraph[C];\n            long long E_clique = clique_edge_counts[C];\n\n            // Estimated flips = (edges missing from clique) + (edges outside clique)\n            double estimated_flips = (double)(E_clique - E_star) + (H.n_edges - E_star);\n\n            if (estimated_flips < min_flips) {\n                min_flips = estimated_flips;\n                best_idx = i;\n            }\n        }\n        \n        std::cout << best_idx << std::endl;\n        std::cout.flush();\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    std::cin >> M >> EPS;\n    solve();\n\n    return 0;\n}","ahc017":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <iomanip>\n#include <functional>\n#include <queue>\n\nusing namespace std;\n\nconst long long INF = 1e12;\n\nstruct Edge {\n    int id;\n    int u, v, w;\n};\n\nstruct Point {\n    int x, y;\n};\n\nauto start_time = chrono::high_resolution_clock::now();\n\ndouble get_time() {\n    auto now = chrono::high_resolution_clock::now();\n    return chrono::duration_cast<chrono::duration<double>>(now - start_time).count();\n}\n\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\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    vector<vector<int>> edge_indices_adj(N);\n    for (int i = 0; i < M; ++i) {\n        edges[i].id = i;\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\n        edges[i].u--; \n        edges[i].v--;\n        adj[edges[i].u].push_back({edges[i].v, edges[i].w});\n        adj[edges[i].v].push_back({edges[i].u, edges[i].w});\n        edge_indices_adj[edges[i].u].push_back(i);\n        edge_indices_adj[edges[i].v].push_back(i);\n    }\n\n    vector<Point> coords(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> coords[i].x >> coords[i].y;\n    }\n    \n    vector<long long> edge_path_counts(M, 0);\n    int SAMPLES = 100;\n    if (N > 800) SAMPLES = 60;\n    vector<int> sample_nodes(N);\n    iota(sample_nodes.begin(), sample_nodes.end(), 0);\n    shuffle(sample_nodes.begin(), sample_nodes.end(), rng);\n\n    for (int i = 0; i < SAMPLES; ++i) {\n        int start_node = sample_nodes[i];\n        \n        vector<long long> dist(N, INF);\n        vector<int> parent_edge(N, -1);\n        dist[start_node] = 0;\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n        pq.push({0, start_node});\n\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n\n            if (d > dist[u]) continue;\n\n            for (auto& edge_idx : edge_indices_adj[u]) {\n                int v = (edges[edge_idx].u == u) ? edges[edge_idx].v : edges[edge_idx].u;\n                int w = edges[edge_idx].w;\n                if (dist[u] + w < dist[v]) {\n                    dist[v] = dist[u] + w;\n                    parent_edge[v] = edge_idx;\n                    pq.push({dist[v], v});\n                }\n            }\n        }\n\n        vector<vector<int>> tree_adj(N);\n        for(int j=0; j<N; ++j) {\n            if (parent_edge[j] != -1) {\n                int u = (edges[parent_edge[j]].u == j) ? edges[parent_edge[j]].v : edges[parent_edge[j]].u;\n                tree_adj[u].push_back(j);\n            }\n        }\n        \n        vector<int> subtree_size(N, 0);\n        function<void(int)> dfs_size = [&](int u) {\n            subtree_size[u] = 1;\n            for(int v : tree_adj[u]) {\n                dfs_size(v);\n                subtree_size[u] += subtree_size[v];\n            }\n        };\n        dfs_size(start_node);\n        \n        for(int j=0; j<N; ++j) {\n            if(parent_edge[j] != -1) {\n                edge_path_counts[parent_edge[j]] += (long long)subtree_size[j] * (N - subtree_size[j]);\n            }\n        }\n    }\n    \n    vector<double> edge_importance(M);\n    for (int i = 0; i < M; ++i) {\n        edge_importance[i] = (double)edge_path_counts[i] * edges[i].w;\n    }\n\n    vector<vector<float>> interactions(M, vector<float>(M));\n    vector<pair<double, double>> midpoints(M);\n    for(int i=0; i<M; ++i) {\n        midpoints[i] = {\n            (coords[edges[i].u].x + coords[edges[i].v].x) / 2.0,\n            (coords[edges[i].u].y + coords[edges[i].v].y) / 2.0\n        };\n    }\n\n    for(int i=0; i<M; ++i) {\n        for(int j=i+1; j<M; ++j) {\n            double dx = midpoints[i].first - midpoints[j].first;\n            double dy = midpoints[i].second - midpoints[j].second;\n            double dist_sq = dx*dx + dy*dy;\n            float val = 1.0f / (dist_sq + 1.0f);\n            if (edges[i].u == edges[j].u || edges[i].u == edges[j].v ||\n                edges[i].v == edges[j].u || edges[i].v == edges[j].v) {\n                val *= 2.0f;\n            }\n            interactions[i][j] = interactions[j][i] = val;\n        }\n    }\n\n    vector<int> sorted_edges(M);\n    iota(sorted_edges.begin(), sorted_edges.end(), 0);\n    sort(sorted_edges.begin(), sorted_edges.end(), [&](int a, int b){\n        return edge_importance[a] > edge_importance[b];\n    });\n\n    vector<vector<int>> days(D);\n    vector<int> edge_to_day(M);\n    \n    for (int edge_idx : sorted_edges) {\n        int best_day = -1;\n        float min_cost_increase = 1e18;\n\n        for (int d = 0; d < D; ++d) {\n            if (days[d].size() >= K) continue;\n            \n            float cost_increase = 0;\n            for (int other_edge_idx : days[d]) {\n                cost_increase += interactions[edge_idx][other_edge_idx];\n            }\n\n            if (cost_increase < min_cost_increase) {\n                min_cost_increase = cost_increase;\n                best_day = d;\n            } else if (abs(cost_increase - min_cost_increase) < 1e-9) { // Tie-breaking\n                if (best_day == -1 || days[d].size() < days[best_day].size()) {\n                    best_day = d;\n                }\n            }\n        }\n        days[best_day].push_back(edge_idx);\n        edge_to_day[edge_idx] = best_day;\n    }\n\n    double T0 = 20, T = T0;\n    long long iter_count = 0;\n    \n    double time_limit = 5.8;\n\n    while (true) {\n        iter_count++;\n        if ((iter_count & 255) == 0) {\n            double elapsed = get_time();\n            if (elapsed > time_limit) break;\n            double progress = elapsed / time_limit;\n            T = T0 * (1.0 - progress);\n        }\n\n        int move_type = uniform_int_distribution<>(0, 1)(rng);\n        \n        if (move_type == 0 && M > 0) { // Single edge move\n            int e_idx = uniform_int_distribution<>(0, M - 1)(rng);\n            int d1 = edge_to_day[e_idx];\n            int d2 = uniform_int_distribution<>(0, D - 1)(rng);\n\n            if (d1 == d2 || days[d2].size() >= K) continue;\n            \n            float cost_d1_old = 0;\n            for(int other_e : days[d1]) if(other_e != e_idx) cost_d1_old += interactions[e_idx][other_e];\n            \n            float cost_d2_new = 0;\n            for(int other_e : days[d2]) cost_d2_new += interactions[e_idx][other_e];\n            \n            double delta = cost_d2_new - cost_d1_old;\n\n            if (delta < 0 || (T > 1e-9 && uniform_real_distribution<>(0.0, 1.0)(rng) < exp(-delta / T))) {\n                auto& d1_edges = days[d1];\n                d1_edges.erase(remove(d1_edges.begin(), d1_edges.end(), e_idx), d1_edges.end());\n                days[d2].push_back(e_idx);\n                edge_to_day[e_idx] = d2;\n            }\n        } else if (M > 1) { // Swap move\n            int e1_idx = uniform_int_distribution<>(0, M - 1)(rng);\n            int d1 = edge_to_day[e1_idx];\n            \n            int d2;\n            do {\n                d2 = uniform_int_distribution<>(0, D - 1)(rng);\n            } while (d1 == d2 || days[d2].empty());\n            \n            int e2_idx = days[d2][uniform_int_distribution<>(0, (int)days[d2].size() - 1)(rng)];\n\n            float cost1_in_d1 = 0, cost2_in_d2 = 0, cost1_in_d2 = 0, cost2_in_d1 = 0;\n\n            for(int e_other : days[d1]) {\n                if (e_other == e1_idx) continue;\n                cost1_in_d1 += interactions[e1_idx][e_other];\n                cost2_in_d1 += interactions[e2_idx][e_other];\n            }\n            for(int e_other : days[d2]) {\n                if (e_other == e2_idx) continue;\n                cost2_in_d2 += interactions[e2_idx][e_other];\n                cost1_in_d2 += interactions[e1_idx][e_other];\n            }\n            \n            double delta = (cost2_in_d1 + cost1_in_d2) - (cost1_in_d1 + cost2_in_d2);\n\n            if (delta < 0 || (T > 1e-9 && uniform_real_distribution<>(0.0, 1.0)(rng) < exp(-delta / T))) {\n                auto& d1_edges = days[d1];\n                auto& d2_edges = days[d2];\n                \n                d1_edges.erase(remove(d1_edges.begin(), d1_edges.end(), e1_idx), d1_edges.end());\n                d2_edges.erase(remove(d2_edges.begin(), d2_edges.end(), e2_idx), d2_edges.end());\n                \n                d1_edges.push_back(e2_idx);\n                d2_edges.push_back(e1_idx);\n                \n                edge_to_day[e1_idx] = d2;\n                edge_to_day[e2_idx] = d1;\n            }\n        }\n    }\n\n    vector<int> result(M);\n    for (int i = 0; i < M; ++i) {\n        result[edges[i].id] = edge_to_day[i] + 1;\n    }\n\n    for (int i = 0; i < M; ++i) {\n        cout << result[i] << (i == M - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n\n    return 0;\n}","ahc019":"#include <iostream>\n#include <vector>\n#include <string>\n#include <tuple>\n#include <numeric>\n#include <algorithm>\n#include <set>\n#include <map>\n#include <chrono>\n\nusing namespace std;\n\nint D;\n\nstruct Point3D {\n    int x, y, z;\n    bool operator<(const Point3D& other) const {\n        if (x != other.x) return x < other.x;\n        if (y != other.y) return y < other.y;\n        return z < other.z;\n    }\n    bool operator==(const Point3D& other) const {\n        return x == other.x && y == other.y && z == other.z;\n    }\n};\n\nPoint3D operator+(const Point3D& a, const Point3D& b) {\n    return {a.x + b.x, a.y + b.y, a.z + b.z};\n}\n\nPoint3D operator-(const Point3D& a, const Point3D& b) {\n    return {a.x - b.x, a.y - b.y, a.z - b.z};\n}\n\nusing Shape = vector<Point3D>;\n\n// All 24 rotations of a cube\nconst vector<vector<int>> ROTS = {\n    {1,0,0,0,1,0,0,0,1}, {1,0,0,0,0,-1,0,1,0}, {1,0,0,0,-1,0,0,0,-1}, {1,0,0,0,0,1,0,-1,0},\n    {-1,0,0,0,-1,0,0,0,1}, {-1,0,0,0,0,1,0,1,0}, {-1,0,0,0,1,0,0,0,-1}, {-1,0,0,0,0,-1,0,-1,0},\n    {0,1,0,1,0,0,0,0,-1}, {0,1,0,0,0,1,1,0,0}, {0,1,0,-1,0,0,0,0,1}, {0,1,0,0,0,-1,-1,0,0},\n    {0,-1,0,-1,0,0,0,0,-1}, {0,-1,0,0,0,-1,1,0,0}, {0,-1,0,1,0,0,0,0,1}, {0,-1,0,0,0,1,-1,0,0},\n    {0,0,1,0,1,0,-1,0,0}, {0,0,1,1,0,0,0,1,0}, {0,0,1,0,-1,0,1,0,0}, {0,0,1,-1,0,0,0,-1,0},\n    {0,0,-1,0,-1,0,-1,0,0}, {0,0,-1,-1,0,0,0,1,0}, {0,0,-1,0,1,0,1,0,0}, {0,0,-1,1,0,0,0,-1,0}\n};\n\nPoint3D rotate(const Point3D& p, const vector<int>& R) {\n    return {\n        R[0]*p.x + R[1]*p.y + R[2]*p.z,\n        R[3]*p.x + R[4]*p.y + R[5]*p.z,\n        R[6]*p.x + R[7]*p.y + R[8]*p.z\n    };\n}\n\nShape normalize_shape(Shape s) {\n    if (s.empty()) return {};\n    Point3D min_p = s[0];\n    for (size_t i = 1; i < s.size(); ++i) {\n        min_p.x = min(min_p.x, s[i].x);\n        min_p.y = min(min_p.y, s[i].y);\n        min_p.z = min(min_p.z, s[i].z);\n    }\n    for (auto& p : s) {\n        p = p - min_p;\n    }\n    sort(s.begin(), s.end());\n    return s;\n}\n\nShape get_canonical_shape(const Shape& s) {\n    if (s.empty()) return {};\n    Shape canonical = normalize_shape(s);\n    for (const auto& R : ROTS) {\n        Shape rotated_s;\n        for (const auto& p : s) {\n            rotated_s.push_back(rotate(p, R));\n        }\n        Shape normalized_rotated = normalize_shape(rotated_s);\n        if (normalized_rotated < canonical) {\n            canonical = normalized_rotated;\n        }\n    }\n    return canonical;\n}\n\nstruct ProtoBlock {\n    Shape points;\n    int id = 0;\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\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    auto is_valid_coord = [&](int x, int y, int z) {\n        return x >= 0 && x < D && y >= 0 && y < D && z >= 0 && z < D;\n    };\n\n    vector<vector<vector<bool>>> C1(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    vector<vector<vector<bool>>> C2(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    vector<vector<vector<bool>>> C_common(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    \n    for (int x = 0; x < D; ++x) for (int y = 0; y < D; ++y) for (int z = 0; z < D; ++z) {\n        if (f1[z][x] == '1' && r1[z][y] == '1') C1[x][y][z] = true;\n        if (f2[z][x] == '1' && r2[z][y] == '1') C2[x][y][z] = true;\n        if (C1[x][y][z] && C2[x][y][z]) C_common[x][y][z] = true;\n    }\n\n    vector<ProtoBlock> common_blocks;\n    vector<vector<vector<bool>>> visited_common = C_common;\n    for (int x = 0; x < D; ++x) for (int y = 0; y < D; ++y) for (int z = 0; z < D; ++z) {\n        if (visited_common[x][y][z]) {\n            Shape current_block_points;\n            vector<Point3D> q;\n            q.push_back({x, y, z});\n            visited_common[x][y][z] = false;\n            size_t head = 0;\n            while(head < q.size()){\n                Point3D curr = q[head++];\n                current_block_points.push_back(curr);\n                int dx[] = {-1, 1, 0, 0, 0, 0};\n                int dy[] = {0, 0, -1, 1, 0, 0};\n                int dz[] = {0, 0, 0, 0, -1, 1};\n                for (int i = 0; i < 6; ++i) {\n                    Point3D next = {curr.x + dx[i], curr.y + dy[i], curr.z + dz[i]};\n                    if (is_valid_coord(next.x, next.y, next.z) && visited_common[next.x][next.y][next.z]) {\n                        visited_common[next.x][next.y][next.z] = false;\n                        q.push_back(next);\n                    }\n                }\n            }\n            common_blocks.push_back({current_block_points, 0});\n        }\n    }\n\n    vector<bool> f1_req_met(D*D, false), r1_req_met(D*D, false);\n    for (const auto& block : common_blocks) {\n        for (const auto& p : block.points) {\n            f1_req_met[p.z * D + p.x] = true;\n            r1_req_met[p.z * D + p.y] = true;\n        }\n    }\n\n    vector<ProtoBlock> filler1_blocks;\n    {\n        vector<Point3D> c1_only_cells;\n        for (int x=0; x<D; ++x) for (int y=0; y<D; ++y) for (int z=0; z<D; ++z) {\n             if (C1[x][y][z] && !C_common[x][y][z]) c1_only_cells.push_back({x,y,z});\n        }\n        vector<Point3D> filler1_cells;\n        while(true) {\n            int best_score = 0; int best_idx = -1;\n            for(size_t i=0; i<c1_only_cells.size(); ++i){\n                const auto& p = c1_only_cells[i];\n                int score = (f1[p.z][p.x]=='1' && !f1_req_met[p.z*D+p.x]) + (r1[p.z][p.y]=='1' && !r1_req_met[p.z*D+p.y]);\n                if(score > best_score) { best_score = score; best_idx = i; }\n            }\n            if (best_score == 0) break;\n            Point3D p = c1_only_cells[best_idx];\n            filler1_cells.push_back(p);\n            f1_req_met[p.z*D+p.x] = true; r1_req_met[p.z*D+p.y] = true;\n            swap(c1_only_cells[best_idx], c1_only_cells.back()); c1_only_cells.pop_back();\n        }\n        vector<vector<vector<bool>>> filler1_grid(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n        for(const auto& p : filler1_cells) filler1_grid[p.x][p.y][p.z] = true;\n        for(const auto& p_start : filler1_cells) {\n            if (filler1_grid[p_start.x][p_start.y][p_start.z]) {\n                Shape current_block_points; vector<Point3D> q; q.push_back(p_start);\n                filler1_grid[p_start.x][p_start.y][p_start.z] = false;\n                size_t head = 0;\n                while(head < q.size()){\n                    Point3D curr = q[head++]; current_block_points.push_back(curr);\n                    int dx[]={-1,1,0,0,0,0}, dy[]={0,0,-1,1,0,0}, dz[]={0,0,0,0,-1,1};\n                    for (int i=0; i<6; ++i) {\n                        Point3D next = {curr.x+dx[i], curr.y+dy[i], curr.z+dz[i]};\n                        if (is_valid_coord(next.x, next.y, next.z) && filler1_grid[next.x][next.y][next.z]) {\n                            filler1_grid[next.x][next.y][next.z] = false; q.push_back(next);\n                        }\n                    }\n                }\n                filler1_blocks.push_back({current_block_points, 0});\n            }\n        }\n    }\n    \n    vector<pair<int, ProtoBlock>> placed_common_blocks;\n    for(size_t i=0; i<common_blocks.size(); ++i) {\n        placed_common_blocks.push_back({(int)i, common_blocks[i]});\n    }\n    vector<ProtoBlock> filler2_blocks;\n    {\n        vector<vector<vector<bool>>> occupied2(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n        vector<bool> f2_req_met(D*D, false), r2_req_met(D*D, false);\n\n        sort(placed_common_blocks.begin(), placed_common_blocks.end(), [](const auto& a, const auto& b){\n            return a.second.points.size() > b.second.points.size();\n        });\n\n        for (auto& [idx, block] : placed_common_blocks) {\n            Shape s_rel = normalize_shape(block.points);\n            int best_block_score = -1; Shape best_block_placed_shape;\n            for (const auto& R : ROTS) {\n                Shape s_rot; for(const auto& p : s_rel) s_rot.push_back(rotate(p, R));\n                Point3D min_p = s_rot[0];\n                for(size_t i=1; i<s_rot.size(); ++i) { min_p.x=min(min_p.x,s_rot[i].x); min_p.y=min(min_p.y,s_rot[i].y); min_p.z=min(min_p.z,s_rot[i].z); }\n                for (int x=0; x<D; ++x) for(int y=0; y<D; ++y) for(int z=0; z<D; ++z) {\n                    Point3D trans = {x - min_p.x, y - min_p.y, z - min_p.z};\n                    bool possible = true; Shape placed_shape;\n                    set<pair<int,int>> f_covered, r_covered;\n                    for (const auto& p_rot : s_rot) {\n                        Point3D p_final = p_rot + trans;\n                        if (!is_valid_coord(p_final.x, p_final.y, p_final.z) || !C2[p_final.x][p_final.y][p_final.z] || occupied2[p_final.x][p_final.y][p_final.z]) {\n                            possible = false; break;\n                        }\n                        placed_shape.push_back(p_final);\n                        if (f2[p_final.z][p_final.x]=='1' && !f2_req_met[p_final.z*D+p_final.x]) f_covered.insert({p_final.z, p_final.x});\n                        if (r2[p_final.z][p_final.y]=='1' && !r2_req_met[p_final.z*D+p_final.y]) r_covered.insert({p_final.z, p_final.y});\n                    }\n                    if (possible) {\n                        int current_score = f_covered.size() + r_covered.size();\n                        if (current_score > best_block_score) {\n                            best_block_score = current_score; best_block_placed_shape = placed_shape;\n                        }\n                    }\n                }\n            }\n            if(best_block_score > -1){\n                block.points = best_block_placed_shape;\n                for (const auto& p : block.points) {\n                    occupied2[p.x][p.y][p.z] = true;\n                    f2_req_met[p.z*D+p.x] = true; r2_req_met[p.z*D+p.y] = true;\n                }\n            } else { block.points.clear(); }\n        }\n        \n        vector<Point3D> c2_rem_cells;\n        for (int x=0; x<D; ++x) for (int y=0; y<D; ++y) for (int z=0; z<D; ++z) {\n             if (C2[x][y][z] && !occupied2[x][y][z]) c2_rem_cells.push_back({x,y,z});\n        }\n        vector<Point3D> filler2_cells;\n        while(true) {\n            int best_score=0; int best_idx=-1;\n            for(size_t i=0; i<c2_rem_cells.size(); ++i){\n                const auto& p = c2_rem_cells[i];\n                int score = (f2[p.z][p.x]=='1' && !f2_req_met[p.z*D+p.x]) + (r2[p.z][p.y]=='1' && !r2_req_met[p.z*D+p.y]);\n                if(score > best_score) { best_score = score; best_idx = i; }\n            }\n            if(best_score == 0) break;\n            Point3D p = c2_rem_cells[best_idx];\n            filler2_cells.push_back(p);\n            f2_req_met[p.z*D+p.x] = true; r2_req_met[p.z*D+p.y] = true;\n            swap(c2_rem_cells[best_idx], c2_rem_cells.back()); c2_rem_cells.pop_back();\n        }\n        \n        vector<vector<vector<bool>>> filler2_grid(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n        for(const auto& p : filler2_cells) filler2_grid[p.x][p.y][p.z] = true;\n        for(const auto& p_start : filler2_cells) {\n            if (filler2_grid[p_start.x][p_start.y][p_start.z]) {\n                Shape current_block_points; vector<Point3D> q; q.push_back(p_start);\n                filler2_grid[p_start.x][p_start.y][p_start.z] = false;\n                size_t head = 0;\n                while(head < q.size()){\n                    Point3D curr = q[head++]; current_block_points.push_back(curr);\n                    int dx[]={-1,1,0,0,0,0}, dy[]={0,0,-1,1,0,0}, dz[]={0,0,0,0,-1,1};\n                    for (int i=0; i<6; ++i) {\n                        Point3D next = {curr.x+dx[i], curr.y+dy[i], curr.z+dz[i]};\n                        if (is_valid_coord(next.x, next.y, next.z) && filler2_grid[next.x][next.y][next.z]) {\n                            filler2_grid[next.x][next.y][next.z] = false; q.push_back(next);\n                        }\n                    }\n                }\n                filler2_blocks.push_back({current_block_points, 0});\n            }\n        }\n    }\n    \n    map<Shape, int> canonical_to_id; int next_id = 1;\n    auto get_id = [&](const Shape& s) {\n        if (s.empty()) return 0;\n        Shape relative_s = normalize_shape(s);\n        Shape canon = get_canonical_shape(relative_s);\n        if (canonical_to_id.find(canon) == canonical_to_id.end()) {\n            canonical_to_id[canon] = next_id++;\n        }\n        return canonical_to_id[canon];\n    };\n    \n    for (auto& block : common_blocks) block.id = get_id(block.points);\n    for (auto& block : filler1_blocks) block.id = get_id(block.points);\n    for (auto& block : filler2_blocks) block.id = get_id(block.points);\n\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    for (const auto& block : common_blocks) for (const auto& p : block.points) b1[p.x][p.y][p.z] = block.id;\n    for (const auto& block : filler1_blocks) for (const auto& p : block.points) b1[p.x][p.y][p.z] = block.id;\n    for (const auto& [idx, block] : placed_common_blocks) {\n        if (!block.points.empty()) {\n            int id = common_blocks[idx].id;\n            for (const auto& p : block.points) b2[p.x][p.y][p.z] = id;\n        }\n    }\n    for (const auto& block : filler2_blocks) for (const auto& p : block.points) b2[p.x][p.y][p.z] = block.id;\n    \n    cout << next_id - 1 << endl;\n    for (int x=0; x<D; ++x) for (int y=0; y<D; ++y) for (int z=0; z<D; ++z) cout << b1[x][y][z] << (x==D-1 && y==D-1 && z==D-1 ? \"\" : \" \"); cout << endl;\n    for (int x=0; x<D; ++x) for (int y=0; y<D; ++y) for (int z=0; z<D; ++z) cout << b2[x][y][z] << (x==D-1 && y==D-1 && z==D-1 ? \"\" : \" \"); cout << endl;\n\n    return 0;\n}","ahc020":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <queue>\n\nusing namespace std;\n\nconst long long INF = 1e18;\n\nstruct Point {\n    long long x, y;\n};\n\nstruct Edge {\n    int u, v;\n    long long w;\n    int id;\n};\n\nstruct GraphEdge {\n    int to;\n    long long weight;\n    int id;\n};\n\nlong long distSq(const Point& p1, const Point& p2) {\n    return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y);\n}\n\n// Global timer\nchrono::steady_clock::time_point start_time;\n\nbool is_time_up(double time_limit) {\n    auto now = chrono::steady_clock::now();\n    double elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n    return elapsed > time_limit;\n}\n\n// --- Precomputed data ---\nint N, M, K;\nvector<Point> stations;\nvector<Point> residents;\nvector<Edge> edges;\nvector<vector<GraphEdge>> adj;\nvector<vector<long long>> dist_G;\nvector<vector<int>> parent_G;\nvector<vector<pair<long long, int>>> dists_to_resident;\n\n// --- Randomness ---\nmt19937 rng;\n\nlong long calculate_connection_cost(const vector<int>& V_list) {\n    if (V_list.empty()) return 0;\n    if (V_list.size() == 1) return 0;\n\n    long long cost = 0;\n    vector<long long> min_cost(N + 1, INF);\n    vector<bool> in_mst(N + 1, false);\n\n    min_cost[V_list[0]] = 0;\n    \n    for (size_t i = 0; i < V_list.size(); ++i) {\n        int u = -1;\n        for (int station_id : V_list) {\n            if (!in_mst[station_id] && (u == -1 || min_cost[station_id] < min_cost[u])) {\n                u = station_id;\n            }\n        }\n\n        if (u == -1) break;\n        if (min_cost[u] == INF) return INF; // Should not happen in a connected graph\n        in_mst[u] = true;\n        cost += min_cost[u];\n\n        for (int v : V_list) {\n            if (!in_mst[v]) {\n                min_cost[v] = min(min_cost[v], dist_G[u - 1][v - 1]);\n            }\n        }\n    }\n    return cost;\n}\n\nbool check_coverage(const vector<bool>& active) {\n    for (int k = 0; k < K; ++k) {\n        bool covered = false;\n        for (const auto& p : dists_to_resident[k]) {\n            if (active[p.second]) {\n                covered = true;\n                break;\n            }\n        }\n        if (!covered) return false;\n    }\n    return true;\n}\n\nlong long calculate_total_cost(const vector<bool>& active) {\n    vector<int> V_list;\n    for (int i = 1; i <= N; ++i) {\n        if (active[i]) V_list.push_back(i);\n    }\n    if (V_list.empty() || !active[1]) {\n        return INF;\n    }\n\n    long long connection_cost = calculate_connection_cost(V_list);\n\n    long long power_cost = 0;\n    vector<long long> required_power_sq(N + 1, 0);\n\n    for (int k = 0; k < K; ++k) {\n        for (const auto& p : dists_to_resident[k]) {\n            int station_id = p.second;\n            if (active[station_id]) {\n                required_power_sq[station_id] = max(required_power_sq[station_id], p.first);\n                break;\n            }\n        }\n    }\n\n    for (int i = 1; i <= N; ++i) {\n        power_cost += required_power_sq[i];\n    }\n    \n    return connection_cost + power_cost;\n}\n\nvoid solve() {\n    start_time = chrono::steady_clock::now();\n    \n    cin >> N >> M >> K;\n    stations.resize(N);\n    for (int i = 0; i < N; ++i) cin >> stations[i].x >> stations[i].y;\n    edges.resize(M);\n    adj.resize(N + 1);\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\n        edges[i].id = i + 1;\n        adj[edges[i].u].push_back({edges[i].v, edges[i].w, edges[i].id});\n        adj[edges[i].v].push_back({edges[i].u, edges[i].w, edges[i].id});\n    }\n    residents.resize(K);\n    for (int i = 0; i < K; ++i) cin >> residents[i].x >> residents[i].y;\n\n    // Precomputation\n    dist_G.assign(N, vector<long long>(N, INF));\n    parent_G.assign(N, vector<int>(N, -1));\n\n    for (int i = 0; i < N; ++i) {\n        dist_G[i][i] = 0;\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n        pq.push({0, i + 1});\n\n        vector<long long> d(N + 1, INF);\n        vector<int> p(N + 1, -1);\n        d[i + 1] = 0;\n\n        while (!pq.empty()) {\n            auto [cost, u] = pq.top();\n            pq.pop();\n\n            if (cost > d[u]) continue;\n\n            for (const auto& edge : adj[u]) {\n                int v = edge.to;\n                if (d[u] + edge.weight < d[v]) {\n                    d[v] = d[u] + edge.weight;\n                    p[v] = u;\n                    pq.push({d[v], v});\n                }\n            }\n        }\n        for (int j = 0; j < N; ++j) {\n            dist_G[i][j] = d[j + 1];\n            parent_G[i][j] = p[j + 1];\n        }\n    }\n    \n    dists_to_resident.resize(K);\n    for (int k = 0; k < K; ++k) {\n        for (int i = 0; i < N; ++i) {\n            dists_to_resident[k].push_back({distSq(residents[k], stations[i]), i + 1});\n        }\n        sort(dists_to_resident[k].begin(), dists_to_resident[k].end());\n    }\n\n    // Initial Solution\n    vector<bool> current_V(N + 1, false);\n    current_V[1] = true;\n\n    while (true) {\n        int first_uncovered = -1;\n        for (int k = 0; k < K; ++k) {\n            bool is_k_covered = false;\n            for (const auto& p : dists_to_resident[k]) {\n                if (current_V[p.second]) {\n                    is_k_covered = true;\n                    break;\n                }\n            }\n            if (!is_k_covered) {\n                first_uncovered = k;\n                break;\n            }\n        }\n\n        if (first_uncovered == -1) break;\n\n        current_V[dists_to_resident[first_uncovered][0].second] = true;\n    }\n\n    vector<bool> best_V = current_V;\n    long long current_cost = calculate_total_cost(current_V);\n    long long best_cost = current_cost;\n\n    // Simulated Annealing\n    double time_limit = 1950;\n    double T_start = best_cost / 10.0;\n    double T_end = 1.0;\n    \n    uniform_int_distribution<> dist_N(1, N);\n    uniform_real_distribution<> dist_real(0.0, 1.0);\n\n    while (!is_time_up(time_limit)) {\n        double elapsed = chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count();\n        double progress = elapsed / time_limit;\n        if (progress > 1.0) progress = 1.0;\n        double T = T_start * pow(T_end / T_start, progress);\n\n        vector<bool> next_V = current_V;\n        \n        double p = dist_real(rng);\n        if (p < 0.45) { // ADD\n            int u = dist_N(rng);\n            int attempts = 0;\n            while (next_V[u] && attempts < 2*N) {\n                u = dist_N(rng);\n                attempts++;\n            }\n            if (!next_V[u]) next_V[u] = true; else continue;\n        } else if (p < 0.9) { // REMOVE\n            int v = dist_N(rng);\n            int attempts = 0;\n            while ((v == 1 || !next_V[v]) && attempts < 2*N) {\n                v = dist_N(rng);\n                attempts++;\n            }\n            if (v != 1 && next_V[v]) next_V[v] = false; else continue;\n            \n            if (!check_coverage(next_V)) continue;\n        } else { // SWAP\n            int u = dist_N(rng);\n            int attempts_u = 0;\n            while(next_V[u] && attempts_u < 2*N) {\n                 u = dist_N(rng);\n                 attempts_u++;\n            }\n            if(next_V[u]) continue;\n\n            int v = dist_N(rng);\n            int attempts_v = 0;\n            while((v==1 || !next_V[v]) && attempts_v < 2*N) {\n                v = dist_N(rng);\n                attempts_v++;\n            }\n            if(v==1 || !next_V[v]) continue;\n            \n            next_V[u] = true;\n            next_V[v] = false;\n            if (!check_coverage(next_V)) continue;\n        }\n        \n        long long next_cost = calculate_total_cost(next_V);\n        if(next_cost == INF) continue;\n\n        long long delta = next_cost - current_cost;\n        if (delta < 0 || dist_real(rng) < exp(-(double)delta / T)) {\n            current_V = next_V;\n            current_cost = next_cost;\n            if (current_cost < best_cost) {\n                best_cost = current_cost;\n                best_V = current_V;\n            }\n        }\n    }\n\n    // Output\n    vector<long long> P(N + 1, 0);\n    vector<long long> required_power_sq(N + 1, 0);\n    for (int k = 0; k < K; ++k) {\n        for (const auto& p : dists_to_resident[k]) {\n            int station_id = p.second;\n            if (best_V[station_id]) {\n                required_power_sq[station_id] = max(required_power_sq[station_id], p.first);\n                break;\n            }\n        }\n    }\n    for (int i = 1; i <= N; ++i) {\n        if (best_V[i]) {\n            P[i] = min(5000LL, (long long)round(sqrt((long double)required_power_sq[i])));\n        }\n    }\n\n    vector<bool> B(M + 1, false);\n    vector<int> V_list;\n    for (int i = 1; i <= N; ++i) if (best_V[i]) V_list.push_back(i);\n\n    if (V_list.size() > 1) {\n        vector<long long> min_cost(N + 1, INF);\n        vector<int> edge_from(N + 1, -1);\n        vector<bool> in_mst(N + 1, false);\n        min_cost[V_list[0]] = 0;\n\n        for (size_t i = 0; i < V_list.size(); ++i) {\n            int u = -1;\n            for (int station_id : V_list) {\n                if (!in_mst[station_id] && (u == -1 || min_cost[station_id] < min_cost[u])) {\n                    u = station_id;\n                }\n            }\n\n            if (u == -1) break;\n            in_mst[u] = true;\n            if (edge_from[u] != -1) {\n                int v = edge_from[u];\n                int target = v - 1;\n                int curr = u - 1;\n                while (curr != target) {\n                    int prev = parent_G[target][curr] - 1;\n                    if(prev < 0) break;\n                    \n                    bool edge_found = false;\n                    for (const auto& edge : adj[curr + 1]) {\n                        if (edge.to == prev + 1) {\n                            B[edge.id] = true;\n                            edge_found = true;\n                            break;\n                        }\n                    }\n                    if(!edge_found) { // for undirected graph\n                        for (const auto& edge : adj[prev + 1]) {\n                            if (edge.to == curr + 1) {\n                                B[edge.id] = true;\n                                break;\n                            }\n                        }\n                    }\n                    curr = prev;\n                }\n            }\n\n            for (int v : V_list) {\n                if (!in_mst[v] && dist_G[u - 1][v - 1] < min_cost[v]) {\n                    min_cost[v] = dist_G[u - 1][v - 1];\n                    edge_from[v] = u;\n                }\n            }\n        }\n    }\n\n\n    for (int i = 1; i <= N; ++i) cout << P[i] << (i == N ? \"\" : \" \");\n    cout << endl;\n    for (int i = 1; i <= M; ++i) cout << B[i] << (i == M ? \"\" : \" \");\n    cout << endl;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    unsigned int seed = 0;\n    try {\n        seed = chrono::high_resolution_clock::now().time_since_epoch().count();\n    } catch(const exception& e) {\n        // fallback\n    }\n    rng.seed(seed);\n    solve();\n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <tuple>\n\nconst int N = 30;\n\nstd::vector<std::vector<int>> b;\nstd::vector<std::tuple<int, int, int, int>> ops;\n\n// A helper function to perform a swap and record it.\n// It stops recording if the operation limit is reached.\nvoid do_swap(int r1, int c1, int r2, int c2) {\n    if (ops.size() >= 10000) return;\n    std::swap(b[r1][c1], b[r2][c2]);\n    ops.emplace_back(r1, c1, r2, c2);\n}\n\n// Function to check if the pyramid satisfies the condition (E=0).\nint count_errors() {\n    int errors = 0;\n    for (int r = 0; r < N - 1; ++r) {\n        for (int c = 0; c <= r; ++c) {\n            if (b[r][c] > b[r + 1][c]) {\n                errors++;\n            }\n            if (b[r][c] > b[r + 1][c + 1]) {\n                errors++;\n            }\n        }\n    }\n    return errors;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    b.resize(N);\n    for (int i = 0; i < N; ++i) {\n        b[i].resize(i + 1);\n        for (int j = 0; j <= i; ++j) {\n            std::cin >> b[i][j];\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        if (ops.size() >= 10000) break;\n        \n        // Top-down pass: push large numbers down.\n        if (i % 2 == 0) { // Alternate column iteration direction\n            for (int r = 0; r < N - 1; ++r) {\n                for (int c = 0; c <= r; ++c) {\n                    if (ops.size() >= 10000) break;\n                    int val_p = b[r][c];\n                    int val_c1 = b[r + 1][c];\n                    int val_c2 = b[r + 1][c + 1];\n\n                    if (val_p > val_c1 && val_p > val_c2) {\n                        if (val_c1 < val_c2) do_swap(r, c, r + 1, c);\n                        else do_swap(r, c, r + 1, c + 1);\n                    } else if (val_p > val_c1) {\n                        do_swap(r, c, r + 1, c);\n                    } else if (val_p > val_c2) {\n                        do_swap(r, c, r + 1, c + 1);\n                    }\n                }\n                if (ops.size() >= 10000) break;\n            }\n        } else {\n             for (int r = 0; r < N - 1; ++r) {\n                for (int c = r; c >= 0; --c) {\n                    if (ops.size() >= 10000) break;\n                    int val_p = b[r][c];\n                    int val_c1 = b[r + 1][c];\n                    int val_c2 = b[r + 1][c + 1];\n\n                    if (val_p > val_c1 && val_p > val_c2) {\n                        if (val_c1 < val_c2) do_swap(r, c, r + 1, c);\n                        else do_swap(r, c, r + 1, c + 1);\n                    } else if (val_p > val_c1) {\n                        do_swap(r, c, r + 1, c);\n                    } else if (val_p > val_c2) {\n                        do_swap(r, c, r + 1, c + 1);\n                    }\n                }\n                if (ops.size() >= 10000) break;\n            }\n        }\n\n        if (ops.size() >= 10000) break;\n\n        // Bottom-up pass: pull small numbers up.\n        if (i % 2 == 0) { // Alternate column iteration direction\n            for (int r = N - 1; r >= 1; --r) {\n                for (int c = 0; c <= r; ++c) {\n                    if (ops.size() >= 10000) break;\n                    int val_c = b[r][c];\n                    bool has_p1 = (c > 0);\n                    bool has_p2 = (c < r);\n\n                    if (has_p1 && !has_p2) { // Right edge child\n                        if (val_c < b[r - 1][c - 1]) {\n                            do_swap(r, c, r - 1, c - 1);\n                        }\n                    } else if (!has_p1 && has_p2) { // Left edge child\n                        if (val_c < b[r - 1][c]) {\n                            do_swap(r, c, r - 1, c);\n                        }\n                    } else if (has_p1 && has_p2) { // Middle child\n                        int val_p1 = b[r - 1][c - 1];\n                        int val_p2 = b[r - 1][c];\n                        if (val_c < val_p1 || val_c < val_p2) {\n                            if (val_p1 > val_p2) {\n                                if (val_c < val_p1) do_swap(r, c, r - 1, c - 1);\n                            } else {\n                                if (val_c < val_p2) do_swap(r, c, r - 1, c);\n                            }\n                        }\n                    }\n                }\n                if (ops.size() >= 10000) break;\n            }\n        } else {\n            for (int r = N - 1; r >= 1; --r) {\n                for (int c = r; c >= 0; --c) {\n                    if (ops.size() >= 10000) break;\n                    int val_c = b[r][c];\n                    bool has_p1 = (c > 0);\n                    bool has_p2 = (c < r);\n\n                    if (has_p1 && !has_p2) { // Right edge child\n                        if (val_c < b[r - 1][c - 1]) {\n                            do_swap(r, c, r - 1, c - 1);\n                        }\n                    } else if (!has_p1 && has_p2) { // Left edge child\n                        if (val_c < b[r - 1][c]) {\n                            do_swap(r, c, r - 1, c);\n                        }\n                    } else if (has_p1 && has_p2) { // Middle child\n                        int val_p1 = b[r - 1][c - 1];\n                        int val_p2 = b[r - 1][c];\n                        if (val_c < val_p1 || val_c < val_p2) {\n                            if (val_p1 > val_p2) {\n                                if (val_c < val_p1) do_swap(r, c, r - 1, c - 1);\n                            } else {\n                                if (val_c < val_p2) do_swap(r, c, r - 1, c);\n                            }\n                        }\n                    }\n                }\n                if (ops.size() >= 10000) break;\n            }\n        }\n        \n        // Check for early termination if sorted.\n        if (count_errors() == 0) {\n            break;\n        }\n    }\n\n    std::cout << ops.size() << \"\\n\";\n    for (const auto& op : ops) {\n        std::cout << std::get<0>(op) << \" \" << std::get<1>(op) << \" \" << std::get<2>(op) << \" \" << std::get<3>(op) << \"\\n\";\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n#include <map>\n#include <tuple>\n#include <set>\n\nusing namespace std;\n\n// Constants\nconst int D_CONST = 9;\nconst int ENTRANCE_R = 0;\nconst int ENTRANCE_C = (D_CONST - 1) / 2;\nconst int DR[] = {-1, 1, 0, 0};\nconst int DC[] = {0, 0, -1, 1};\n\n// Global state\nint D_input, N;\nint C; // Number of containers\nvector<vector<int>> grid;\n\n// Precomputed data\nstruct SquareInfo {\n    int r, c;\n    int dist;\n    int block_count;\n\n    bool operator<(const SquareInfo& other) const {\n        if (block_count != other.block_count) return block_count > other.block_count;\n        if (dist != other.dist) return dist > other.dist;\n        if (r != other.r) return r > other.r;\n        if (abs(c - ENTRANCE_C) != abs(other.c - ENTRANCE_C)) return abs(c - ENTRANCE_C) > abs(other.c - ENTRANCE_C);\n        return c > other.c;\n    }\n};\nvector<SquareInfo> P;\nvector<bool> p_occupied;\nmap<int, pair<int, int>> container_locs;\n\n// Utility functions\nbool is_valid(int r, int c) {\n    return r >= 0 && r < D_CONST && c >= 0 && c < D_CONST;\n}\n\n// BFS on a grid where -1 is a wall.\nvector<vector<int>> bfs_on_static_grid(const vector<vector<int>>& static_grid) {\n    vector<vector<int>> dist(D_CONST, vector<int>(D_CONST, -1));\n    queue<pair<int, int>> q;\n\n    if (static_grid[ENTRANCE_R][ENTRANCE_C] == -1) return dist;\n\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();\n        q.pop();\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + DR[i];\n            int nc = c + DC[i];\n            if (is_valid(nr, nc) && dist[nr][nc] == -1 && static_grid[nr][nc] != -1) {\n                dist[nr][nc] = dist[r][c] + 1;\n                q.push({nr, nc});\n            }\n        }\n    }\n    return dist;\n}\n\n// Phase 1: Pre-computation\nvoid precompute() {\n    C = D_CONST * D_CONST - 1 - N;\n\n    grid.assign(D_CONST, vector<int>(D_CONST, -3)); // -3: empty\n    grid[ENTRANCE_R][ENTRANCE_C] = -2; // -2: entrance\n    \n    for (int i = 0; i < N; ++i) {\n        int r, c;\n        cin >> r >> c;\n        grid[r][c] = -1; // -1: obstacle\n    }\n\n    vector<pair<int, int>> placeable_squares;\n    for (int i = 0; i < D_CONST; ++i) {\n        for (int j = 0; j < D_CONST; ++j) {\n            if (grid[i][j] == -3) {\n                placeable_squares.push_back({i, j});\n            }\n        }\n    }\n\n    auto initial_dist_grid = bfs_on_static_grid(grid);\n\n    for (const auto& s : placeable_squares) {\n        SquareInfo info;\n        info.r = s.first;\n        info.c = s.second;\n        info.dist = initial_dist_grid[s.first][s.second];\n\n        vector<vector<int>> temp_grid = grid;\n        temp_grid[s.first][s.second] = -1;\n        \n        auto dist_after_block = bfs_on_static_grid(temp_grid);\n        \n        int reachable_count = 0;\n        for (const auto& other_s : placeable_squares) {\n            if (s != other_s) {\n                if (dist_after_block[other_s.first][other_s.second] != -1) {\n                    reachable_count++;\n                }\n            }\n        }\n        info.block_count = (placeable_squares.size() - 1) - reachable_count;\n        P.push_back(info);\n    }\n    \n    sort(P.begin(), P.end());\n}\n\n// Phase 2: Placement\nvoid solve_placement() {\n    p_occupied.assign(C, false);\n    \n    for (int d = 0; d < C; ++d) {\n        int t_d;\n        cin >> t_d;\n\n        vector<vector<bool>> visited(D_CONST, vector<bool>(D_CONST, false));\n        queue<pair<int, int>> q;\n\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();\n            q.pop();\n\n            for(int i = 0; i < 4; ++i){\n                int nr = r + DR[i];\n                int nc = c + DC[i];\n                if(is_valid(nr, nc) && !visited[nr][nc]) {\n                    if(grid[nr][nc] == -3 || grid[nr][nc] == -2) {\n                        visited[nr][nc] = true;\n                        q.push({nr, nc});\n                    }\n                }\n            }\n        }\n\n        int target_rank = (C - 1) - t_d;\n        int best_k = -1;\n\n        for (int delta = 0; delta < C; ++delta) {\n            int k1 = target_rank - delta;\n            if (k1 >= 0 && k1 < C && !p_occupied[k1]) {\n                if (visited[P[k1].r][P[k1].c]) {\n                    best_k = k1;\n                    break;\n                }\n            }\n            if (delta > 0) {\n                int k2 = target_rank + delta;\n                if (k2 >= 0 && k2 < C && !p_occupied[k2]) {\n                    if (visited[P[k2].r][P[k2].c]) {\n                        best_k = k2;\n                        break;\n                    }\n                }\n            }\n        }\n        \n        p_occupied[best_k] = true;\n        int r_out = P[best_k].r;\n        int c_out = P[best_k].c;\n        grid[r_out][c_out] = t_d;\n        container_locs[t_d] = {r_out, c_out};\n\n        cout << r_out << \" \" << c_out << endl;\n    }\n}\n\n// Phase 3: Retrieval\nvoid solve_retrieval() {\n    for (int k = 0; k < C; ++k) {\n        set<int> accessible_containers;\n        queue<pair<int, int>> q;\n        vector<vector<bool>> visited_empty(D_CONST, vector<bool>(D_CONST, false));\n\n        q.push({ENTRANCE_R, ENTRANCE_C});\n        visited_empty[ENTRANCE_R][ENTRANCE_C] = true;\n\n        while(!q.empty()){\n            auto [r, c] = q.front();\n            q.pop();\n\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + DR[i];\n                int nc = c + DC[i];\n                if (!is_valid(nr, nc)) continue;\n                \n                if (grid[nr][nc] >= 0) {\n                    accessible_containers.insert(grid[nr][nc]);\n                } else if (grid[nr][nc] == -3 && !visited_empty[nr][nc]) {\n                    visited_empty[nr][nc] = true;\n                    q.push({nr, nc});\n                }\n            }\n        }\n\n        int min_t = *accessible_containers.begin();\n\n        auto [qr, qc] = container_locs[min_t];\n        cout << qr << \" \" << qc << endl;\n        grid[qr][qc] = -3;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> D_input >> N;\n    \n    precompute();\n    solve_placement();\n    solve_retrieval();\n\n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <set>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <queue>\n#include <tuple>\n\n// Constants\nconstexpr int N = 50;\nconstexpr int M = 100;\n\n// Randomness\nstruct Xoroshiro128 {\n    uint64_t s[2];\n\n    Xoroshiro128() {\n        std::random_device rd;\n        s[0] = ((uint64_t)rd() << 32) | rd();\n        s[1] = ((uint64_t)rd() << 32) | rd();\n    }\n\n    static inline uint64_t rotl(const uint64_t x, int k) {\n        return (x << k) | (x >> (64 - k));\n    }\n\n    uint64_t next() {\n        const uint64_t s0 = s[0];\n        uint64_t s1 = s[1];\n        const uint64_t result = s0 + s1;\n\n        s1 ^= s0;\n        s[0] = rotl(s0, 24) ^ s1 ^ (s1 << 16);\n        s[1] = rotl(s1, 37);\n\n        return result;\n    }\n\n    double next_double() {\n        return (double)(next() >> 11) * (1.0 / (1LL << 53));\n    }\n};\n\nXoroshiro128 rng;\n\n// Timer\nclass Timer {\npublic:\n    Timer() : start_time(std::chrono::high_resolution_clock::now()) {}\n\n    double get_elapsed_sec() {\n        auto now = std::chrono::high_resolution_clock::now();\n        return std::chrono::duration_cast<std::chrono::duration<double>>(now - start_time).count();\n    }\nprivate:\n    std::chrono::time_point<std::chrono::high_resolution_clock> start_time;\n};\n\n// Data structures\nstruct Point {\n    int r, c;\n};\n\nstruct Vec2d {\n    double x, y;\n};\n\n// Globals for problem data\nstd::vector<std::vector<bool>> adj;\nstd::vector<std::vector<int>> initial_grid;\n\nvoid read_input() {\n    int n_dummy, m_dummy;\n    std::cin >> n_dummy >> m_dummy;\n    initial_grid.assign(N, std::vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            std::cin >> initial_grid[i][j];\n        }\n    }\n}\n\nvoid build_adj() {\n    adj.assign(M + 1, std::vector<bool>(M + 1, false));\n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            if (r == 0 || r == N - 1 || c == 0 || c == N - 1) {\n                adj[initial_grid[r][c]][0] = adj[0][initial_grid[r][c]] = true;\n            }\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + dr[i];\n                int nc = c + dc[i];\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                    int c1 = initial_grid[r][c];\n                    int c2 = initial_grid[nr][nc];\n                    if (c1 != c2) {\n                        adj[c1][c2] = adj[c2][c1] = true;\n                    }\n                }\n            }\n        }\n    }\n}\n\nstruct Solution {\n    std::vector<std::vector<int>> grid;\n    int score;\n\n    Solution() : grid(N, std::vector<int>(N, 0)), score(0) {}\n\n    void calculate_score() {\n        int empty_count = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (grid[i][j] == 0) {\n                    empty_count++;\n                }\n            }\n        }\n        score = empty_count + 1;\n    }\n\n    void print() {\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                std::cout << grid[i][j] << (j == N - 1 ? \"\" : \" \");\n            }\n            std::cout << std::endl;\n        }\n    }\n};\n\nclass Solver {\npublic:\n    Solver(const Timer& timer) : timer(timer) {}\n\n    Solution solve() {\n        Solution best_solution;\n        best_solution.score = -1;\n\n        while(timer.get_elapsed_sec() < 1.95) {\n            Solution current_solution = generate_solution();\n            if (current_solution.score > best_solution.score) {\n                best_solution = current_solution;\n            }\n        }\n        return best_solution;\n    }\n\nprivate:\n    const Timer& timer;\n    std::vector<std::vector<int>> grid;\n    std::vector<Point> seed_pos;\n\n    Solution generate_solution() {\n        std::vector<Vec2d> positions = force_directed_layout();\n        grid.assign(N, std::vector<int>(N, 0));\n        seed_pos.assign(M + 1, {-1, -1});\n        place_seeds(positions);\n        connect_regions();\n        \n        Solution sol;\n        sol.grid = grid;\n        sol.calculate_score();\n        return sol;\n    }\n\n    std::vector<Vec2d> force_directed_layout() {\n        std::vector<Vec2d> pos(M + 1);\n        for (int i = 1; i <= M; ++i) {\n            pos[i] = {rng.next_double() * N, rng.next_double() * N};\n        }\n\n        double temp = N / 4.0;\n        const int iterations = 150;\n        const double k_attr = 0.1, k_rep = 150.0;\n        const double border_rep = 200.0;\n\n        for (int iter = 0; iter < iterations; ++iter) {\n            if (timer.get_elapsed_sec() > 1.95) break;\n\n            std::vector<Vec2d> forces(M + 1, {0.0, 0.0});\n            for (int i = 1; i <= M; ++i) {\n                for (int j = i + 1; j <= M; ++j) {\n                    Vec2d diff = {pos[j].x - pos[i].x, pos[j].y - pos[i].y};\n                    double dist_sq = diff.x * diff.x + diff.y * diff.y + 1e-6;\n                    double dist = std::sqrt(dist_sq);\n                    \n                    if (adj[i][j]) {\n                        double f = k_attr * (dist - N/10.0);\n                        forces[i].x += f * diff.x / dist;\n                        forces[i].y += f * diff.y / dist;\n                        forces[j].x -= f * diff.x / dist;\n                        forces[j].y -= f * diff.y / dist;\n                    } else {\n                        double f = k_rep / dist_sq;\n                        forces[i].x -= f * diff.x / dist;\n                        forces[i].y -= f * diff.y / dist;\n                        forces[j].x += f * diff.x / dist;\n                        forces[j].y += f * diff.y / dist;\n                    }\n                }\n            }\n\n            for (int i = 1; i <= M; ++i) {\n                 if (!adj[i][0]) {\n                    forces[i].x += border_rep / (pos[i].x * pos[i].x + 1e-6);\n                    forces[i].y += border_rep / (pos[i].y * pos[i].y + 1e-6);\n                    forces[i].x -= border_rep / ((N-1 - pos[i].x) * (N-1 - pos[i].x) + 1e-6);\n                    forces[i].y -= border_rep / ((N-1 - pos[i].y) * (N-1 - pos[i].y) + 1e-6);\n                }\n            }\n\n            for (int i = 1; i <= M; ++i) {\n                double force_mag = std::sqrt(forces[i].x * forces[i].x + forces[i].y * forces[i].y) + 1e-6;\n                pos[i].x += temp * forces[i].x / force_mag;\n                pos[i].y += temp * forces[i].y / force_mag;\n                pos[i].x = std::max(1.0, std::min((double)N - 2, pos[i].x));\n                pos[i].y = std::max(1.0, std::min((double)N - 2, pos[i].y));\n            }\n            temp *= 0.98;\n        }\n        return pos;\n    }\n\n    void place_seeds(const std::vector<Vec2d>& pos) {\n        std::vector<int> p(M);\n        std::iota(p.begin(), p.end(), 1);\n        auto mt = std::mt19937(rng.next());\n        std::shuffle(p.begin(), p.end(), mt);\n\n        for (int color : p) {\n            int target_r = std::round(pos[color].y);\n            int target_c = std::round(pos[color].x);\n\n            int best_r = -1, best_c = -1;\n            for (int d = 0; d < N; ++d) {\n                for(int i = -d; i <= d; ++i) {\n                    int j = d - std::abs(i);\n                    int r_offsets[] = {i, i};\n                    int c_offsets[] = {j, -j};\n                    for (int k = 0; k < 2; ++k) {\n                        int r = target_r + r_offsets[k];\n                        int c = target_c + c_offsets[k];\n                        if (r < 0 || r >= N || c < 0 || c >= N) continue;\n                        if (is_valid_placement(color, r, c)) {\n                            best_r = r; best_c = c; goto found_pos;\n                        }\n                    }\n                }\n            }\n            found_pos:;\n            if (best_r != -1) {\n                grid[best_r][best_c] = color;\n                seed_pos[color] = {best_r, best_c};\n            }\n        }\n    }\n\n    bool is_valid_placement(int color, int r, int c) {\n        if (grid[r][c] != 0) return false;\n        if (!adj[color][0] && (r == 0 || r == N - 1 || c == 0 || c == N - 1)) return false;\n        \n        int dr[] = {-1, 1, 0, 0};\n        int dc[] = {0, 0, -1, 1};\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i], nc = c + dc[i];\n            if (nr >= 0 && nr < N && nc >= 0 && nc < N && grid[nr][nc] != 0) {\n                if (!adj[color][grid[nr][nc]]) return false;\n            }\n        }\n        return true;\n    }\n\n    void connect_regions() {\n        std::vector<std::pair<int, int>> reqs;\n        for (int i = 1; i <= M; ++i) for (int j = i + 1; j <= M; ++j) if (adj[i][j]) reqs.push_back({i, j});\n        auto mt = std::mt19937(rng.next());\n        std::shuffle(reqs.begin(), reqs.end(), mt);\n        \n        std::vector<std::vector<bool>> satisfied_adj(M + 1, std::vector<bool>(M + 1, false));\n\n        for (const auto& p : reqs) {\n            if (timer.get_elapsed_sec() > 1.95) break;\n            \n            bool is_adj = false;\n            int c1 = p.first, c2 = p.second;\n            if(seed_pos[c1].r == -1 || seed_pos[c2].r == -1) continue;\n            for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) {\n                if(grid[r][c]==c1) {\n                    int dr[]={-1,1,0,0}, dc[]={0,0,-1,1};\n                    for(int i=0;i<4;++i) {\n                        int nr=r+dr[i], nc=c+dc[i];\n                        if(nr>=0 && nr<N && nc>=0 && nc<N && grid[nr][nc]==c2) { is_adj=true; goto end_check; }\n                    }\n                }\n            }\n            end_check:;\n\n            if (!is_adj) connect_pair(p.first, p.second);\n        }\n        \n        for (int i = 1; i <= M; ++i) {\n            if (timer.get_elapsed_sec() > 1.95) break;\n            if (adj[i][0]) {\n                 bool is_adj_to_0 = false;\n                 for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) {\n                    if (grid[r][c] == i && (r==0 || r==N-1 || c==0 || c==N-1)) {\n                        is_adj_to_0 = true; break;\n                    }\n                 }\n                 if(!is_adj_to_0) connect_to_border(i);\n            }\n        }\n    }\n\n    void connect_pair(int c1, int c2) {\n        using State = std::tuple<int, int, int>;\n        std::priority_queue<State, std::vector<State>, std::greater<State>> pq;\n        std::vector<std::vector<int>> dist(N, std::vector<int>(N, 1e9));\n        std::vector<std::vector<Point>> parent(N, std::vector<Point>(N, {-1, -1}));\n\n        for (int r = 0; r < N; ++r) for (int c = 0; c < N; ++c) {\n            if (grid[r][c] == c1) { pq.emplace(0, r, c); dist[r][c] = 0; }\n        }\n\n        const int PENALTY = N*N;\n        int dr[] = {-1, 1, 0, 0}; int dc[] = {0, 0, -1, 1};\n        Point end_pos = {-1, -1};\n\n        while (!pq.empty()) {\n            auto [d, r, c] = pq.top(); pq.pop();\n            if (d > dist[r][c]) continue;\n\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + dr[i], nc = c + dc[i];\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N && grid[nr][nc] == c2) {\n                    end_pos = {r, c}; goto path_found;\n                }\n            }\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + dr[i], nc = c + dc[i];\n                if (nr < 0 || nr >= N || nc < 0 || nc >= N || (grid[nr][nc] != 0 && grid[nr][nc] != c1)) continue;\n                int cost = 1, penalty = 0;\n                for (int j = 0; j < 4; ++j) {\n                    int nnr = nr + dr[j], nnc = nc + dc[j];\n                    if (nnr < 0 || nnr >= N || nnc < 0 || nnc >= N) continue;\n                    int neighbor_color = grid[nnr][nnc];\n                    if (neighbor_color != 0 && neighbor_color != c1 && !adj[c1][neighbor_color]) penalty += PENALTY;\n                }\n                if (dist[nr][nc] > d + cost + penalty) {\n                    dist[nr][nc] = d + cost + penalty; parent[nr][nc] = {r, c}; pq.emplace(dist[nr][nc], nr, nc);\n                }\n            }\n        }\n    path_found:\n        if (end_pos.r != -1) {\n            Point curr = end_pos;\n            while (grid[curr.r][curr.c] == 0) {\n                grid[curr.r][curr.c] = c1; curr = parent[curr.r][curr.c];\n            }\n        }\n    }\n\n    void connect_to_border(int c1) {\n        if (seed_pos[c1].r == -1) return;\n        using State = std::tuple<int, int, int>;\n        std::priority_queue<State, std::vector<State>, std::greater<State>> pq;\n        std::vector<std::vector<int>> dist(N, std::vector<int>(N, 1e9));\n        std::vector<std::vector<Point>> parent(N, std::vector<Point>(N, {-1, -1}));\n\n        for (int r = 0; r < N; ++r) for (int c = 0; c < N; ++c) {\n            if (grid[r][c] == c1) { pq.emplace(0, r, c); dist[r][c] = 0; }\n        }\n        \n        const int PENALTY = N*N;\n        int dr[] = {-1, 1, 0, 0}; int dc[] = {0, 0, -1, 1};\n        Point end_pos = {-1, -1};\n\n        while (!pq.empty()) {\n            auto [d, r, c] = pq.top(); pq.pop();\n            if (d > dist[r][c]) continue;\n            if (r == 0 || r == N - 1 || c == 0 || c == N - 1) { end_pos = {r, c}; break; }\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + dr[i], nc = c + dc[i];\n                if (nr < 0 || nr >= N || nc < 0 || nc >= N || (grid[nr][nc] != 0 && grid[nr][nc] != c1)) continue;\n                int cost = 1, penalty = 0;\n                for (int j = 0; j < 4; ++j) {\n                    int nnr = nr + dr[j], nnc = nc + dc[j];\n                    if (nnr < 0 || nnr >= N || nnc < 0 || nnc >= N) continue;\n                    int neighbor_color = grid[nnr][nnc];\n                    if (neighbor_color != 0 && neighbor_color != c1 && !adj[c1][neighbor_color]) penalty += PENALTY;\n                }\n                if (!adj[c1][0] && (nr==0 || nr==N-1 || nc==0 || nc==N-1)) penalty += PENALTY;\n                if (dist[nr][nc] > d + cost + penalty) {\n                    dist[nr][nc] = d + cost + penalty; parent[nr][nc] = {r, c}; pq.emplace(dist[nr][nc], nr, nc);\n                }\n            }\n        }\n        if (end_pos.r != -1) {\n            Point curr = end_pos;\n            while (grid[curr.r][curr.c] == 0) {\n                grid[curr.r][curr.c] = c1; curr = parent[curr.r][curr.c];\n            }\n        }\n    }\n};\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    Timer timer;\n\n    read_input();\n    build_adj();\n\n    Solver solver(timer);\n    Solution best_solution = solver.solve();\n    \n    best_solution.print();\n\n    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n\n// --- Utilities ---\nstruct Timer {\n    std::chrono::high_resolution_clock::time_point start_time;\n    Timer() {\n        start_time = std::chrono::high_resolution_clock::now();\n    }\n    long long get_elapsed_ms() const {\n        auto now = std::chrono::high_resolution_clock::now();\n        return std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time).count();\n    }\n};\n\nstd::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// --- Problem specific globals ---\nint N, D, Q;\nconst int NUM_PARTICLES = 2000;\nstd::vector<std::vector<long long>> particles;\ndouble W_CAP;\n\n// --- Query interaction ---\nchar query(const std::vector<int>& L, const std::vector<int>& R) {\n    std::cout << L.size() << \" \" << R.size();\n    for (int x : L) std::cout << \" \" << x;\n    for (int x : R) std::cout << \" \" << x;\n    std::cout << std::endl;\n    char res;\n    std::cin >> res;\n    return res;\n}\n\n// --- Particle management ---\nvoid generate_particles() {\n    particles.clear();\n    std::uniform_real_distribution<double> unif(0.0, 1.0);\n    const double lambda = 1e-5;\n\n    for (int i = 0; i < NUM_PARTICLES; ++i) {\n        std::vector<long long> weights(N);\n        for (int j = 0; j < N; ++j) {\n            double w_prime;\n            do {\n                double u = std::max(1e-9, unif(rng)); // Avoid log(0)\n                w_prime = -log(u) / lambda;\n            } while (w_prime > W_CAP);\n            weights[j] = std::max(1LL, (long long)round(w_prime));\n        }\n        particles.push_back(weights);\n    }\n}\n\nvoid filter_particles(const std::vector<int>& L, const std::vector<int>& R, char result) {\n    std::vector<std::vector<long long>> next_particles;\n    next_particles.reserve(particles.size());\n    for (const auto& p : particles) {\n        long long sum_L = 0, sum_R = 0;\n        for (int i : L) sum_L += p[i];\n        for (int i : R) sum_R += p[i];\n        \n        bool consistent = false;\n        if (result == '<' && sum_L < sum_R) consistent = true;\n        else if (result == '>' && sum_L > sum_R) consistent = true;\n        else if (result == '=' && sum_L == sum_R) consistent = true;\n        \n        if (consistent) {\n            next_particles.push_back(p);\n        }\n    }\n    if (!next_particles.empty()) {\n        particles = std::move(next_particles);\n    }\n}\n\nstd::vector<double> get_estimated_weights() {\n    std::vector<double> avg_weights(N, 0.0);\n    if (particles.empty()) {\n        for(int i=0; i<N; ++i) avg_weights[i] = 1.0;\n        return avg_weights;\n    }\n    for (int i = 0; i < N; ++i) {\n        long long total = 0;\n        for (const auto& p : particles) {\n            total += p[i];\n        }\n        avg_weights[i] = (double)total / particles.size();\n    }\n    return avg_weights;\n}\n\n// --- Main logic ---\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    Timer timer;\n\n    std::cin >> N >> D >> Q;\n    W_CAP = 1e5 * N / D;\n\n    generate_particles();\n\n    int queries_made = 0;\n\n    int num_sort_queries = std::min((int)(Q * 0.5), N * (N - 1) / 2);\n    if (N > 80 && Q > 20 * N) num_sort_queries = std::min((int)(Q * 0.3), N * (N - 1) / 2);\n\n    std::vector<std::pair<int, int>> pairs;\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            pairs.push_back({i, j});\n        }\n    }\n    std::shuffle(pairs.begin(), pairs.end(), rng);\n\n    for (int i = 0; i < num_sort_queries && i < pairs.size() && queries_made < Q; ++i) {\n        auto [u, v] = pairs[i];\n        char res = query({u}, {v});\n        filter_particles({u}, {v}, res);\n        queries_made++;\n    }\n\n    int k_cycle = 0;\n    while (queries_made < Q) {\n        auto estimated_weights = get_estimated_weights();\n        std::vector<int> p(N);\n        std::iota(p.begin(), p.end(), 0);\n        std::sort(p.begin(), p.end(), [&](int i, int j) {\n            return estimated_weights[i] < estimated_weights[j];\n        });\n\n        std::vector<double> prefix_sum_w(N, 0.0);\n        prefix_sum_w[0] = estimated_weights[p[0]];\n        for (int i = 1; i < N; ++i) {\n            prefix_sum_w[i] = prefix_sum_w[i-1] + estimated_weights[p[i]];\n        }\n        \n        int k_idx = (N - 1) - (k_cycle % (N - 1));\n        if (k_idx <= 0) k_idx = 1;\n        int item_k = p[k_idx];\n\n        auto it = std::upper_bound(prefix_sum_w.begin(), prefix_sum_w.begin() + k_idx, estimated_weights[item_k]);\n        int j_idx = std::distance(prefix_sum_w.begin(), it);\n        if (j_idx > 0 && j_idx < k_idx) {\n            if (std::abs(prefix_sum_w[j_idx] - estimated_weights[item_k]) > std::abs(prefix_sum_w[j_idx-1] - estimated_weights[item_k])) {\n                j_idx--;\n            }\n        }\n        j_idx = std::max(0, std::min(k_idx - 1, j_idx));\n        \n        std::vector<int> L = {item_k};\n        std::vector<int> R;\n        for (int i = 0; i <= j_idx; ++i) {\n            R.push_back(p[i]);\n        }\n\n        char res = query(L, R);\n        filter_particles(L, R, res);\n        queries_made++;\n        k_cycle++;\n    }\n\n    auto final_weights = get_estimated_weights();\n    std::vector<long long> scaled_weights(N);\n    double scale_factor = 1000.0;\n    for(int i=0; i<N; ++i) {\n        scaled_weights[i] = round(final_weights[i] * scale_factor);\n    }\n\n    std::vector<int> p(N);\n    std::iota(p.begin(), p.end(), 0);\n    std::sort(p.begin(), p.end(), [&](int i, int j) {\n        return scaled_weights[i] > scaled_weights[j];\n    });\n\n    std::vector<int> assignment(N);\n    using int128 = __int128_t;\n    std::vector<int128> set_sums(D, 0);\n    \n    for (int item_idx : p) {\n        int best_set = 0;\n        if (D > 0) {\n            for (int j = 1; j < D; ++j) {\n                if (set_sums[j] < set_sums[best_set]) {\n                    best_set = j;\n                }\n            }\n        }\n        assignment[item_idx] = best_set;\n        if(D > 0) set_sums[best_set] += scaled_weights[item_idx];\n    }\n    \n    std::vector<int128> current_set_sums = set_sums;\n    std::vector<int> current_assignment = assignment;\n    \n    int128 current_score = 0;\n    for(auto s : current_set_sums) current_score += s*s;\n\n    auto best_assignment = current_assignment;\n    int128 best_score = current_score;\n\n    long double start_temp = 0.0;\n    if (N > 0 && D > 1) {\n        for(int i=0; i<100; ++i) {\n            int item_idx = rng() % N;\n            int d1 = current_assignment[item_idx];\n            int d2 = (d1 + 1 + (rng() % (D-1))) % D;\n            int128 w = scaled_weights[item_idx];\n            int128 s1 = current_set_sums[d1];\n            int128 s2 = current_set_sums[d2];\n            start_temp += std::abs((long double)(2 * w * (s2 - s1 + w)));\n        }\n        start_temp /= 100;\n        if (start_temp < 1e-9) start_temp = 1.0;\n    }\n\n\n    long double end_temp = 1e-9;\n    \n    long long time_limit = 1950;\n    \n    while(D > 1 && timer.get_elapsed_ms() < time_limit) {\n        \n        long double temp = start_temp * pow(end_temp / start_temp, (long double)timer.get_elapsed_ms() / time_limit);\n        \n        if (rng() % 2 == 0) { // Move\n            int item_idx = rng() % N;\n            int d1 = current_assignment[item_idx];\n            int d2 = (d1 + 1 + (rng() % (D-1))) % D;\n\n            int128 w = scaled_weights[item_idx];\n            int128 s1 = current_set_sums[d1];\n            int128 s2 = current_set_sums[d2];\n\n            int128 new_score = current_score - s1*s1 - s2*s2 + (s1 - w)*(s1 - w) + (s2 + w)*(s2 + w);\n            \n            if (new_score < current_score || std::uniform_real_distribution<long double>(0,1)(rng) < expl((long double)(current_score - new_score) / temp)) {\n                current_assignment[item_idx] = d2;\n                current_set_sums[d1] -= w;\n                current_set_sums[d2] += w;\n                current_score = new_score;\n\n                if (current_score < best_score) {\n                    best_score = current_score;\n                    best_assignment = current_assignment;\n                }\n            }\n        } else { // Swap\n            int item1_idx = rng() % N;\n            int item2_idx;\n            do { item2_idx = rng() % N; } while (item1_idx == item2_idx);\n\n            int d1 = current_assignment[item1_idx];\n            int d2 = current_assignment[item2_idx];\n\n            if (d1 == d2) continue;\n\n            int128 w1 = scaled_weights[item1_idx];\n            int128 w2 = scaled_weights[item2_idx];\n            int128 s1 = current_set_sums[d1];\n            int128 s2 = current_set_sums[d2];\n\n            int128 new_score = current_score - s1*s1 - s2*s2 + (s1 - w1 + w2)*(s1 - w1 + w2) + (s2 - w2 + w1)*(s2 - w2 + w1);\n\n            if (new_score < current_score || std::uniform_real_distribution<long double>(0,1)(rng) < expl((long double)(current_score - new_score) / temp)) {\n                std::swap(current_assignment[item1_idx], current_assignment[item2_idx]);\n                current_set_sums[d1] = s1 - w1 + w2;\n                current_set_sums[d2] = s2 - w2 + w1;\n                current_score = new_score;\n\n                if (current_score < best_score) {\n                    best_score = current_score;\n                    best_assignment = current_assignment;\n                }\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        std::cout << best_assignment[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    std::cout << std::endl;\n\n    return 0;\n}","ahc026":"#include <iostream>\n#include <vector>\n#include <deque>\n#include <array>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n\nusing namespace std;\n\nconst int N = 200;\nconst int M = 10;\nint BEAM_WIDTH = 50; // Tunable parameter\n\nstruct State {\n    array<deque<int>, M> stacks;\n    array<pair<int, int>, N + 1> box_pos; // {stack_idx, height_from_bottom}\n    long long cost = 0;\n    double score = 0.0;\n    vector<pair<int, int>> history;\n\n    State() {\n        for(int i=0; i<=N; ++i) box_pos[i] = {-1, -1};\n    }\n    \n    double calculate_heuristic(int v_start) const {\n        double h = 0;\n        for (int v = v_start; v <= N; ++v) {\n            if (box_pos[v].first != -1) { // if not carried out\n                int stack_idx = box_pos[v].first;\n                int height = box_pos[v].second;\n                int boxes_on_top = stacks[stack_idx].size() - height - 1;\n                if (boxes_on_top > 0) {\n                    h += boxes_on_top + 1;\n                }\n            }\n        }\n        return h;\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    auto start_time = chrono::high_resolution_clock::now();\n\n    int n_in, m_in;\n    cin >> n_in >> m_in;\n\n    State initial_state;\n    for (int i = 0; i < M; ++i) {\n        initial_state.stacks[i].resize(N / M);\n        for (int j = 0; j < N / M; ++j) {\n            int b;\n            cin >> b;\n            initial_state.stacks[i][j] = b;\n            initial_state.box_pos[b] = {i, j};\n        }\n    }\n\n    vector<State> beam;\n    beam.push_back(initial_state);\n\n    for (int v_to_carry = 1; v_to_carry <= N; ++v_to_carry) {\n        auto current_time = chrono::high_resolution_clock::now();\n        double elapsed_ms = chrono::duration<double, milli>(current_time - start_time).count();\n        if (elapsed_ms > 1900) {\n            BEAM_WIDTH = 1;\n        } else if (elapsed_ms > 1800) {\n            BEAM_WIDTH = min(BEAM_WIDTH, 5);\n        } else if (elapsed_ms > 1500) {\n            BEAM_WIDTH = min(BEAM_WIDTH, 15);\n        }\n\n        vector<State> candidates;\n        candidates.reserve(beam.size() * M);\n        \n        for (const auto& s : beam) {\n            int stack_idx = s.box_pos[v_to_carry].first;\n            int height = s.box_pos[v_to_carry].second;\n            \n            if (s.stacks[stack_idx].size() - 1 == height) { // is on top\n                State next_s = s;\n                int box_v = next_s.stacks[stack_idx].back();\n                next_s.stacks[stack_idx].pop_back();\n                next_s.box_pos[box_v] = {-1, -1};\n                next_s.history.push_back({box_v, 0});\n                next_s.score = next_s.cost + next_s.calculate_heuristic(v_to_carry + 1);\n                candidates.push_back(move(next_s));\n            } else { // not on top, must move\n                int move_v = s.stacks[stack_idx][height + 1];\n                \n                int empty_stack_idx = -1;\n                for (int i = 0; i < M; ++i) {\n                    if (i != stack_idx && s.stacks[i].empty()) {\n                        empty_stack_idx = i;\n                        break;\n                    }\n                }\n                \n                vector<int> dest_options;\n                if (empty_stack_idx != -1) {\n                    dest_options.push_back(empty_stack_idx);\n                } else {\n                    for (int i = 0; i < M; ++i) {\n                        if (i != stack_idx) {\n                            dest_options.push_back(i);\n                        }\n                    }\n                }\n\n                for (int dest_idx : dest_options) {\n                    State next_s = s;\n                    \n                    auto& src_stack = next_s.stacks[stack_idx];\n                    vector<int> moved_boxes;\n                    moved_boxes.assign(src_stack.begin() + height + 1, src_stack.end());\n                    src_stack.resize(height + 1);\n                    \n                    int num_moved = moved_boxes.size();\n                    next_s.cost += num_moved + 1;\n                    next_s.history.push_back({move_v, dest_idx + 1});\n                    \n                    auto& dest_stack = next_s.stacks[dest_idx];\n                    int old_dest_size = dest_stack.size();\n                    dest_stack.insert(dest_stack.end(), moved_boxes.begin(), moved_boxes.end());\n\n                    for (size_t i = 0; i < moved_boxes.size(); ++i) {\n                        int box_id = moved_boxes[i];\n                        next_s.box_pos[box_id] = {dest_idx, (int)(old_dest_size + i)};\n                    }\n                    \n                    // Now carry out v_to_carry\n                    int box_v = next_s.stacks[stack_idx].back();\n                    next_s.stacks[stack_idx].pop_back();\n                    next_s.box_pos[box_v] = {-1, -1};\n                    next_s.history.push_back({box_v, 0});\n\n                    next_s.score = next_s.cost + next_s.calculate_heuristic(v_to_carry + 1);\n                    candidates.push_back(move(next_s));\n                }\n            }\n        }\n\n        sort(candidates.begin(), candidates.end(), [](const auto& a, const auto& b) {\n            return a.score < b.score;\n        });\n\n        beam.clear();\n        for (size_t i = 0; i < min((size_t)candidates.size(), (size_t)BEAM_WIDTH); ++i) {\n            beam.push_back(move(candidates[i]));\n        }\n    }\n    \n    const State* best_state = &beam[0];\n    for(size_t i = 1; i < beam.size(); ++i) {\n        if(beam[i].cost < best_state->cost) {\n            best_state = &beam[i];\n        }\n    }\n\n    for (const auto& op : best_state->history) {\n        cout << op.first << \" \" << op.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc027":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <functional>\n#include <list>\n#include <set>\n#include <chrono>\n#include <map>\n\n// Timer\nauto start_time = std::chrono::high_resolution_clock::now();\n\nstruct Pos {\n    short r, c;\n    bool operator<(const Pos& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n    bool operator==(const Pos& other) const {\n        return r == other.r && c == other.c;\n    }\n};\n\nint N;\nstd::vector<std::string> h_walls, v_walls;\nstd::vector<std::vector<int>> d;\nstd::vector<std::vector<std::vector<Pos>>> adj;\nstd::vector<std::vector<long long>> k;\nstd::vector<std::vector<double>> g;\n\n// Randomness\nstd::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\nvoid build_adj() {\n    adj.assign(N, std::vector<std::vector<Pos>>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (i > 0 && h_walls[i - 1][j] == '0') adj[i][j].push_back({(short)(i - 1), (short)j});\n            if (i < N - 1 && h_walls[i][j] == '0') adj[i][j].push_back({(short)(i + 1), (short)j});\n            if (j > 0 && v_walls[i][j - 1] == '0') adj[i][j].push_back({(short)i, (short)(j - 1)});\n            if (j < N - 1 && v_walls[i][j] == '0') adj[i][j].push_back({(short)i, (short)(j + 1)});\n        }\n    }\n}\n\n// Generate initial path via randomized DFS\nstd::list<Pos> tour;\nstd::vector<std::vector<bool>> visited;\n\nvoid generate_initial_path_dfs(Pos p) {\n    visited[p.r][p.c] = true;\n    tour.push_back(p);\n    \n    std::vector<Pos> neighbors = adj[p.r][p.c];\n    std::shuffle(neighbors.begin(), neighbors.end(), rng);\n    \n    for (const auto& next_p : neighbors) {\n        if (!visited[next_p.r][next_p.c]) {\n            generate_initial_path_dfs(next_p);\n            tour.push_back(p);\n        }\n    }\n}\n\nstd::string pos_to_moves(const std::list<Pos>& pos_path) {\n    std::string moves;\n    moves.reserve(pos_path.size());\n    auto it = pos_path.begin();\n    Pos current = *it;\n    ++it;\n    while (it != pos_path.end()) {\n        Pos next = *it;\n        if (next.r == current.r - 1) moves.push_back('U');\n        else if (next.r == current.r + 1) moves.push_back('D');\n        else if (next.c == current.c - 1) moves.push_back('L');\n        else moves.push_back('R');\n        current = next;\n        ++it;\n    }\n    return moves;\n}\n\ndouble calculate_g(const Pos& p) {\n    if (k[p.r][p.c] == 0) return 1e18; // Should not happen after initial path\n    return (double)d[p.r][p.c] / (k[p.r][p.c] * (k[p.r][p.c] + 1.0));\n}\n\nstruct PQ_Elem {\n    double score;\n    Pos p;\n    bool operator<(const PQ_Elem& other) const {\n        if (std::abs(score - other.score) > 1e-9) return score < other.score;\n        return p < other.p;\n    }\n};\n\nvoid solve() {\n    build_adj();\n    \n    visited.assign(N, std::vector<bool>(N, false));\n    generate_initial_path_dfs({0,0});\n    \n    k.assign(N, std::vector<long long>(N, 0));\n    std::vector<std::vector<std::list<Pos>::iterator>> pos_iters(N, std::vector<std::list<Pos>::iterator>(N));\n\n    for(auto it = tour.begin(); it != tour.end(); ++it) {\n        k[it->r][it->c]++;\n        pos_iters[it->r][it->c] = it;\n    }\n\n    g.assign(N, std::vector<double>(N));\n    std::vector<std::vector<Pos>> best_neighbor(N, std::vector<Pos>(N));\n    std::set<PQ_Elem> pq;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            g[i][j] = calculate_g({(short)i, (short)j});\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            Pos p = {(short)i, (short)j};\n            double max_g = -1.0;\n            Pos bn = {-1, -1};\n            for (const auto& neighbor : adj[i][j]) {\n                if (g[neighbor.r][neighbor.c] > max_g) {\n                    max_g = g[neighbor.r][neighbor.c];\n                    bn = neighbor;\n                }\n            }\n            best_neighbor[i][j] = bn;\n            if (bn.r != -1) {\n                pq.insert({g[i][j] + max_g, p});\n            }\n        }\n    }\n\n    int MAX_L = 100000;\n    \n    while (tour.size() + 2 <= MAX_L) {\n        auto now = std::chrono::high_resolution_clock::now();\n        if (std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time).count() > 1980) {\n            break;\n        }\n\n        if (pq.empty()) break;\n        \n        PQ_Elem top = *pq.rbegin();\n        Pos u = top.p;\n        Pos v = best_neighbor[u.r][u.c];\n\n        if(v.r == -1) {\n            pq.erase(std::prev(pq.end()));\n            continue;\n        }\n        \n        auto it_u_orig = pos_iters[u.r][u.c];\n        auto it_after_u = std::next(it_u_orig);\n        auto it_new_u = tour.insert(it_after_u, u);\n        auto it_v = tour.insert(it_new_u, v);\n        \n        pos_iters[u.r][u.c] = it_new_u;\n        pos_iters[v.r][v.c] = it_v;\n\n        k[u.r][u.c]++;\n        k[v.r][v.c]++;\n\n        std::set<Pos> to_update_pq;\n        to_update_pq.insert(u);\n        to_update_pq.insert(v);\n        for(const auto& neighbor: adj[u.r][u.c]) to_update_pq.insert(neighbor);\n        for(const auto& neighbor: adj[v.r][v.c]) to_update_pq.insert(neighbor);\n        \n        for (const auto& p : to_update_pq) {\n            Pos bn = best_neighbor[p.r][p.c];\n            if (bn.r != -1) {\n                pq.erase({g[p.r][p.c] + g[bn.r][bn.c], p});\n            }\n        }\n        \n        g[u.r][u.c] = calculate_g(u);\n        g[v.r][v.c] = calculate_g(v);\n\n        for (const auto& p : to_update_pq) {\n            double max_g = -1.0;\n            Pos bn = {-1, -1};\n            if (!adj[p.r][p.c].empty()){\n                for (const auto& neighbor : adj[p.r][p.c]) {\n                    if (g[neighbor.r][neighbor.c] > max_g) {\n                        max_g = g[neighbor.r][neighbor.c];\n                        bn = neighbor;\n                    }\n                }\n                best_neighbor[p.r][p.c] = bn;\n                if (bn.r != -1) {\n                    pq.insert({g[p.r][p.c] + max_g, p});\n                }\n            }\n        }\n    }\n\n    std::string moves = pos_to_moves(tour);\n    std::cout << moves << std::endl;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    std::cin >> N;\n    h_walls.resize(N - 1);\n    v_walls.resize(N);\n    d.assign(N, std::vector<int>(N));\n    for (int i = 0; i < N - 1; ++i) std::cin >> h_walls[i];\n    for (int i = 0; i < N; ++i) std::cin >> v_walls[i];\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            std::cin >> d[i][j];\n        }\n    }\n    \n    solve();\n    \n    return 0;\n}","ahc028":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <random>\n\nusing namespace std;\n\n// Constants are defined in problem statement\nconst int N_GRID = 15;\nconst int M_TARGETS = 200;\n\n// Global variables to hold problem input\nint start_r, start_c;\nvector<string> grid(N_GRID);\nvector<string> targets(M_TARGETS);\n\n// Precomputed data structures for efficiency\nvector<pair<int, int>> char_positions[26];\nint overlaps[M_TARGETS][M_TARGETS];\ndouble avg_transition_cost[26][26];\ndouble weights[M_TARGETS][M_TARGETS];\n\n// Random number generator for SA\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// --- Utility Functions ---\n\nint manhattan_distance(int r1, int c1, int r2, int c2) {\n    return abs(r1 - r2) + abs(c1 - c2);\n}\n\n// --- Precomputation Functions ---\n\nvoid read_input() {\n    int n_in, m_in;\n    cin >> n_in >> m_in; // Consume N, M though they are fixed\n    cin >> start_r >> start_c;\n    for (int i = 0; i < N_GRID; ++i) cin >> grid[i];\n    for (int i = 0; i < M_TARGETS; ++i) cin >> targets[i];\n}\n\nvoid precompute_char_positions() {\n    for (int i = 0; i < N_GRID; ++i) {\n        for (int j = 0; j < N_GRID; ++j) {\n            char_positions[grid[i][j] - 'A'].push_back({i, j});\n        }\n    }\n}\n\nvoid precompute_overlaps() {\n    for (int i = 0; i < M_TARGETS; ++i) {\n        for (int j = 0; j < M_TARGETS; ++j) {\n            if (i == j) continue;\n            for (int k = 4; k >= 1; --k) {\n                if (targets[i].substr(5 - k) == targets[j].substr(0, k)) {\n                    overlaps[i][j] = k;\n                    break;\n                }\n            }\n        }\n    }\n}\n\nvoid precompute_avg_transition_cost() {\n    for (int i = 0; i < 26; ++i) {\n        for (int j = 0; j < 26; ++j) {\n            if (char_positions[i].empty() || char_positions[j].empty()) continue;\n            double total_min_dist = 0;\n            for (const auto& p1 : char_positions[i]) {\n                int min_dist = 1e9;\n                for (const auto& p2 : char_positions[j]) {\n                    min_dist = min(min_dist, manhattan_distance(p1.first, p1.second, p2.first, p2.second));\n                }\n                total_min_dist += min_dist;\n            }\n            avg_transition_cost[i][j] = total_min_dist / char_positions[i].size() + 1.0;\n        }\n    }\n}\n\nvoid precompute_weights() {\n    for (int i = 0; i < M_TARGETS; ++i) {\n        for (int j = 0; j < M_TARGETS; ++j) {\n            if (i == j) continue;\n            int ov = overlaps[i][j];\n            const string& t_j = targets[j];\n            const string& t_i = targets[i];\n            \n            double cost_est = 0;\n            if (5 - ov > 0) {\n                cost_est += avg_transition_cost[t_i.back() - 'A'][t_j[ov] - 'A'];\n                for (int k = ov; k < 4; ++k) {\n                    cost_est += avg_transition_cost[t_j[k] - 'A'][t_j[k+1] - 'A'];\n                }\n            }\n            weights[i][j] = cost_est;\n        }\n    }\n}\n\n// --- Core Logic ---\n\nlong long calculate_path_cost(const vector<int>& path, vector<pair<int, int>>& move_sequence) {\n    move_sequence.clear();\n    string S = targets[path[0]];\n    for (size_t i = 1; i < path.size(); ++i) {\n        int u = path[i-1];\n        int v = path[i];\n        int ov = overlaps[u][v];\n        S += targets[v].substr(ov);\n    }\n\n    if (S.length() > 5000) return 1e18; \n\n    long long total_cost = 0;\n    int cur_r = start_r;\n    int cur_c = start_c;\n\n    for (char ch : S) {\n        int char_idx = ch - 'A';\n        int best_r = -1, best_c = -1;\n        int min_dist = 1e9;\n\n        for (const auto& pos : char_positions[char_idx]) {\n            int d = manhattan_distance(cur_r, cur_c, pos.first, pos.second);\n            if (d < min_dist) {\n                min_dist = d;\n                best_r = pos.first;\n                best_c = pos.second;\n            }\n        }\n        total_cost += min_dist + 1;\n        cur_r = best_r;\n        cur_c = best_c;\n        move_sequence.push_back({cur_r, cur_c});\n    }\n    return total_cost;\n}\n\nlong long calculate_path_cost(const vector<int>& path) {\n    vector<pair<int, int>> dummy;\n    return calculate_path_cost(path, dummy);\n}\n\nvector<int> get_initial_solution() {\n    vector<int> best_path;\n    long long min_cost = 1e18;\n\n    for (int start_node = 0; start_node < M_TARGETS; ++start_node) {\n        vector<int> path;\n        path.push_back(start_node);\n        vector<bool> visited(M_TARGETS, false);\n        visited[start_node] = true;\n        int current_node = start_node;\n\n        for (int i = 0; i < M_TARGETS - 1; ++i) {\n            int next_node = -1;\n            double min_weight = 1e18;\n            for (int j = 0; j < M_TARGETS; ++j) {\n                if (!visited[j]) {\n                    if (weights[current_node][j] < min_weight) {\n                        min_weight = weights[current_node][j];\n                        next_node = j;\n                    }\n                }\n            }\n            visited[next_node] = true;\n            path.push_back(next_node);\n            current_node = next_node;\n        }\n        \n        long long current_cost = calculate_path_cost(path);\n        if (current_cost < min_cost) {\n            min_cost = current_cost;\n            best_path = path;\n        }\n    }\n    return best_path;\n}\n\nvoid solve() {\n    auto time_start = chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_MS = 1950.0;\n\n    vector<int> current_path = get_initial_solution();\n    vector<int> best_path = current_path;\n    long long current_cost = calculate_path_cost(current_path);\n    long long best_cost = current_cost;\n\n    double start_temp = 300;\n    double end_temp = 0.1;\n    \n    while(true) {\n        auto time_now = chrono::high_resolution_clock::now();\n        double time_elapsed_ms = chrono::duration<double, milli>(time_now - time_start).count();\n        if (time_elapsed_ms > TIME_LIMIT_MS) break;\n\n        vector<int> new_path = current_path;\n        int i = uniform_int_distribution<int>(0, M_TARGETS - 1)(rng);\n        int j = uniform_int_distribution<int>(0, M_TARGETS - 1)(rng);\n        if (i == j) continue;\n        if (i > j) swap(i, j);\n        reverse(new_path.begin() + i, new_path.begin() + j + 1);\n\n        long long new_cost = calculate_path_cost(new_path);\n\n        double temp = start_temp * pow(end_temp / start_temp, time_elapsed_ms / TIME_LIMIT_MS);\n        \n        if (new_cost < current_cost ||\n            uniform_real_distribution<double>(0.0, 1.0)(rng) < exp((double)(current_cost - new_cost) / temp)) {\n            current_path = new_path;\n            current_cost = new_cost;\n        }\n\n        if (current_cost < best_cost) {\n            best_path = current_path;\n            best_cost = current_cost;\n        }\n    }\n\n    vector<pair<int, int>> final_moves;\n    calculate_path_cost(best_path, final_moves);\n    for (const auto& move : final_moves) {\n        cout << move.first << \" \" << move.second << \"\\n\";\n    }\n}\n\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    read_input();\n    precompute_char_positions();\n    precompute_overlaps();\n    precompute_avg_transition_cost();\n    precompute_weights();\n    \n    solve();\n\n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <map>\n#include <iomanip>\n\n// Constants and Typedefs\nusing namespace std;\nusing Point = pair<int, int>;\n\n// Utilities\nstruct Timer {\n    chrono::high_resolution_clock::time_point start_time;\n    Timer() {\n        start_time = chrono::high_resolution_clock::now();\n    }\n    long long get_elapsed_ms() {\n        auto end_time = chrono::high_resolution_clock::now();\n        return chrono::duration_cast<chrono::milliseconds>(end_time - start_time).count();\n    }\n};\n\n// Global random engine\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// Problem specific structures\nstruct Polyomino {\n    int id;\n    int d;\n    vector<Point> coords;\n    int max_i = 0, max_j = 0;\n};\n\nstruct Problem {\n    int N, M;\n    double epsilon;\n    vector<Polyomino> fields;\n    vector<vector<Point>> valid_placements;\n    map<vector<Point>, vector<int>> identical_shapes;\n};\n\nstruct Particle {\n    vector<Point> placements;\n    vector<vector<int>> v_grid;\n\n    Particle(int M, int N) : placements(M), v_grid(N, vector<int>(N, 0)) {}\n\n    void compute_v_grid(const Problem& prob) {\n        for (auto& row : v_grid) fill(row.begin(), row.end(), 0);\n        for (int m = 0; m < prob.M; ++m) {\n            const auto& field = prob.fields[m];\n            const auto& p = placements[m];\n            for (const auto& rel_coord : field.coords) {\n                v_grid[p.first + rel_coord.first][p.second + rel_coord.second]++;\n            }\n        }\n    }\n};\n\n// Main solver\nclass Solver {\nprivate:\n    Problem prob;\n    int num_particles;\n    vector<Particle> particles;\n    vector<double> weights;\n    vector<vector<int>> known_v;\n    Timer timer;\n    int query_count = 0;\n    \npublic:\n    Solver(int N, int M, double epsilon, const vector<Polyomino>& fields, int K)\n        : prob{N, M, epsilon, fields}, num_particles(K), known_v(N, vector<int>(N, -1)) {\n        prob.valid_placements.resize(M);\n        for (int m = 0; m < M; ++m) {\n            auto& field = prob.fields[m];\n            field.max_i = 0;\n            field.max_j = 0;\n            for(const auto& p : field.coords) {\n                field.max_i = max(field.max_i, p.first);\n                field.max_j = max(field.max_j, p.second);\n            }\n            for (int i = 0; i < N - field.max_i; ++i) {\n                for (int j = 0; j < N - field.max_j; ++j) {\n                    prob.valid_placements[m].push_back({i, j});\n                }\n            }\n        }\n        \n        for (int m = 0; m < M; ++m) {\n            vector<Point> sorted_coords = fields[m].coords;\n            sort(sorted_coords.begin(), sorted_coords.end());\n            prob.identical_shapes[sorted_coords].push_back(m);\n        }\n    }\n\n    void solve() {\n        initialize_particles();\n\n        perform_initial_queries();\n\n        while (timer.get_elapsed_ms() < 2800 && query_count < 2 * prob.N * prob.N) {\n            auto p_grid = calculate_p_grid();\n            vector<Point> uncertain_cells;\n            Point most_uncertain_cell = {-1, -1};\n            double min_dist_to_half = 1.0;\n\n            for (int i = 0; i < prob.N; ++i) {\n                for (int j = 0; j < prob.N; ++j) {\n                    if (known_v[i][j] == -1) {\n                         if (p_grid[i][j] > 0.05 && p_grid[i][j] < 0.95) {\n                            uncertain_cells.push_back({i, j});\n                            if (abs(p_grid[i][j] - 0.5) < min_dist_to_half) {\n                                min_dist_to_half = abs(p_grid[i][j] - 0.5);\n                                most_uncertain_cell = {i, j};\n                            }\n                        }\n                    }\n                }\n            }\n            \n            if (most_uncertain_cell.first == -1) {\n                break; // Converged\n            }\n\n            if (uncertain_cells.size() < prob.N) { // Phase 3: Verification\n                query_drill(most_uncertain_cell.first, most_uncertain_cell.second);\n            } else { // Phase 2: Refinement\n                int block_size = 3;\n                vector<Point> query_set;\n                for (int di = -block_size / 2; di <= block_size / 2; ++di) {\n                    for (int dj = -block_size / 2; dj <= block_size / 2; ++dj) {\n                        int ni = most_uncertain_cell.first + di;\n                        int nj = most_uncertain_cell.second + dj;\n                        if (ni >= 0 && ni < prob.N && nj >= 0 && nj < prob.N && known_v[ni][nj] == -1) {\n                           query_set.push_back({ni, nj});\n                        }\n                    }\n                }\n                if (query_set.size() >= 2) {\n                    query_divine(query_set);\n                } else {\n                    query_drill(most_uncertain_cell.first, most_uncertain_cell.second);\n                }\n            }\n\n            if (timer.get_elapsed_ms() > 2800) break;\n\n            resample_and_mutate();\n        }\n\n        make_final_guess();\n    }\n\nprivate:\n    void initialize_particles() {\n        particles.clear();\n        for (int i = 0; i < num_particles; ++i) {\n            particles.emplace_back(prob.M, prob.N);\n            for (int m = 0; m < prob.M; ++m) {\n                uniform_int_distribution<> dist(0, prob.valid_placements[m].size() - 1);\n                particles.back().placements[m] = prob.valid_placements[m][dist(rng)];\n            }\n        }\n        for (auto& p : particles) p.compute_v_grid(prob);\n        weights.assign(num_particles, 1.0 / num_particles);\n    }\n    \n    void perform_initial_queries() {\n        vector<Point> all_cells, half_i, half_j, checker;\n        for (int i = 0; i < prob.N; ++i) {\n            for (int j = 0; j < prob.N; ++j) {\n                all_cells.push_back({i, j});\n                if (i < prob.N / 2) half_i.push_back({i, j});\n                if (j < prob.N / 2) half_j.push_back({i, j});\n                if ((i + j) % 2 == 0) checker.push_back({i, j});\n            }\n        }\n        \n        vector<vector<Point>> initial_queries = {all_cells, half_i, half_j, checker};\n        for(const auto& q_set : initial_queries){\n            if (timer.get_elapsed_ms() > 2800) break;\n            if (q_set.size() >= 2) {\n                query_divine(q_set);\n                resample_and_mutate();\n            }\n        }\n    }\n\n    void query_drill(int r, int c) {\n        if (known_v[r][c] != -1) return;\n        query_count++;\n        cout << \"q 1 \" << r << \" \" << c << endl;\n        int v;\n        cin >> v;\n        known_v[r][c] = v;\n        for (int i = 0; i < num_particles; ++i) {\n            if (particles[i].v_grid[r][c] != v) {\n                weights[i] = 0;\n            }\n        }\n    }\n\n    void query_divine(const vector<Point>& S) {\n        if (S.empty()) return;\n        if (S.size() == 1) {\n            query_drill(S[0].first, S[0].second);\n            return;\n        }\n\n        query_count++;\n        cout << \"q \" << S.size();\n        for (const auto& p : S) {\n            cout << \" \" << p.first << \" \" << p.second;\n        }\n        cout << endl;\n        \n        int O;\n        cin >> O;\n        \n        int k = S.size();\n        double var = k * prob.epsilon * (1.0 - prob.epsilon);\n        double stddev = sqrt(var);\n\n        for (int i = 0; i < num_particles; ++i) {\n            if (weights[i] == 0) continue;\n            int vS = 0;\n            for (const auto& p : S) {\n                vS += particles[i].v_grid[p.first][p.second];\n            }\n            double mu = k * prob.epsilon + vS * (1.0 - 2.0 * prob.epsilon);\n            \n            double prob_density;\n            if (stddev > 1e-9) {\n                prob_density = (1.0 / (stddev * sqrt(2 * M_PI))) * exp(-0.5 * pow((O - mu) / stddev, 2));\n            } else {\n                prob_density = (abs(O - mu) < 0.5) ? 1.0 : 1e-9;\n            }\n            weights[i] *= prob_density;\n        }\n    }\n\n    void resample_and_mutate() {\n        double total_weight = accumulate(weights.begin(), weights.end(), 0.0);\n        if (total_weight < 1e-20) {\n            initialize_particles();\n            return;\n        }\n        for (double& w : weights) {\n            w /= total_weight;\n        }\n\n        vector<Particle> new_particles;\n        new_particles.reserve(num_particles);\n        \n        discrete_distribution<int> dist(weights.begin(), weights.end());\n\n        int num_random_particles = num_particles * 0.05;\n        for (int i = 0; i < num_particles - num_random_particles; ++i) {\n            new_particles.push_back(particles[dist(rng)]);\n        }\n        for (int i = 0; i < num_random_particles; ++i) {\n            new_particles.emplace_back(prob.M, prob.N);\n            for (int m = 0; m < prob.M; ++m) {\n                uniform_int_distribution<> p_dist(0, prob.valid_placements[m].size() - 1);\n                new_particles.back().placements[m] = prob.valid_placements[m][p_dist(rng)];\n            }\n        }\n        \n        uniform_real_distribution<> r_dist(0.0, 1.0);\n        for(auto& p : new_particles) {\n            for(int m = 0; m < prob.M; ++m) {\n                if(r_dist(rng) < 0.1) {\n                    if (r_dist(rng) < 0.8 && prob.valid_placements[m].size() > 1) {\n                        const auto& current_pos = p.placements[m];\n                        vector<Point> neighbors;\n                        int dr[] = {-1,1,0,0}; int dc[] = {0,0,-1,1};\n                        for(int i=0; i<4; ++i) {\n                             Point neighbor = {current_pos.first + dr[i], current_pos.second + dc[i]};\n                             if (neighbor.first >= 0 && neighbor.first <= prob.N - 1 - prob.fields[m].max_i &&\n                                 neighbor.second >= 0 && neighbor.second <= prob.N - 1 - prob.fields[m].max_j) {\n                                neighbors.push_back(neighbor);\n                            }\n                        }\n                        if(!neighbors.empty()){\n                           uniform_int_distribution<> neighbor_dist(0, neighbors.size() - 1);\n                           p.placements[m] = neighbors[neighbor_dist(rng)];\n                        }\n                    } else {\n                        uniform_int_distribution<> p_dist(0, prob.valid_placements[m].size() - 1);\n                        p.placements[m] = prob.valid_placements[m][p_dist(rng)];\n                    }\n                }\n            }\n            for(const auto& [shape_coords, indices] : prob.identical_shapes) {\n                if (indices.size() > 1 && r_dist(rng) < 0.1) {\n                    uniform_int_distribution<int> idx_dist(0, indices.size() - 1);\n                    int m1_idx = idx_dist(rng);\n                    int m2_idx = idx_dist(rng);\n                    if (m1_idx == m2_idx) continue;\n                    swap(p.placements[indices[m1_idx]], p.placements[indices[m2_idx]]);\n                }\n            }\n        }\n\n        particles = new_particles;\n        for (auto& p : particles) p.compute_v_grid(prob);\n        weights.assign(num_particles, 1.0 / num_particles);\n    }\n    \n    vector<vector<double>> calculate_p_grid() {\n        vector<vector<double>> p_grid(prob.N, vector<double>(prob.N, 0.0));\n        for (const auto& p : particles) {\n            for (int i = 0; i < prob.N; ++i) {\n                for (int j = 0; j < prob.N; ++j) {\n                    if (p.v_grid[i][j] > 0) {\n                        p_grid[i][j] += 1.0;\n                    }\n                }\n            }\n        }\n        for (int i = 0; i < prob.N; ++i) {\n            for (int j = 0; j < prob.N; ++j) {\n                p_grid[i][j] /= num_particles;\n            }\n        }\n        return p_grid;\n    }\n\n    void make_final_guess() {\n        auto p_grid = calculate_p_grid();\n        \n        vector<Point> guess;\n        for (int i = 0; i < prob.N; ++i) {\n            for (int j = 0; j < prob.N; ++j) {\n                if (known_v[i][j] != -1) {\n                    if (known_v[i][j] > 0) {\n                        guess.push_back({i, j});\n                    }\n                } else {\n                    if (p_grid[i][j] > 0.5) {\n                        guess.push_back({i, j});\n                    }\n                }\n            }\n        }\n        \n        cout << \"a \" << guess.size();\n        for (const auto& p : guess) {\n            cout << \" \" << p.first << \" \" << p.second;\n        }\n        cout << endl;\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M;\n    double epsilon;\n    cin >> N >> M >> epsilon;\n\n    vector<Polyomino> fields(M);\n    for (int i = 0; i < M; ++i) {\n        fields[i].id = i;\n        cin >> fields[i].d;\n        fields[i].coords.resize(fields[i].d);\n        for (int j = 0; j < fields[i].d; ++j) {\n            cin >> fields[i].coords[j].first >> fields[i].coords[j].second;\n        }\n    }\n    \n    int K = 2000;\n    if (N <= 12) K = 1000;\n    if (M >= 15) K = 3000;\n\n    Solver solver(N, M, epsilon, fields, K);\n    solver.solve();\n\n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n\nusing namespace std;\n\n// Constants\nconstexpr int W = 1000;\nint D, N;\n\n// Structures\nstruct Rect {\n    int r0, c0, r1, c1;\n    long long area() const {\n        return (long long)(r1 - r0) * (c1 - c0);\n    }\n};\n\nstruct Node {\n    bool is_leaf;\n    int k_min, k_max; // range of reservation indices\n    Node *left = nullptr, *right = nullptr;\n\n    // For internal nodes\n    bool is_vertical_split;\n    int split_idx;\n\n    // For leaf nodes\n    int k;\n};\n\n// Globals\nvector<vector<long long>> a;\nvector<Node> tree_nodes;\nint node_idx_counter;\nvector<Rect> current_rects;\nvector<int> split_coords;\n\nvector<vector<bool>> h_prev_exists, v_prev_exists;\nvector<vector<int>> h_curr_count, v_curr_count;\n\n// Randomness\nuint64_t xor_shift() {\n    static uint64_t x = 88172645463325252ULL;\n    x ^= x << 13;\n    x ^= x >> 7;\n    x ^= x << 17;\n    return x;\n}\n\nint rand_int(int min_val, int max_val) {\n    if (min_val > max_val) return min_val;\n    return min_val + xor_shift() % (max_val - min_val + 1);\n}\n\ndouble rand_double() {\n    return (double)xor_shift() / UINT64_MAX;\n}\n\n// Tree building\nNode* build_tree(int k_min, int k_max, const Rect& region) {\n    Node* node = &tree_nodes[node_idx_counter++];\n    node->k_min = k_min;\n    node->k_max = k_max;\n\n    if (k_max - k_min == 1) {\n        node->is_leaf = true;\n        node->k = k_min;\n        return node;\n    }\n\n    node->is_leaf = false;\n    int k_mid = k_min + (k_max - k_min) / 2;\n    \n    node->is_vertical_split = (region.c1 - region.c0 >= region.r1 - region.r0);\n    \n    Rect left_region, right_region;\n    if (node->is_vertical_split) {\n        int c_split = region.c0 + (region.c1 - region.c0) / 2;\n        left_region = {region.r0, region.c0, region.r1, c_split};\n        right_region = {region.r0, c_split, region.r1, region.c1};\n    } else {\n        int r_split = region.r0 + (region.r1 - region.r0) / 2;\n        left_region = {region.r0, region.c0, r_split, region.c1};\n        right_region = {r_split, region.c0, region.r1, region.c1};\n    }\n    \n    node->left = build_tree(k_min, k_mid, left_region);\n    node->right = build_tree(k_mid, k_max, right_region);\n    return node;\n}\n\nvoid assign_split_indices(Node* node, int& split_idx_counter) {\n    if (node->is_leaf) return;\n    node->split_idx = split_idx_counter++;\n    assign_split_indices(node->left, split_idx_counter);\n    assign_split_indices(node->right, split_idx_counter);\n}\n\n\n// Layout and cost calculations\nvoid get_rects_from_coords(Node* node, const Rect& region, const vector<int>& coords, vector<Rect>& rects_out) {\n    if (node->is_leaf) {\n        rects_out[node->k] = region;\n        return;\n    }\n\n    int coord = coords[node->split_idx];\n    Rect left_region, right_region;\n\n    if (node->is_vertical_split) {\n        left_region = {region.r0, region.c0, region.r1, coord};\n        right_region = {region.r0, coord, region.r1, region.c1};\n    } else {\n        left_region = {region.r0, region.c0, coord, region.c1};\n        right_region = {coord, region.c0, region.r1, region.c1};\n    }\n    get_rects_from_coords(node->left, left_region, coords, rects_out);\n    get_rects_from_coords(node->right, right_region, coords, rects_out);\n}\n\nvoid get_ideal_coords(Node* node, const Rect& region, int d, vector<int>& coords) {\n    if (node->is_leaf) return;\n    \n    long long total_area_left = 0;\n    for (int k = node->left->k_min; k < node->left->k_max; ++k) total_area_left += a[d][k];\n    \n    long long total_area_right = 0;\n    for (int k = node->right->k_min; k < node->right->k_max; ++k) total_area_right += a[d][k];\n\n    long long total_area_node = total_area_left + total_area_right;\n    if (total_area_node == 0) total_area_node = 1;\n\n    int coord;\n    Rect left_region, right_region;\n    if (node->is_vertical_split) {\n        coord = region.c0 + round((double)(region.c1 - region.c0) * total_area_left / total_area_node);\n        coord = clamp(coord, region.c0 + 1, region.c1 - 1);\n        left_region = {region.r0, region.c0, region.r1, coord};\n        right_region = {region.r0, coord, region.r1, region.c1};\n    } else {\n        coord = region.r0 + round((double)(region.r1 - region.r0) * total_area_left / total_area_node);\n        coord = clamp(coord, region.r0 + 1, region.r1 - 1);\n        left_region = {region.r0, region.c0, coord, region.c1};\n        right_region = {coord, region.c0, region.r1, region.c1};\n    }\n    coords[node->split_idx] = coord;\n    get_ideal_coords(node->left, left_region, d, coords);\n    get_ideal_coords(node->right, right_region, d, coords);\n}\n\nlong long calculate_area_cost(int d, const vector<Rect>& rects) {\n    long long cost = 0;\n    for (int k = 0; k < N; ++k) {\n        cost += 100 * max(0LL, a[d][k] - rects[k].area());\n    }\n    return cost;\n}\n\nvoid populate_partition_counts(const vector<Rect>& rects) {\n    for (int i=1; i<W; ++i) fill(h_curr_count[i].begin(), h_curr_count[i].end(), 0);\n    for (int i=0; i<W; ++i) fill(v_curr_count[i].begin(), v_curr_count[i].end(), 0);\n    \n    for (int k = 0; k < N; ++k) {\n        const auto& r = rects[k];\n        if (r.r0 > 0) for (int c = r.c0; c < r.c1; ++c) h_curr_count[r.r0][c]++;\n        if (r.r1 < W) for (int c = r.c0; c < r.c1; ++c) h_curr_count[r.r1][c]++;\n        if (r.c0 > 0) for (int i = r.r0; i < r.r1; ++i) v_curr_count[i][r.c0]++;\n        if (r.c1 < W) for (int i = r.r0; i < r.r1; ++i) v_curr_count[i][r.c1]++;\n    }\n}\n\nlong long calculate_partition_change_cost_full() {\n    long long cost = 0;\n    for (int i = 1; i < W; ++i) {\n        for (int j = 0; j < W; ++j) {\n            cost += (h_prev_exists[i][j] != (h_curr_count[i][j] > 0));\n        }\n    }\n    for (int i = 0; i < W; ++i) {\n        for (int j = 1; j < W; ++j) {\n            cost += (v_prev_exists[i][j] != (v_curr_count[i][j] > 0));\n        }\n    }\n    return cost;\n}\n\nvoid update_prev_partitions() {\n    for (int i = 1; i < W; ++i) {\n        for (int j = 0; j < W; ++j) {\n            h_prev_exists[i][j] = (h_curr_count[i][j] > 0);\n        }\n    }\n    for (int i = 0; i < W; ++i) {\n        for (int j = 1; j < W; ++j) {\n            v_prev_exists[i][j] = (v_curr_count[i][j] > 0);\n        }\n    }\n}\n\n// Main logic\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int W_in;\n    cin >> W_in >> D >> N; \n    a.resize(D, vector<long long>(N));\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            cin >> a[d][k];\n        }\n    }\n\n    tree_nodes.resize(2 * N);\n    node_idx_counter = 0;\n    Node* root = build_tree(0, N, {0, 0, W, W});\n    int split_idx_counter = 0;\n    assign_split_indices(root, split_idx_counter);\n\n    current_rects.resize(N);\n    split_coords.resize(N - 1);\n    \n    h_prev_exists.resize(W + 1, vector<bool>(W + 1, false));\n    v_prev_exists.resize(W + 1, vector<bool>(W + 1, false));\n    h_curr_count.resize(W + 1, vector<int>(W + 1, 0));\n    v_curr_count.resize(W + 1, vector<int>(W + 1, 0));\n\n    // Day 0\n    get_ideal_coords(root, {0, 0, W, W}, 0, split_coords);\n    get_rects_from_coords(root, {0, 0, W, W}, split_coords, current_rects);\n    populate_partition_counts(current_rects);\n    update_prev_partitions();\n\n    vector<vector<Rect>> solution(D, vector<Rect>(N));\n    solution[0] = current_rects;\n\n    auto global_start_time = chrono::high_resolution_clock::now();\n\n    // Day 1 to D-1\n    for (int d = 1; d < D; ++d) {\n        get_rects_from_coords(root, {0, 0, W, W}, split_coords, current_rects);\n        populate_partition_counts(current_rects);\n        \n        long long current_area_cost = calculate_area_cost(d, current_rects);\n        long long partition_change_cost = calculate_partition_change_cost_full();\n        long long current_total_cost = current_area_cost + partition_change_cost;\n        \n        vector<int> best_coords = split_coords;\n        long long best_total_cost = current_total_cost;\n        \n        auto day_start_time = chrono::high_resolution_clock::now();\n        double time_limit_per_day = (2950.0 - chrono::duration_cast<chrono::milliseconds>(day_start_time - global_start_time).count()) / (D - d);\n\n        double temp = 5000;\n        int iter = 0;\n        while (true) {\n            iter++;\n            if (iter % 128 == 0) {\n                 auto now = chrono::high_resolution_clock::now();\n                 double elapsed = chrono::duration_cast<chrono::milliseconds>(now - day_start_time).count();\n                 if (elapsed > time_limit_per_day) break;\n            }\n            temp *= 0.9999;\n\n            int split_to_change = rand_int(0, N - 2);\n            \n            // Find region for the split\n            Node* target_node = nullptr;\n            vector<pair<Node*, Rect>> q;\n            q.push_back({root, {0,0,W,W}});\n            Rect split_region;\n            while(!q.empty()){\n                auto [curr, region] = q.back();\n                q.pop_back();\n                if(!curr->is_leaf && curr->split_idx == split_to_change) {\n                    target_node = curr;\n                    split_region = region;\n                    break;\n                }\n                if(!curr->is_leaf){\n                    int coord = split_coords[curr->split_idx];\n                    if (curr->is_vertical_split) {\n                        q.push_back({curr->left, {region.r0, region.c0, region.r1, coord}});\n                        q.push_back({curr->right, {region.r0, coord, region.r1, region.c1}});\n                    } else {\n                        q.push_back({curr->left, {region.r0, region.c0, coord, region.c1}});\n                        q.push_back({curr->right, {coord, region.c0, region.r1, region.c1}});\n                    }\n                }\n            }\n\n            int old_coord = split_coords[split_to_change];\n            int range_min, range_max;\n            if (target_node->is_vertical_split) {\n                range_min = split_region.c0 + 1; range_max = split_region.c1 - 1;\n            } else {\n                range_min = split_region.r0 + 1; range_max = split_region.r1 - 1;\n            }\n            if (range_min >= range_max) continue;\n\n            int move_range = max(1, (int)((range_max - range_min) * 0.1 * temp / 5000.0));\n            int new_coord = old_coord + rand_int(-move_range, move_range);\n            new_coord = clamp(new_coord, range_min, range_max);\n            \n            if (new_coord == old_coord) continue;\n\n            vector<Rect> new_subtree_rects(N);\n            auto get_subtree_rects = [&](Node* n, Rect r, const vector<int>& coords) {\n                function<void(Node*, Rect)> recurse = \n                    [&](Node* node, Rect region) {\n                    if (node->is_leaf) {\n                        new_subtree_rects[node->k] = region;\n                        return;\n                    }\n                    int c = coords[node->split_idx];\n                    Rect r_left, r_right;\n                    if (node->is_vertical_split) {\n                        r_left = {region.r0, region.c0, region.r1, c}; r_right = {region.r0, c, region.r1, region.c1};\n                    } else {\n                        r_left = {region.r0, region.c0, c, region.c1}; r_right = {c, region.c0, region.r1, region.c1};\n                    }\n                    recurse(node->left, r_left);\n                    recurse(node->right, r_right);\n                };\n                recurse(n, r);\n            };\n            \n            vector<int> next_coords = split_coords;\n            next_coords[split_to_change] = new_coord;\n            get_subtree_rects(target_node, split_region, next_coords);\n\n            long long area_cost_delta = 0;\n            for(int k=target_node->k_min; k<target_node->k_max; ++k) {\n                area_cost_delta -= 100 * max(0LL, a[d][k] - current_rects[k].area());\n                area_cost_delta += 100 * max(0LL, a[d][k] - new_subtree_rects[k].area());\n            }\n\n            long long partition_cost_delta = 0;\n            if (target_node->is_vertical_split) {\n                for (int i = split_region.r0; i < split_region.r1; ++i) {\n                    partition_cost_delta -= (v_prev_exists[i][old_coord] != (v_curr_count[i][old_coord] > 0));\n                    v_curr_count[i][old_coord]--;\n                    partition_cost_delta += (v_prev_exists[i][old_coord] != (v_curr_count[i][old_coord] > 0));\n                    partition_cost_delta -= (v_prev_exists[i][new_coord] != (v_curr_count[i][new_coord] > 0));\n                    v_curr_count[i][new_coord]++;\n                    partition_cost_delta += (v_prev_exists[i][new_coord] != (v_curr_count[i][new_coord] > 0));\n                }\n            } else {\n                for (int j = split_region.c0; j < split_region.c1; ++j) {\n                    partition_cost_delta -= (h_prev_exists[old_coord][j] != (h_curr_count[old_coord][j] > 0));\n                    h_curr_count[old_coord][j]--;\n                    partition_cost_delta += (h_prev_exists[old_coord][j] != (h_curr_count[old_coord][j] > 0));\n                    partition_cost_delta -= (h_prev_exists[new_coord][j] != (h_curr_count[new_coord][j] > 0));\n                    h_curr_count[new_coord][j]++;\n                    partition_cost_delta += (h_prev_exists[new_coord][j] != (h_curr_count[new_coord][j] > 0));\n                }\n            }\n\n            long long cost_delta = area_cost_delta + partition_cost_delta;\n\n            if (cost_delta < 0 || (temp > 1 && rand_double() < exp(-(double)cost_delta / temp))) {\n                current_total_cost += cost_delta;\n                split_coords = next_coords;\n                for(int k=target_node->k_min; k<target_node->k_max; ++k) {\n                    current_rects[k] = new_subtree_rects[k];\n                }\n                \n                if (current_total_cost < best_total_cost) {\n                    best_total_cost = current_total_cost;\n                    best_coords = split_coords;\n                }\n            } else { // revert counts\n                if (target_node->is_vertical_split) {\n                    for (int i = split_region.r0; i < split_region.r1; ++i) {\n                        v_curr_count[i][old_coord]++; v_curr_count[i][new_coord]--;\n                    }\n                } else {\n                    for (int j = split_region.c0; j < split_region.c1; ++j) {\n                        h_curr_count[old_coord][j]++; h_curr_count[new_coord]--;\n                    }\n                }\n            }\n        }\n        \n        split_coords = best_coords;\n        get_rects_from_coords(root, {0, 0, W, W}, split_coords, current_rects);\n        solution[d] = current_rects;\n        populate_partition_counts(current_rects);\n        update_prev_partitions();\n    }\n\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            const auto& r = solution[d][k];\n            cout << r.r0 << \" \" << r.c0 << \" \" << r.r1 << \" \" << r.c1 << \"\\n\";\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <optional>\n#include <map>\n#include <cmath>\n#include <array>\n\n// --- Constants ---\nconstexpr int N = 9;\nconstexpr int M = 20;\nconstexpr int K = 81;\nconstexpr long long P = 998244353;\nconstexpr int MAX_POS = N - 2;\n\n// --- Type Definitions ---\nusing Board = std::vector<std::vector<long long>>;\nusing Stamp = std::vector<std::vector<long long>>;\n\nstruct Operation {\n    int m, p, q;\n};\n\n// --- Global Variables ---\nstd::vector<Stamp> stamps(M, Stamp(3, std::vector<long long>(3)));\nBoard initial_board(N, std::vector<long long>(N));\n\n// --- Randomness ---\nstd::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// --- Timer ---\nstd::chrono::steady_clock::time_point start_time;\n\n// --- Utility Functions ---\nlong long current_time_ms() {\n    return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count();\n}\n\nlong long positive_modulo(long long i, long long n) {\n    return (i % n + n) % n;\n}\n\nBoard apply_operations(const std::vector<Operation>& ops) {\n    Board current_board = initial_board;\n    for (const auto& op : ops) {\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                current_board[op.p + i][op.q + j] += stamps[op.m][i][j];\n            }\n        }\n    }\n    return current_board;\n}\n\nlong long calculate_score(const Board& board) {\n    long long score = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            score += board[i][j] % P;\n        }\n    }\n    return score;\n}\n\n\n// --- Greedy Algorithm ---\nstd::vector<Operation> greedy_solution() {\n    std::vector<Operation> ops;\n    Board current_board = initial_board;\n    \n    for (int k = 0; k < K; ++k) {\n        long long best_delta_score = 0;\n        std::optional<Operation> best_op;\n        \n        for (int m = 0; m < M; ++m) {\n            for (int p = 0; p < MAX_POS; ++p) {\n                for (int q = 0; q < MAX_POS; ++q) {\n                    long long current_delta_score = 0;\n                    for (int i = 0; i < 3; ++i) {\n                        for (int j = 0; j < 3; ++j) {\n                            long long old_val = current_board[p + i][q + j];\n                            long long new_val = old_val + stamps[m][i][j];\n                            current_delta_score += (new_val % P) - (old_val % P);\n                        }\n                    }\n                    \n                    if (current_delta_score > best_delta_score) {\n                        best_delta_score = current_delta_score;\n                        best_op = {m, p, q};\n                    }\n                }\n            }\n        }\n        \n        if (best_op) {\n            ops.push_back(*best_op);\n            for (int i = 0; i < 3; ++i) {\n                for (int j = 0; j < 3; ++j) {\n                    current_board[best_op->p + i][best_op->q + j] += stamps[best_op->m][i][j];\n                }\n            }\n        } else {\n            break; // No improvement possible\n        }\n    }\n    \n    return ops;\n}\n\n// --- Simulated Annealing ---\nvoid simulated_annealing(std::vector<Operation>& solution) {\n    long long time_limit = 1950;\n    \n    Board current_board = apply_operations(solution);\n    long long current_score = calculate_score(current_board);\n    \n    std::vector<Operation> best_solution = solution;\n    long long best_score = current_score;\n    \n    double start_temp = 3e9;\n    double end_temp = 1e4;\n\n    while (true) {\n        long long elapsed_time = current_time_ms();\n        if (elapsed_time >= time_limit) {\n            break;\n        }\n        \n        double progress = static_cast<double>(elapsed_time) / time_limit;\n        double temp = start_temp * std::pow(end_temp / start_temp, progress);\n\n        int move_type = -1; // 0: change, 1: add, 2: remove\n        if (solution.size() == K) {\n            if (solution.empty()) { // K=0\n                continue;\n            }\n            move_type = (std::uniform_int_distribution<>(0, 9)(rng) < 8) ? 0 : 2; // 80% change, 20% remove\n        } else if (solution.empty()) { // implies K > 0\n            move_type = 1;\n        } else { // 0 < size < K\n            int r = std::uniform_int_distribution<>(0, 9)(rng);\n            if (r < 8) move_type = 0;\n            else if (r < 9) move_type = 1;\n            else move_type = 2;\n        }\n        \n        std::optional<Operation> old_op, new_op;\n        int op_idx = -1;\n        \n        if (move_type == 0) { // Change\n            op_idx = std::uniform_int_distribution<int>(0, solution.size() - 1)(rng);\n            old_op = solution[op_idx];\n            new_op = {\n                std::uniform_int_distribution<int>(0, M - 1)(rng),\n                std::uniform_int_distribution<int>(0, N - 3)(rng),\n                std::uniform_int_distribution<int>(0, N - 3)(rng)\n            };\n        } else if (move_type == 1) { // Add\n            new_op = {\n                std::uniform_int_distribution<int>(0, M - 1)(rng),\n                std::uniform_int_distribution<int>(0, N - 3)(rng),\n                std::uniform_int_distribution<int>(0, N - 3)(rng)\n            };\n        } else { // Remove\n            op_idx = std::uniform_int_distribution<int>(0, solution.size() - 1)(rng);\n            old_op = solution[op_idx];\n        }\n\n        std::map<int, long long> deltas;\n        if (old_op) {\n            for (int i = 0; i < 3; ++i) {\n                for (int j = 0; j < 3; ++j) {\n                    deltas[(old_op->p + i) * N + old_op->q + j] -= stamps[old_op->m][i][j];\n                }\n            }\n        }\n        if (new_op) {\n            for (int i = 0; i < 3; ++i) {\n                for (int j = 0; j < 3; ++j) {\n                    deltas[(new_op->p + i) * N + new_op->q + j] += stamps[new_op->m][i][j];\n                }\n            }\n        }\n        \n        long long delta_score = 0;\n        for (const auto& [pos_key, change] : deltas) {\n            int r = pos_key / N;\n            int c = pos_key % N;\n            long long old_val = current_board[r][c];\n            long long new_val = old_val + change;\n            delta_score += positive_modulo(new_val, P) - (old_val % P);\n        }\n        \n        if (delta_score > 0 || std::uniform_real_distribution<>(0.0, 1.0)(rng) < std::exp(static_cast<double>(delta_score) / temp)) {\n            current_score += delta_score;\n            for (const auto& [pos_key, change] : deltas) {\n                current_board[pos_key / N][pos_key % N] += change;\n            }\n            \n            if (move_type == 0) {\n                solution[op_idx] = *new_op;\n            } else if (move_type == 1) {\n                solution.push_back(*new_op);\n            } else {\n                solution.erase(solution.begin() + op_idx);\n            }\n            \n            if (current_score > best_score) {\n                best_score = current_score;\n                best_solution = solution;\n            }\n        }\n    }\n    \n    solution = best_solution;\n}\n\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    start_time = std::chrono::steady_clock::now();\n    \n    int n_dummy, m_dummy, k_dummy;\n    std::cin >> n_dummy >> m_dummy >> k_dummy;\n    \n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            std::cin >> initial_board[i][j];\n        }\n    }\n    \n    for (int m = 0; m < M; ++m) {\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                std::cin >> stamps[m][i][j];\n            }\n        }\n    }\n    \n    auto solution = greedy_solution();\n    simulated_annealing(solution);\n    \n    std::cout << solution.size() << std::endl;\n    for (const auto& op : solution) {\n        std::cout << op.m << \" \" << op.p << \" \" << op.q << std::endl;\n    }\n    \n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <map>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nconst int N = 5;\nconst int MAX_TURNS = 10000;\n\nstruct Pos {\n    int r, c;\n    bool operator==(const Pos& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Pos& other) const {\n        return !(*this == other);\n    }\n    bool operator<(const Pos& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n};\n\nenum TaskType {\n    NONE,\n    MOVE_TO_PARK,\n    UNLOAD,\n    SORT,\n    DISPATCH\n};\n\nstruct Task {\n    TaskType type = NONE;\n    int container_id = -1;\n    Pos from;\n    Pos to;\n};\n\nstruct Crane {\n    int id;\n    Pos pos;\n    int payload = -1;\n    Task task;\n    bool bombed = false;\n};\n\nint grid[N][N];\nPos container_pos[N * N];\nCrane cranes[N];\nint arrival_idx[N];\nint dispatch_next[N];\nvector<string> history(N);\n\nvoid init() {\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            grid[i][j] = -1;\n        }\n    }\n    for (int i = 0; i < N * N; ++i) {\n        container_pos[i] = {-1, -1};\n    }\n    for (int i = 0; i < N; ++i) {\n        cranes[i].id = i;\n        cranes[i].pos = {i, 0};\n        arrival_idx[i] = 0;\n        dispatch_next[i] = N * i;\n    }\n}\n\nvoid apply_actions(const string& actions) {\n    for (int i = 0; i < N; ++i) {\n        history[i] += actions[i];\n    }\n    \n    // Update payload first\n    for (int i = 0; i < N; ++i) {\n        char act = actions[i];\n        if (act == 'P') {\n            cranes[i].payload = grid[cranes[i].pos.r][cranes[i].pos.c];\n            grid[cranes[i].pos.r][cranes[i].pos.c] = -1;\n        } else if (act == 'Q') {\n            grid[cranes[i].pos.r][cranes[i].pos.c] = cranes[i].payload;\n            container_pos[cranes[i].payload] = cranes[i].pos;\n            cranes[i].payload = -1;\n        } else if (act == 'B') {\n            cranes[i].bombed = true;\n        }\n    }\n\n    // Update positions\n    for (int i = 0; i < N; ++i) {\n        char act = actions[i];\n        if (act == 'U') cranes[i].pos.r--;\n        else if (act == 'D') cranes[i].pos.r++;\n        else if (act == 'L') cranes[i].pos.c--;\n        else if (act == 'R') cranes[i].pos.c++;\n    }\n}\n\nPos get_next_pos(Pos current, char action) {\n    if (action == 'U') return {current.r - 1, current.c};\n    if (action == 'D') return {current.r + 1, current.c};\n    if (action == 'L') return {current.r, current.c - 1};\n    if (action == 'R') return {current.r, current.c + 1};\n    return current;\n}\n\nchar get_move_action(Pos from, Pos to) {\n    if (from.r < to.r) return 'D';\n    if (from.r > to.r) return 'U';\n    if (from.c < to.c) return 'R';\n    if (from.c > to.c) return 'L';\n    return '.';\n}\n\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n_dummy;\n    cin >> n_dummy;\n    vector<vector<int>> A(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> A[i][j];\n        }\n    }\n\n    init();\n\n    int dispatched_count = 0;\n\n    for (int t = 0; t < MAX_TURNS; ++t) {\n        if (dispatched_count == N * N) break;\n\n        // 1. Containers arrive\n        for (int i = 0; i < N; ++i) {\n            if (arrival_idx[i] < N && grid[i][0] == -1) {\n                int new_container = A[i][arrival_idx[i]];\n                grid[i][0] = new_container;\n                container_pos[new_container] = {i, 0};\n                arrival_idx[i]++;\n            }\n        }\n\n        // 2. Crane actions\n        \n        // Task assignment\n        for (int i = 0; i < N; ++i) {\n            if (cranes[i].task.type != NONE && cranes[i].payload == -1 && container_pos[cranes[i].task.container_id].r == -1) {\n                 cranes[i].task.type = NONE;\n            }\n            if (cranes[i].task.type == NONE) {\n                if (i == 0) { // Large crane\n                    int c_to_dispatch = dispatch_next[0];\n                    if (c_to_dispatch < N && grid[0][N - 1] == -1 && container_pos[c_to_dispatch].r != -1) {\n                        Pos c_pos = container_pos[c_to_dispatch];\n                        if(c_pos.r == 0 && c_pos.c == 3) {\n                           cranes[i].task = {DISPATCH, c_to_dispatch, c_pos, {0, N - 1}};\n                        }\n                    }\n                    if (cranes[i].task.type == NONE) {\n                        for (int r = 0; r < N; ++r) {\n                            if (grid[r][0] != -1 && grid[r][1] == -1) {\n                                int c = grid[r][0];\n                                cranes[i].task = {UNLOAD, c, {r, 0}, {r, 1}};\n                                break;\n                            }\n                        }\n                    }\n                    if (cranes[i].task.type == NONE) {\n                        for (int r = 0; r < N; ++r) {\n                            if (grid[r][1] != -1) {\n                                int c = grid[r][1];\n                                int dest_r = c / N;\n                                if (grid[dest_r][3] == -1) {\n                                    cranes[i].task = {SORT, c, {r, 1}, {dest_r, 3}};\n                                    break;\n                                }\n                            }\n                        }\n                    }\n                } else { // Small cranes\n                    int c_to_dispatch = dispatch_next[i];\n                    if (c_to_dispatch < N * (i + 1) && grid[i][N - 1] == -1 && container_pos[c_to_dispatch].r != -1) {\n                        Pos c_pos = container_pos[c_to_dispatch];\n                        if (c_pos.r == i && c_pos.c == 3) {\n                           cranes[i].task = {DISPATCH, c_to_dispatch, c_pos, {i, N-1}};\n                        }\n                    }\n                    if (cranes[i].task.type == NONE) {\n                        if (cranes[i].pos != Pos{i, 2}) {\n                           cranes[i].task.type = MOVE_TO_PARK;\n                           cranes[i].task.to = {i,2};\n                        }\n                    }\n                }\n            }\n        }\n        \n        string actions(N, '.');\n        vector<Pos> next_pos(N);\n        for(int i=0; i<N; ++i) next_pos[i] = cranes[i].pos;\n        \n        for(int iter=0; iter<5; ++iter) { // Iteratively resolve conflicts\n            vector<Pos> current_next_pos(N);\n            for(int i=0; i<N; ++i) current_next_pos[i] = get_next_pos(cranes[i].pos, actions[i]);\n\n            string planned_actions = actions;\n\n            // --- Action planning for each crane, considering current state of others ---\n            for (int k = 0; k < N; ++k) {\n                if(cranes[k].bombed) { planned_actions[k] = '.'; continue;}\n\n                char best_action = '.';\n                Task& task = cranes[k].task;\n\n                if (t < 2 && k > 0) {\n                    best_action = 'R';\n                } else if (task.type != NONE) {\n                    if (cranes[k].payload != -1) {\n                        if (cranes[k].pos == task.to) {\n                            best_action = 'Q';\n                            task.type = NONE; \n                        } else {\n                            Pos target = task.to;\n                            if (k == 0 && cranes[k].pos.c != 1 && cranes[k].pos.c != target.c) {\n                                target = {cranes[k].pos.r, 1};\n                            } else if (k == 0 && cranes[k].pos.c == 1 && cranes[k].pos.r != target.r) {\n                                target = {target.r, 1};\n                            }\n                            best_action = get_move_action(cranes[k].pos, target);\n                        }\n                    } else {\n                        if (task.type == MOVE_TO_PARK) {\n                             if (cranes[k].pos == task.to) {\n                                task.type = NONE;\n                                best_action = '.';\n                             } else {\n                                best_action = get_move_action(cranes[k].pos, task.to);\n                             }\n                        } else if (cranes[k].pos == task.from) {\n                            if (grid[task.from.r][task.from.c] == task.container_id){\n                               best_action = 'P';\n                            } else {\n                               task.type = NONE;\n                            }\n                        } else {\n                            Pos target = task.from;\n                            if (k == 0 && cranes[k].pos.c != 1 && cranes[k].pos.c != target.c) {\n                                target = {cranes[k].pos.r, 1};\n                            } else if (k == 0 && cranes[k].pos.c == 1 && cranes[k].pos.r != target.r) {\n                                target = {target.r, 1};\n                            }\n                            best_action = get_move_action(cranes[k].pos, target);\n                        }\n                    }\n                }\n                planned_actions[k] = best_action;\n            }\n\n            // --- Conflict resolution with priorities ---\n            actions = planned_actions;\n            for(int i=0; i<N; ++i) next_pos[i] = get_next_pos(cranes[i].pos, actions[i]);\n            \n            // Evasion\n            Pos np0 = next_pos[0];\n            for (int j=1; j<N; ++j) {\n                if (np0 == cranes[j].pos && cranes[j].pos == next_pos[j]) { // Crane 0 wants to move into stationary Crane j\n                    // j must evade\n                    char original_action_j = actions[j];\n                    actions[j] = '.';\n                    Pos evade_targets[] = {{cranes[j].pos.r, 1}, {cranes[j].pos.r - 1, 2}, {cranes[j].pos.r + 1, 2}};\n                    for(const Pos& evade_pos : evade_targets) {\n                        if (evade_pos.r < 0 || evade_pos.r >= N || evade_pos.c < 0 || evade_pos.c >= N) continue;\n                        \n                        bool pos_ok = true;\n                        if (evade_pos == np0) pos_ok = false;\n                        for(int k=0; k<N; ++k) if(k!=j && evade_pos == cranes[k].pos) pos_ok = false;\n                        \n                        if(pos_ok) {\n                            actions[j] = get_move_action(cranes[j].pos, evade_pos);\n                            break;\n                        }\n                    }\n                    if (actions[j] == '.') { // could not evade\n                        actions[0] = '.'; // crane 0 waits\n                        actions[j] = original_action_j;\n                    }\n                }\n            }\n\n            for(int i=0; i<N; ++i) next_pos[i] = get_next_pos(cranes[i].pos, actions[i]);\n\n            // General collision\n            for (int i = 0; i < N; ++i) {\n                for (int j = i + 1; j < N; ++j) {\n                    if (next_pos[i] == next_pos[j] || (next_pos[i] == cranes[j].pos && next_pos[j] == cranes[i].pos)) {\n                        actions[j] = '.';\n                        next_pos[j] = cranes[j].pos;\n                    }\n                }\n            }\n\n            // Small crane payload constraints\n            for(int i=1; i<N; ++i) {\n                if (cranes[i].payload != -1) {\n                    Pos np = get_next_pos(cranes[i].pos, actions[i]);\n                    if (np.r < 0 || np.r >= N || np.c < 0 || np.c >= N) {\n                        actions[i] = '.';\n                        continue;\n                    }\n                    for(int c=0; c<N*N; ++c) {\n                        if (container_pos[c] == np) {\n                            actions[i] = '.';\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n\n        // Bomb cranes whose jobs are done\n        for(int i=1; i<N; ++i){\n            if(dispatch_next[i] >= N*(i+1) && cranes[i].payload == -1 && !cranes[i].bombed) {\n                actions[i] = 'B';\n            }\n        }\n        \n        apply_actions(actions);\n        \n        // 3. Containers are dispatched\n        for (int i = 0; i < N; ++i) {\n            if (grid[i][N - 1] != -1) {\n                int dispatched_container = grid[i][N - 1];\n                if (dispatched_container / N == i) {\n                    if (dispatch_next[i] == dispatched_container)\n                        dispatch_next[i]++;\n                }\n                grid[i][N - 1] = -1;\n                container_pos[dispatched_container] = {-1, -1};\n                dispatched_count++;\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << history[i] << endl;\n    }\n\n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <cmath>\n#include <map>\n#include <algorithm>\n#include <chrono>\n#include <random>\n\n#include <atcoder/mincostflow>\n\nusing namespace std;\n\n// --- Utilities ---\nstruct XorShift {\n    unsigned int x, y, z, w;\n    XorShift() : x(123456789), y(362436069), z(521288629), w(88675123) {}\n    unsigned int next() {\n        unsigned int t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));\n    }\n    int next_int(int upper) { return next() % upper; }\n    int next_int(int lower, int upper) { return lower + next() % (upper - lower + 1); }\n    double next_double() { return next() / 4294967295.0; }\n};\nXorShift rnd;\n\nauto start_time = chrono::steady_clock::now();\ndouble time_limit = 1.95;\n\nbool is_time_up() {\n    auto now = chrono::steady_clock::now();\n    double elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count() / 1000.0;\n    return elapsed > time_limit;\n}\n\n// --- Problem specific structures ---\nconst int N = 20;\n\nstruct Pos {\n    int r, c;\n};\n\nint manhattan_dist(const Pos& p1, const Pos& p2) {\n    return abs(p1.r - p2.r) + abs(p1.c - p2.c);\n}\n\nvector<Pos> sources, sinks;\nvector<int> source_supply, sink_demand;\n\nusing Plan = vector<vector<int>>;\n\n// --- Core Logic ---\n\nlong long calculate_tour_cost(Pos start_pos, int initial_load, const vector<pair<int, int>>& tour, vector<string>* ops = nullptr) {\n    long long cost = 0;\n    Pos current_pos = start_pos;\n    int truck_load = initial_load;\n\n    for (const auto& stop : tour) {\n        int t_idx = stop.first;\n        int amount = stop.second;\n        Pos t_pos = sinks[t_idx];\n        \n        int dist = manhattan_dist(current_pos, t_pos);\n        cost += (long long)dist * (100 + truck_load);\n\n        if (ops) {\n            int dr = t_pos.r - current_pos.r;\n            int dc = t_pos.c - current_pos.c;\n            if (dr > 0) for(int i=0; i<dr; ++i) ops->push_back(\"D\");\n            if (dr < 0) for(int i=0; i<-dr; ++i) ops->push_back(\"U\");\n            if (dc > 0) for(int i=0; i<dc; ++i) ops->push_back(\"R\");\n            if (dc < 0) for(int i=0; i<-dc; ++i) ops->push_back(\"L\");\n\n            ops->push_back(\"-\" + to_string(amount));\n        }\n\n        cost += amount;\n        truck_load -= amount;\n        current_pos = t_pos;\n    }\n    return cost;\n}\n\nvoid optimize_tour(Pos start_pos, vector<pair<int, int>>& tour) {\n    if (tour.size() <= 1) return;\n\n    auto get_tour_dist = [&](const vector<pair<int, int>>& current_tour) {\n        long long d = 0;\n        Pos current_pos = start_pos;\n        for (const auto& stop : current_tour) {\n            d += manhattan_dist(current_pos, sinks[stop.first]);\n            current_pos = sinks[stop.first];\n        }\n        return d;\n    };\n\n    for(int iter = 0; iter < 2 * tour.size() * tour.size() && iter < 200; ++iter) {\n        int i = rnd.next_int(tour.size());\n        int j = rnd.next_int(tour.size());\n        if (i == j) continue;\n        if (i > j) swap(i, j);\n\n        vector<pair<int, int>> next_tour = tour;\n        reverse(next_tour.begin() + i, next_tour.begin() + j + 1);\n\n        if (get_tour_dist(next_tour) < get_tour_dist(tour)) {\n            tour = next_tour;\n        }\n    }\n}\n\nlong long evaluate(const Plan& plan, vector<string>* ops = nullptr) {\n    if (ops) ops->clear();\n    long long total_cost = 0;\n    Pos current_pos = {0, 0};\n\n    map<int, vector<pair<int, int>>> deliveries_by_source;\n    for (size_t s_idx = 0; s_idx < sources.size(); ++s_idx) {\n        for (size_t t_idx = 0; t_idx < sinks.size(); ++t_idx) {\n            if (plan[s_idx][t_idx] > 0) {\n                deliveries_by_source[s_idx].push_back({(int)t_idx, plan[s_idx][t_idx]});\n            }\n        }\n    }\n\n    vector<int> active_sources_indices;\n    for (const auto& [s_idx, v] : deliveries_by_source) {\n        active_sources_indices.push_back(s_idx);\n    }\n    \n    while (!active_sources_indices.empty()) {\n        int best_s_idx = -1;\n        int min_dist = 1e9;\n        size_t best_vec_idx = -1;\n\n        for (size_t i = 0; i < active_sources_indices.size(); ++i) {\n            int s_idx = active_sources_indices[i];\n            int d = manhattan_dist(current_pos, sources[s_idx]);\n            if (d < min_dist) {\n                min_dist = d;\n                best_s_idx = s_idx;\n                best_vec_idx = i;\n            }\n        }\n        \n        Pos s_pos = sources[best_s_idx];\n        total_cost += (long long)manhattan_dist(current_pos, s_pos) * 100;\n        \n        if (ops) {\n            int dr = s_pos.r - current_pos.r;\n            int dc = s_pos.c - current_pos.c;\n            if (dr > 0) for(int i=0; i<dr; ++i) ops->push_back(\"D\");\n            if (dr < 0) for(int i=0; i<-dr; ++i) ops->push_back(\"U\");\n            if (dc > 0) for(int i=0; i<dc; ++i) ops->push_back(\"R\");\n            if (dc < 0) for(int i=0; i<-dc; ++i) ops->push_back(\"L\");\n        }\n        current_pos = s_pos;\n\n        int total_load_amount = 0;\n        vector<pair<int, int>> tour_stops; // {t_idx, amount}\n        for (const auto& delivery : deliveries_by_source[best_s_idx]) {\n            total_load_amount += delivery.second;\n            tour_stops.push_back(delivery);\n        }\n\n        total_cost += total_load_amount;\n        if (ops && total_load_amount > 0) {\n            ops->push_back(\"+\" + to_string(total_load_amount));\n        }\n        \n        Pos tour_start_pos = current_pos;\n        vector<pair<int, int>> tour;\n        while (!tour_stops.empty()) {\n            auto best_it = tour_stops.end();\n            int min_dist_t = 1e9;\n            for (auto it = tour_stops.begin(); it != tour_stops.end(); ++it) {\n                int t_idx = it->first;\n                int d = manhattan_dist(current_pos, sinks[t_idx]);\n                if (d < min_dist_t) {\n                    min_dist_t = d;\n                    best_it = it;\n                }\n            }\n            tour.push_back(*best_it);\n            current_pos = sinks[best_it->first];\n            tour_stops.erase(best_it);\n        }\n\n        optimize_tour(tour_start_pos, tour);\n\n        total_cost += calculate_tour_cost(tour_start_pos, total_load_amount, tour, ops);\n        if (!tour.empty()) {\n            current_pos = sinks[tour.back().first];\n        }\n\n        active_sources_indices.erase(active_sources_indices.begin() + best_vec_idx);\n    }\n    return total_cost;\n}\n\nvoid solve() {\n    vector<vector<int>> h(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> h[i][j];\n            if (h[i][j] > 0) {\n                sources.push_back({i, j});\n                source_supply.push_back(h[i][j]);\n            } else if (h[i][j] < 0) {\n                sinks.push_back({i, j});\n                sink_demand.push_back(-h[i][j]);\n            }\n        }\n    }\n    \n    if (sources.empty()) return;\n\n    int num_s = sources.size();\n    int num_t = sinks.size();\n    atcoder::mcf_graph<int, int> g(num_s + num_t + 2);\n    int S_node = num_s + num_t;\n    int T_node = S_node + 1;\n\n    long long total_supply_val = 0;\n    for (int i = 0; i < num_s; ++i) {\n        g.add_edge(S_node, i, source_supply[i], 0);\n        total_supply_val += source_supply[i];\n    }\n    for (int i = 0; i < num_t; ++i) {\n        g.add_edge(num_s + i, T_node, sink_demand[i], 0);\n    }\n    for (int i = 0; i < num_s; ++i) {\n        for (int j = 0; j < num_t; ++j) {\n            g.add_edge(i, num_s + j, 1e9, manhattan_dist(sources[i], sinks[j]));\n        }\n    }\n    \n    g.flow(S_node, T_node, total_supply_val);\n    \n    Plan current_plan(num_s, vector<int>(num_t, 0));\n    for (const auto& e : g.edges()) {\n        if (e.from >= 0 && e.from < num_s && e.to >= num_s && e.to < num_s + num_t) {\n            if (e.flow > 0) {\n                current_plan[e.from][e.to-num_s] = e.flow;\n            }\n        }\n    }\n\n    Plan best_plan = current_plan;\n    long long best_cost = evaluate(best_plan);\n    long long current_cost = best_cost;\n    \n    double start_temp = 5000, end_temp = 10;\n    \n    while (!is_time_up()) {\n        double elapsed_ratio = chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count() / 1000.0 / time_limit;\n        double temp = start_temp * pow(end_temp / start_temp, elapsed_ratio);\n\n        int s1 = rnd.next_int(num_s);\n        int s2 = rnd.next_int(num_s);\n        int t1 = rnd.next_int(num_t);\n        int t2 = rnd.next_int(num_t);\n\n        if (s1 == s2 || t1 == t2) continue;\n        \n        int amount1 = current_plan[s1][t1];\n        int amount2 = current_plan[s2][t2];\n        if (amount1 == 0 || amount2 == 0) continue;\n        \n        int d = rnd.next_int(1, min(amount1, amount2));\n        \n        Plan new_plan = current_plan;\n        new_plan[s1][t1] -= d;\n        new_plan[s2][t2] -= d;\n        new_plan[s1][t2] += d;\n        new_plan[s2][t1] += d;\n\n        long long new_cost = evaluate(new_plan);\n        \n        if (new_cost < current_cost || rnd.next_double() < exp((double)(current_cost - new_cost) / temp)) {\n            current_plan = new_plan;\n            current_cost = new_cost;\n            if (current_cost < best_cost) {\n                best_cost = current_cost;\n                best_plan = current_plan;\n            }\n        }\n    }\n    \n    vector<string> ops;\n    evaluate(best_plan, &ops);\n    for (const auto& op : ops) {\n        cout << op << '\\n';\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    int N_dummy;\n    cin >> N_dummy;\n    solve();\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n#include <random>\n\n// --- Constants ---\nconstexpr int N = 6;\nconstexpr int M = 15;\nconstexpr int T = 10;\nconstexpr int SEED_COUNT = 2 * N * (N - 1); // 60\nconstexpr int GRID_SIZE = N * N;             // 36\nconstexpr long long TIME_LIMIT_MS = 190;\n\n// --- Type Definitions ---\nstruct Seed {\n    int id;\n    std::vector<int> x;\n    int total_value;\n    double score;\n};\n\n// --- Global State ---\nstd::vector<Seed> current_seeds;\nstd::mt19937 rng;\nauto turn_start_time = std::chrono::high_resolution_clock::now();\n\n// --- Helper Functions ---\nvoid read_seeds() {\n    current_seeds.assign(SEED_COUNT, Seed());\n    for (int i = 0; i < SEED_COUNT; ++i) {\n        current_seeds[i].id = i;\n        current_seeds[i].x.resize(M);\n        current_seeds[i].total_value = 0;\n        for (int j = 0; j < M; ++j) {\n            std::cin >> current_seeds[i].x[j];\n            current_seeds[i].total_value += current_seeds[i].x[j];\n        }\n    }\n}\n\n// --- Core Logic for a Single Turn ---\nvoid solve_turn() {\n    // 1. SEED SELECTION\n    std::vector<int> champion_counts(SEED_COUNT, 0);\n    for (int j = 0; j < M; ++j) {\n        int best_seed_idx = -1;\n        int max_val = -1;\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            if (current_seeds[i].x[j] > max_val) {\n                max_val = current_seeds[i].x[j];\n                best_seed_idx = i;\n            }\n        }\n        if (best_seed_idx != -1) champion_counts[best_seed_idx]++;\n    }\n\n    for (int i = 0; i < SEED_COUNT; ++i) {\n        current_seeds[i].score = current_seeds[i].total_value + 50.0 * champion_counts[i];\n    }\n\n    std::vector<int> all_indices(SEED_COUNT);\n    std::iota(all_indices.begin(), all_indices.end(), 0);\n    std::sort(all_indices.begin(), all_indices.end(), [&](int a, int b) {\n        return current_seeds[a].score > current_seeds[b].score;\n    });\n\n    std::vector<int> seeds_to_plant_ids;\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        seeds_to_plant_ids.push_back(all_indices[i]);\n    }\n\n    // 2. PLACEMENT using SIMULATED ANNEALING\n    std::vector<std::vector<double>> desirability_cache(GRID_SIZE, std::vector<double>(GRID_SIZE));\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = i; j < GRID_SIZE; ++j) {\n            int id1 = seeds_to_plant_ids[i];\n            int id2 = seeds_to_plant_ids[j];\n            double d = 0;\n            for (int k = 0; k < M; ++k) {\n                d += std::max(current_seeds[id1].x[k], current_seeds[id2].x[k]);\n            }\n            desirability_cache[i][j] = desirability_cache[j][i] = d;\n        }\n    }\n\n    std::vector<std::vector<int>> current_placement(N, std::vector<int>(N));\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        current_placement[i / N][i % N] = i; // Store indices 0..35\n    }\n\n    auto calculate_total_desirability = [&](const auto& placement) {\n        double total_d = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (i + 1 < N) total_d += desirability_cache[placement[i][j]][placement[i + 1][j]];\n                if (j + 1 < N) total_d += desirability_cache[placement[i][j]][placement[i][j + 1]];\n            }\n        }\n        return total_d;\n    };\n    \n    double current_desirability = calculate_total_desirability(current_placement);\n    auto best_placement = current_placement;\n    double best_desirability = current_desirability;\n    \n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n\n    auto calculate_delta = [&](int r1, int c1, int r2, int c2) {\n        double delta = 0;\n        int s1_idx = current_placement[r1][c1];\n        int s2_idx = current_placement[r2][c2];\n\n        for (int k=0; k<4; ++k) {\n            int nr = r1 + dr[k], nc = c1 + dc[k];\n            if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n            if (nr == r2 && nc == c2) continue;\n            int neighbor_idx = current_placement[nr][nc];\n            delta += desirability_cache[s2_idx][neighbor_idx] - desirability_cache[s1_idx][neighbor_idx];\n        }\n        for (int k=0; k<4; ++k) {\n            int nr = r2 + dr[k], nc = c2 + dc[k];\n            if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n            if (nr == r1 && nc == c1) continue;\n            int neighbor_idx = current_placement[nr][nc];\n            delta += desirability_cache[s1_idx][neighbor_idx] - desirability_cache[s2_idx][neighbor_idx];\n        }\n        return delta;\n    };\n\n    double T_start = 2000.0, T_end = 0.1;\n    double avg_bad_delta = 0;\n    int bad_move_count = 0;\n    std::uniform_int_distribution<> dis_pos(0, GRID_SIZE - 1);\n    for (int i = 0; i < 100; ++i) {\n        int p1_idx = dis_pos(rng), p2_idx = dis_pos(rng);\n        if (p1_idx == p2_idx) continue;\n        double delta = calculate_delta(p1_idx / N, p1_idx % N, p2_idx / N, p2_idx % N);\n        if (delta < 0) {\n            avg_bad_delta += -delta;\n            bad_move_count++;\n        }\n    }\n    if (bad_move_count > 0) {\n        avg_bad_delta /= bad_move_count;\n        T_start = avg_bad_delta / log(2.0);\n    }\n\n    std::uniform_real_distribution<double> accept_dis(0.0, 1.0);\n    while (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - turn_start_time).count() < TIME_LIMIT_MS) {\n        double progress = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - turn_start_time).count() / (double)TIME_LIMIT_MS;\n        if (progress >= 1.0) break;\n        double temp = T_start * std::pow(T_end / T_start, progress);\n\n        int p1_idx = dis_pos(rng), p2_idx = dis_pos(rng);\n        if (p1_idx == p2_idx) continue;\n\n        int r1 = p1_idx / N, c1 = p1_idx % N;\n        int r2 = p2_idx / N, c2 = p2_idx % N;\n        \n        double delta_desirability = calculate_delta(r1, c1, r2, c2);\n        \n        if (delta_desirability > 0 || (temp > 1e-9 && accept_dis(rng) < std::exp(delta_desirability / temp))) {\n            std::swap(current_placement[r1][c1], current_placement[r2][c2]);\n            current_desirability += delta_desirability;\n            if (current_desirability > best_desirability) {\n                best_desirability = current_desirability;\n                best_placement = current_placement;\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            std::cout << seeds_to_plant_ids[best_placement[i][j]] << (j == N - 1 ? \"\" : \" \");\n        }\n        std::cout << std::endl;\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    rng.seed(std::chrono::steady_clock::now().time_since_epoch().count());\n    \n    int n_in, m_in, t_in;\n    std::cin >> n_in >> m_in >> t_in;\n\n    read_seeds();\n\n    for (int t = 0; t < T; ++t) {\n        turn_start_time = std::chrono::high_resolution_clock::now();\n        solve_turn();\n        if (t < T - 1) {\n            read_seeds();\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <set>\n#include <map>\n#include <tuple>\n#include <chrono>\n\n#include <atcoder/mincostflow>\n\nusing namespace std;\n\n// --- Utilities ---\nstruct Timer {\n    chrono::steady_clock::time_point start_time;\n    Timer() {\n        start_time = chrono::steady_clock::now();\n    }\n    double get_elapsed_time() {\n        auto end_time = chrono::steady_clock::now();\n        return chrono::duration_cast<chrono::duration<double>>(end_time - start_time).count();\n    }\n};\n\nstruct Point {\n    int r, c;\n    bool operator<(const Point& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n    bool operator==(const Point& other) const {\n        return r == other.r && c == other.c;\n    }\n};\n\nPoint operator+(const Point& a, const Point& b) { return {a.r + b.r, a.c + b.c}; }\nPoint operator-(const Point& a, const Point& b) { return {a.r - b.r, a.c - b.c}; }\nint manhattan(const Point& a, const Point& b) { return abs(a.r - b.r) + abs(a.c - b.c); }\n\nconst int dr[] = {-1, 0, 1, 0}; // U, R, D, L\nconst int dc[] = {0, 1, 0, -1};\nconst char move_chars[] = {'U', 'R', 'D', 'L'};\nconst Point REL_DIRS[] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; // 0:R, 1:D, 2:L, 3:U\n\nint N, M, V;\n\n// --- Arm Structure ---\nstruct Arm {\n    int v_count;\n    Point root_pos;\n    vector<int> parent;\n    vector<int> length;\n    vector<vector<int>> children;\n    vector<int> is_leaf;\n\n    vector<int> edge_dir;\n    vector<Point> abs_pos;\n    \n    vector<int> finger_indices;\n\n    Arm(int v, Point root, const vector<pair<int, int>>& edges) : v_count(v), root_pos(root) {\n        parent.assign(v, -1);\n        length.assign(v, 0);\n        children.assign(v, vector<int>());\n        edge_dir.assign(v, 0); // All edges point right initially\n        abs_pos.resize(v);\n        is_leaf.assign(v, 0);\n\n        for(int i = 1; i < v; ++i) {\n            parent[i] = edges[i-1].first;\n            length[i] = edges[i-1].second;\n            children[parent[i]].push_back(i);\n        }\n\n        for (int i = 0; i < v; ++i) {\n            if (children[i].empty()) {\n                is_leaf[i] = 1;\n                finger_indices.push_back(i);\n            }\n        }\n        update_abs_pos();\n    }\n\n    void update_abs_pos() {\n        abs_pos.resize(v_count);\n        abs_pos[0] = root_pos;\n        vector<int> q;\n        q.push_back(0);\n        int q_ptr = 0;\n        while(q_ptr < (int)q.size()){\n            int u = q[q_ptr++];\n            for(int v : children[u]){\n                Point rel = {REL_DIRS[edge_dir[v]].r * length[v], REL_DIRS[edge_dir[v]].c * length[v]};\n                abs_pos[v] = abs_pos[u] + rel;\n                q.push_back(v);\n            }\n        }\n    }\n    \n    void apply_command(const string& cmd) {\n        if (cmd[0] == 'U') root_pos.r--;\n        else if (cmd[0] == 'D') root_pos.r++;\n        else if (cmd[0] == 'L') root_pos.c--;\n        else if (cmd[0] == 'R') root_pos.c++;\n\n        for (int i = 1; i < v_count; ++i) {\n            if (cmd[i] == 'L') edge_dir[i] = (edge_dir[i] + 3) % 4;\n            else if (cmd[i] == 'R') edge_dir[i] = (edge_dir[i] + 1) % 4;\n        }\n        update_abs_pos();\n    }\n};\n\n// --- Game State ---\nstruct GameState {\n    Arm arm;\n    set<Point> sources_left;\n    set<Point> targets_to_fill;\n    map<int, Point> held_by_finger; // finger_idx -> original_source_pos\n    map<Point, Point> s_to_t_map;\n\n    GameState(Arm a, set<Point> s, set<Point> t, map<Point, Point> st_map)\n        : arm(a), sources_left(s), targets_to_fill(t), s_to_t_map(st_map) {}\n};\n\nstruct TargetConfig {\n    bool is_pickup;\n    Point root_pos;\n    vector<int> edge_dirs;\n    map<int, Point> finger_assignments;\n    double value = -1e18;\n};\n\n// --- Planning Functions ---\nTargetConfig find_best_config(const GameState& state, bool is_pickup) {\n    TargetConfig best_config;\n    best_config.is_pickup = is_pickup;\n\n    vector<int> available_fingers;\n    if (is_pickup) {\n        for (int f_idx : state.arm.finger_indices) {\n            if (state.held_by_finger.find(f_idx) == state.held_by_finger.end()) {\n                available_fingers.push_back(f_idx);\n            }\n        }\n        if (available_fingers.empty() || state.sources_left.empty()) return best_config;\n\n        for (const Point& p_anchor : state.sources_left) {\n            for (int f_anchor_idx : available_fingers) {\n                if (state.arm.parent[f_anchor_idx] != 0) continue;\n                for (int dir = 0; dir < 4; ++dir) {\n                    Point root_rel = {REL_DIRS[dir].r * state.arm.length[f_anchor_idx], REL_DIRS[dir].c * state.arm.length[f_anchor_idx]};\n                    Point cand_root_pos = p_anchor - root_rel;\n\n                    map<int, Point> assignments;\n                    vector<int> cand_dirs(state.arm.v_count);\n                    \n                    set<Point> remaining_sources = state.sources_left;\n                    vector<int> remaining_fingers;\n                    for(int f : available_fingers) remaining_fingers.push_back(f);\n                    \n                    int current_score = 0;\n\n                    for(int f_idx : remaining_fingers) {\n                        for(int f_dir = 0; f_dir < 4; ++f_dir) {\n                            Point f_rel = {REL_DIRS[f_dir].r * state.arm.length[f_idx], REL_DIRS[f_dir].c * state.arm.length[f_idx]};\n                            Point f_pos = cand_root_pos + f_rel;\n                            if (remaining_sources.count(f_pos)) {\n                                assignments[f_idx] = f_pos;\n                                cand_dirs[f_idx] = f_dir;\n                                remaining_sources.erase(f_pos);\n                                current_score++;\n                                break;\n                            }\n                        }\n                    }\n\n                    int dist_cost = manhattan(state.arm.root_pos, cand_root_pos);\n                    double value = current_score * 100.0 - dist_cost;\n\n                    if (value > best_config.value) {\n                        best_config.value = value;\n                        best_config.root_pos = cand_root_pos;\n                        best_config.edge_dirs = cand_dirs;\n                        best_config.finger_assignments = assignments;\n                    }\n                }\n            }\n        }\n    } else { // dropoff\n        map<int, Point> finger_to_dest;\n        for (const auto& [f_idx, s_pos] : state.held_by_finger) {\n            available_fingers.push_back(f_idx);\n            finger_to_dest[f_idx] = state.s_to_t_map.at(s_pos);\n        }\n        if (available_fingers.empty()) return best_config;\n        \n        for (int f_anchor_idx : available_fingers) {\n            const Point& p_anchor = finger_to_dest.at(f_anchor_idx);\n            if (state.arm.parent[f_anchor_idx] != 0) continue;\n\n            for (int dir = 0; dir < 4; ++dir) {\n                Point root_rel = {REL_DIRS[dir].r * state.arm.length[f_anchor_idx], REL_DIRS[dir].c * state.arm.length[f_anchor_idx]};\n                Point cand_root_pos = p_anchor - root_rel;\n\n                vector<int> cand_dirs(state.arm.v_count);\n                map<int, Point> assignments;\n                \n                int current_score = 0;\n                for(auto const& [f_idx, dest_pos] : finger_to_dest) {\n                    for (int f_dir = 0; f_dir < 4; ++f_dir) {\n                        Point f_rel = {REL_DIRS[f_dir].r * state.arm.length[f_idx], REL_DIRS[f_dir].c * state.arm.length[f_idx]};\n                        if (cand_root_pos + f_rel == dest_pos) {\n                            cand_dirs[f_idx] = f_dir;\n                            assignments[f_idx] = dest_pos;\n                            current_score++;\n                            break;\n                        }\n                    }\n                }\n\n                int dist_cost = manhattan(state.arm.root_pos, cand_root_pos);\n                double value = current_score * 100.0 - dist_cost;\n                if (value > best_config.value) {\n                    best_config.value = value;\n                    best_config.root_pos = cand_root_pos;\n                    best_config.edge_dirs = cand_dirs;\n                    best_config.finger_assignments = assignments;\n                }\n            }\n        }\n    }\n    return best_config;\n}\n\nstring get_next_command(const GameState& state, const TargetConfig& target) {\n    Arm current_arm = state.arm;\n    string command(2 * state.arm.v_count, '.');\n\n    if (current_arm.root_pos == target.root_pos && current_arm.edge_dir == target.edge_dirs) {\n        for (auto const& [f_idx, _] : target.finger_assignments) {\n            command[current_arm.v_count + f_idx] = 'P';\n        }\n        return command;\n    }\n\n    char best_move_c = '.';\n    int min_dist = manhattan(current_arm.root_pos, target.root_pos);\n    Point next_root_pos = current_arm.root_pos;\n    if (min_dist > 0) {\n        for (int i = 0; i < 4; ++i) { // U,R,D,L -> maps to dr/dc indices\n            Point new_pos = {current_arm.root_pos.r + DIRS[i].r, current_arm.root_pos.c + DIRS[i].c};\n            if (new_pos.r >= 0 && new_pos.r < N && new_pos.c >= 0 && new_pos.c < N) {\n                if (manhattan(new_pos, target.root_pos) < min_dist) {\n                    min_dist = manhattan(new_pos, target.root_pos);\n                    best_move_c = \"URDL\"[i];\n                    next_root_pos = new_pos;\n                }\n            }\n        }\n    }\n    command[0] = best_move_c;\n\n    for (int i = 1; i < current_arm.v_count; ++i) {\n        if (current_arm.parent[i] != 0) continue;\n        \n        Point finger_target_pos = target.root_pos;\n        Point finger_rel = {REL_DIRS[target.edge_dirs[i]].r * current_arm.length[i], REL_DIRS[target.edge_dirs[i]].c * current_arm.length[i]};\n        finger_target_pos = finger_target_pos + finger_rel;\n\n        char best_rot_c = '.';\n        int best_rot_dist = -1;\n\n        Point cur_rel = {REL_DIRS[current_arm.edge_dir[i]].r * current_arm.length[i], REL_DIRS[current_arm.edge_dir[i]].c * current_arm.length[i]};\n        best_rot_dist = manhattan(next_root_pos + cur_rel, finger_target_pos);\n        \n        int l_dir = (current_arm.edge_dir[i] + 3) % 4;\n        Point l_rel = {REL_DIRS[l_dir].r * current_arm.length[i], REL_DIRS[l_dir].c * current_arm.length[i]};\n        if (manhattan(next_root_pos + l_rel, finger_target_pos) < best_rot_dist) {\n            best_rot_dist = manhattan(next_root_pos + l_rel, finger_target_pos);\n            best_rot_c = 'L';\n        }\n\n        int r_dir = (current_arm.edge_dir[i] + 1) % 4;\n        Point r_rel = {REL_DIRS[r_dir].r * current_arm.length[i], REL_DIRS[r_dir].c * current_arm.length[i]};\n        if (manhattan(next_root_pos + r_rel, finger_target_pos) < best_rot_dist) {\n            best_rot_c = 'R';\n        }\n        command[i] = best_rot_c;\n    }\n    return command;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    Timer timer;\n    cin >> N >> M >> V;\n    set<Point> sources, targets;\n    for (int i = 0; i < N; ++i) {\n        string row; cin >> row;\n        for (int j = 0; j < N; ++j) if (row[j] == '1') sources.insert({i, j});\n    }\n    for (int i = 0; i < N; ++i) {\n        string row; cin >> row;\n        for (int j = 0; j < N; ++j) if (row[j] == '1') targets.insert({i, j});\n    }\n\n    // --- Arm Design ---\n    int v_to_use = V;\n    vector<pair<int, int>> edges;\n    int arm_L = max(1, (int)round(N / 8.0));\n    for (int i = 1; i < v_to_use; ++i) edges.push_back({0, arm_L});\n    \n    long long sum_r = 0, sum_c = 0; for(const auto& p : sources) { sum_r += p.r; sum_c += p.c; }\n    Point initial_root = {(int)(sum_r/M), (int)(sum_c/M)};\n    \n    cout << v_to_use << endl;\n    for (const auto& edge : edges) cout << edge.first << \" \" << edge.second << endl;\n    cout << initial_root.r << \" \" << initial_root.c << endl;\n\n    // --- Initial Planning (Matching) ---\n    map<Point, Point> s_to_t_map;\n    vector<Point> s_vec(sources.begin(), sources.end());\n    vector<Point> t_vec(targets.begin(), targets.end());\n    atcoder::mcf_graph<int, int> g(2 * M + 2);\n    int S_node = 2 * M, T_node = 2 * M + 1;\n    for (int i = 0; i < M; ++i) {\n        g.add_edge(S_node, i, 1, 0);\n        g.add_edge(M + i, T_node, 1, 0);\n        for (int j = 0; j < M; ++j) g.add_edge(i, M + j, 1, manhattan(s_vec[i], t_vec[j]));\n    }\n    g.flow(S_node, T_node, M);\n    for (auto e : g.edges()) {\n        if (e.from < M && e.to >= M && e.to < 2*M && e.flow > 0) s_to_t_map[s_vec[e.from]] = t_vec[e.to - M];\n    }\n\n    // --- Main Loop ---\n    Arm arm(v_to_use, initial_root, edges);\n    GameState state(arm, sources, targets, s_to_t_map);\n    \n    TargetConfig current_target;\n    int plan_life = 0;\n\n    int max_turns = 100000;\n    for (int turn = 0; turn < max_turns; ++turn) {\n        if (state.targets_to_fill.empty() || timer.get_elapsed_time() > 2.9) break;\n\n        if (plan_life <= 0) {\n            TargetConfig pickup_config = find_best_config(state, true);\n            TargetConfig dropoff_config = find_best_config(state, false);\n\n            if (pickup_config.value > -1e17 || dropoff_config.value > -1e17) {\n                 if (pickup_config.value >= dropoff_config.value) current_target = pickup_config;\n                 else current_target = dropoff_config;\n                 plan_life = manhattan(state.arm.root_pos, current_target.root_pos) + 5;\n            } else { // Fallback\n                string cmd(2 * V, '.'); cout << cmd << endl; state.arm.apply_command(cmd); continue;\n            }\n        }\n        \n        string command = get_next_command(state, current_target);\n        state.arm.apply_command(command);\n        \n        bool action_taken = false;\n        for (int i = 0; i < V; ++i) {\n            if (command[V + i] == 'P') {\n                action_taken = true;\n                if (current_target.is_pickup) {\n                    Point s_pos = state.arm.abs_pos[i];\n                    state.sources_left.erase(s_pos);\n                    state.held_by_finger[i] = s_pos;\n                } else {\n                    Point s_pos = state.held_by_finger.at(i);\n                    state.targets_to_fill.erase(state.s_to_t_map.at(s_pos));\n                    state.held_by_finger.erase(i);\n                }\n            }\n        }\n        if(action_taken) plan_life = 0; else plan_life--;\n\n        cout << command << endl;\n    }\n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n#include <random>\n#include <set>\n#include <map>\n#include <queue>\n\n// --- Utilities ---\nstruct Point {\n    int x, y;\n    bool operator<(const Point& other) const {\n        if (x != other.x) return x < other.x;\n        return y < other.y;\n    }\n     bool operator==(const Point& other) const {\n        return x == other.x && y == other.y;\n    }\n};\n\nlong long cross_product(Point a, Point b, Point c) {\n    return (long long)(b.x - a.x) * (c.y - a.y) - (long long)(b.y - a.y) * (c.x - a.x);\n}\n\n// Global timer\nstd::chrono::high_resolution_clock::time_point start_time;\n\n// --- Polygon Utilities ---\nstruct Polygon {\n    std::vector<Point> vertices;\n\n    bool is_inside(Point p) const {\n        if (vertices.empty()) return false;\n        int n = vertices.size();\n        bool inside = false;\n        for (int i = 0; i < n; ++i) {\n            const Point& p1 = vertices[i];\n            const Point& p2 = vertices[(i + 1) % n];\n\n            if (p1.y == p2.y && p.y == p1.y && p.x >= std::min(p1.x, p2.x) && p.x <= std::max(p1.x, p2.x)) {\n                return true;\n            }\n            if (p1.x == p2.x && p.x == p1.x && p.y >= std::min(p1.y, p2.y) && p.y <= std::max(p1.y, p2.y)) {\n                return true;\n            }\n\n            if ((p1.y > p.y) != (p2.y > p.y)) {\n                double intersect_x = (double)(p2.x - p1.x) * (p.y - p1.y) / (double)(p2.y - p1.y) + p1.x;\n                if (p.x < intersect_x) {\n                    inside = !inside;\n                }\n            }\n        }\n        return inside;\n    }\n\n    long long calculate_perimeter() const {\n        if (vertices.size() < 2) return 0;\n        long long p = 0;\n        for (size_t i = 0; i < vertices.size(); ++i) {\n            const auto& v1 = vertices[i];\n            const auto& v2 = vertices[(i + 1) % vertices.size()];\n            p += std::abs(v1.x - v2.x) + std::abs(v1.y - v2.y);\n        }\n        return p;\n    }\n};\n\n// --- Problem Data ---\nint N;\nstd::vector<Point> mackerels;\nstd::vector<Point> sardines;\n\n// --- Main Algorithm ---\n\nusing GridPoint = std::pair<int, int>;\n\nconst int DX[] = {0, 1, 0, -1};\nconst int DY[] = {1, 0, -1, 0};\n\nPolygon generate_polygon_from_cells(const std::set<GridPoint>& cells, int cell_size) {\n    if (cells.empty()) {\n        return Polygon{};\n    }\n\n    std::map<Point, std::vector<Point>> adj;\n    for (const auto& cell : cells) {\n        int gx = cell.first;\n        int gy = cell.second;\n        Point corners[] = {\n            {gx * cell_size, gy * cell_size},\n            {(gx + 1) * cell_size, gy * cell_size},\n            {(gx + 1) * cell_size, (gy + 1) * cell_size},\n            {gx * cell_size, (gy + 1) * cell_size}\n        };\n\n        for (int i = 0; i < 4; ++i) {\n            GridPoint neighbor = {gx + DX[i], gy + DY[i]};\n            if (cells.find(neighbor) == cells.end()) {\n                Point p1 = corners[i];\n                Point p2 = corners[(i + 3) % 4];\n                adj[p1].push_back(p2);\n                adj[p2].push_back(p1);\n            }\n        }\n    }\n    \n    std::vector<Point> vertices;\n    if (adj.empty()) return Polygon{};\n    \n    Point start_node = adj.begin()->first;\n    Point current_node = start_node;\n    Point prev_node = {start_node.x, start_node.y - 1};\n\n    for(size_t i = 0; i < 2 * adj.size(); ++i) {\n        vertices.push_back(current_node);\n        auto& neighbors = adj[current_node];\n        \n        std::sort(neighbors.begin(), neighbors.end(), [&](const Point& a, const Point& b) {\n            long long cp_a = cross_product(prev_node, current_node, a);\n            long long cp_b = cross_product(prev_node, current_node, b);\n            if (cp_a > 0 && cp_b <= 0) return true;\n            if (cp_a <= 0 && cp_b > 0) return false;\n            return cp_a > cp_b;\n        });\n        \n        Point next_node = neighbors[0];\n        for(const auto& neighbor : neighbors) {\n            if (!(neighbor == prev_node)) {\n                next_node = neighbor;\n                break;\n            }\n        }\n        \n        prev_node = current_node;\n        current_node = next_node;\n        if (current_node == start_node) break;\n    }\n\n    if (vertices.size() > 2) {\n        std::vector<Point> simplified;\n        for (size_t i = 0; i < vertices.size(); ++i) {\n            Point p_prev = simplified.empty() ? vertices.back() : simplified.back();\n            Point p_curr = vertices[i];\n            Point p_next = vertices[(i + 1) % vertices.size()];\n            if (cross_product(p_prev, p_curr, p_next) != 0 || simplified.size() < 2) {\n                simplified.push_back(p_curr);\n            }\n        }\n        vertices = simplified;\n    }\n    \n    return Polygon{vertices};\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    start_time = std::chrono::high_resolution_clock::now();\n\n    std::cin >> N;\n    mackerels.resize(N);\n    sardines.resize(N);\n    for (int i = 0; i < N; ++i) std::cin >> mackerels[i].x >> mackerels[i].y;\n    for (int i = 0; i < N; ++i) std::cin >> sardines[i].x >> sardines[i].y;\n    \n    int best_a = 0, best_b = 0;\n    Polygon best_polygon;\n    \n    std::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n    std::vector<int> cell_sizes = {1000, 667, 500, 400, 333, 250, 200};\n    int time_per_grid = 1980 / cell_sizes.size();\n\n    for (int cell_size : cell_sizes) {\n        auto loop_start_time = std::chrono::high_resolution_clock::now();\n        \n        int grid_dim_x = 100001 / cell_size + 1;\n        int grid_dim_y = 100001 / cell_size + 1;\n        std::vector<std::vector<int>> grid_scores(grid_dim_x, std::vector<int>(grid_dim_y, 0));\n\n        for (const auto& p : mackerels) grid_scores[p.x / cell_size][p.y / cell_size]++;\n        for (const auto& p : sardines) grid_scores[p.x / cell_size][p.y / cell_size]--;\n\n        std::vector<std::vector<bool>> visited(grid_dim_x, std::vector<bool>(grid_dim_y, false));\n\n        for (int gx = 0; gx < grid_dim_x; ++gx) {\n            for (int gy = 0; gy < grid_dim_y; ++gy) {\n                 auto now = std::chrono::high_resolution_clock::now();\n                 if (std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time).count() > 1980) break;\n                 \n                if (grid_scores[gx][gy] > 0 && !visited[gx][gy]) {\n                    std::set<GridPoint> component_cells;\n                    std::queue<GridPoint> q;\n\n                    q.push({gx, gy});\n                    visited[gx][gy] = true;\n                    while (!q.empty()) {\n                        GridPoint curr = q.front(); q.pop();\n                        component_cells.insert(curr);\n                        for (int i = 0; i < 4; ++i) {\n                            GridPoint next = {curr.first + DX[i], curr.second + DY[i]};\n                            if (next.first >= 0 && next.first < grid_dim_x && next.second >= 0 && next.second < grid_dim_y &&\n                                !visited[next.first][next.second] && grid_scores[next.first][next.second] > 0) {\n                                visited[next.first][next.second] = true;\n                                q.push(next);\n                            }\n                        }\n                    }\n\n                    std::set<GridPoint> current_cells = component_cells;\n                    \n                    double T = 5.0;\n                    double T_end = 0.01;\n                    int sa_iter = 0;\n                    \n                    while (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - loop_start_time).count() < time_per_grid - 20 && T > T_end) {\n                        sa_iter++;\n                        if (sa_iter % 200 == 0) T *= 0.99;\n                        \n                        std::vector<GridPoint> boundary_plus_neighbors;\n                        for(const auto& cell : current_cells) {\n                            for(int i=0; i<4; ++i) {\n                                GridPoint neighbor = {cell.first + DX[i], cell.second + DY[i]};\n                                if (neighbor.first >= 0 && neighbor.first < grid_dim_x && neighbor.second >= 0 && neighbor.second < grid_dim_y) {\n                                    boundary_plus_neighbors.push_back(neighbor);\n                                }\n                            }\n                        }\n                        if(boundary_plus_neighbors.empty()) continue;\n                        std::uniform_int_distribution<int> dist_op(0, boundary_plus_neighbors.size() - 1);\n                        GridPoint cand_cell = boundary_plus_neighbors[dist_op(rng)];\n\n                        bool is_in = current_cells.count(cand_cell);\n                        long long delta_score = grid_scores[cand_cell.first][cand_cell.second];\n                        if (is_in) delta_score = -delta_score;\n\n                        std::uniform_real_distribution<double> prob_dist(0.0, 1.0);\n                        if (delta_score > 0 || prob_dist(rng) < std::exp(delta_score / T)) {\n                            if (is_in) { if(current_cells.size() > 1) current_cells.erase(cand_cell); }\n                            else current_cells.insert(cand_cell);\n                        }\n                    }\n\n                    std::set<GridPoint> filled_cells = current_cells;\n                    if (!filled_cells.empty()) {\n                        std::vector<std::vector<bool>> is_component(grid_dim_x, std::vector<bool>(grid_dim_y, false));\n                        for(const auto& cell : filled_cells) is_component[cell.first][cell.second] = true;\n\n                        std::queue<GridPoint> hole_q;\n                        std::vector<std::vector<bool>> visited_bfs(grid_dim_x, std::vector<bool>(grid_dim_y, false));\n                        for(int i=0; i<grid_dim_x; ++i) {\n                            if (!is_component[i][0] && !visited_bfs[i][0]) { hole_q.push({i,0}); visited_bfs[i][0] = true; }\n                            if (grid_dim_y > 1 && !is_component[i][grid_dim_y-1] && !visited_bfs[i][grid_dim_y-1]) { hole_q.push({i,grid_dim_y-1}); visited_bfs[i][grid_dim_y-1] = true; }\n                        }\n                        for(int i=0; i<grid_dim_y; ++i) {\n                            if (!is_component[0][i] && !visited_bfs[0][i]) { hole_q.push({0,i}); visited_bfs[0][i] = true; }\n                            if (grid_dim_x > 1 && !is_component[grid_dim_x-1][i] && !visited_bfs[grid_dim_x-1][i]) { hole_q.push({grid_dim_x-1,i}); visited_bfs[grid_dim_x-1][i] = true; }\n                        }\n\n                        while(!hole_q.empty()){\n                            GridPoint curr = hole_q.front(); hole_q.pop();\n                            for(int i=0; i<4; ++i){\n                                GridPoint next = {curr.first + DX[i], curr.second + DY[i]};\n                                if (next.first >= 0 && next.first < grid_dim_x && next.second >= 0 && next.second < grid_dim_y && !visited_bfs[next.first][next.second] && !is_component[next.first][next.second]){\n                                    visited_bfs[next.first][next.second] = true;\n                                    hole_q.push(next);\n                                }\n                            }\n                        }\n                        \n                        for(int i=0; i<grid_dim_x; ++i) for(int j=0; j<grid_dim_y; ++j) {\n                            if(!visited_bfs[i][j] && !is_component[i][j]) filled_cells.insert({i,j});\n                        }\n                    }\n\n                    Polygon p = generate_polygon_from_cells(filled_cells, cell_size);\n                    if (p.vertices.size() >= 4 && p.vertices.size() <= 1000 && p.calculate_perimeter() <= 400000) {\n                        int current_a = 0, current_b = 0;\n                        for (const auto& m : mackerels) if (p.is_inside(m)) current_a++;\n                        for (const auto& s : sardines) if (p.is_inside(s)) current_b++;\n\n                        if (current_a - current_b > best_a - best_b) {\n                            best_a = current_a;\n                            best_b = current_b;\n                            best_polygon = p;\n                        }\n                    }\n                }\n            }\n             if (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start_time).count() > 1980) break;\n        }\n    }\n\n    if (best_polygon.vertices.empty()) {\n        if (!mackerels.empty()) {\n            Point m = mackerels[0];\n            best_polygon.vertices.push_back({m.x, m.y});\n            best_polygon.vertices.push_back({m.x + 1, m.y});\n            best_polygon.vertices.push_back({m.x + 1, m.y + 1});\n            best_polygon.vertices.push_back({m.x, m.y + 1});\n        }\n    }\n\n    std::cout << best_polygon.vertices.size() << '\\n';\n    for (const auto& v : best_polygon.vertices) {\n        std::cout << v.x << \" \" << v.y << '\\n';\n    }\n\n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <string>\n#include <chrono>\n#include <random>\n#include <numeric>\n#include <algorithm>\n#include <map>\n#include <tuple>\n#include <cmath>\n\n#include <Eigen/Dense>\n\n// --- Timer ---\nusing namespace std;\nusing namespace std::chrono;\n\nlong long start_time;\n\nlong long get_time() {\n    return duration_cast<milliseconds>(high_resolution_clock::now().time_since_epoch()).count();\n}\n\n// --- Random ---\nmt19937 rng(0);\n\n// --- Problem specific structs ---\nstruct Rect {\n    long long x, y, w, h;\n};\n\nstruct Action {\n    int p, r;\n    char d;\n    int b;\n};\n\nusing Plan = vector<Action>;\n\nstruct SimplePlacement {\n    vector<Rect> rects;\n    long long W = 0, H = 0;\n};\n\npair<long long, long long> simulate(int N, const vector<double>& w_est, const vector<double>& h_est, const Plan& plan) {\n    if (plan.empty()) return {0,0};\n\n    SimplePlacement p;\n    map<int, int> p_to_idx;\n    for (const auto& action : plan) {\n        long long w = round((action.r == 0) ? w_est[action.p] : h_est[action.p]);\n        long long h = round((action.r == 0) ? h_est[action.p] : w_est[action.p]);\n        long long new_x, new_y;\n        if (action.d == 'U') {\n            new_x = 0;\n            if (action.b != -1) {\n                const auto& ref_rect = p.rects[p_to_idx.at(action.b)];\n                new_x = ref_rect.x + ref_rect.w;\n            }\n            new_y = 0;\n            for (const auto& rect : p.rects) {\n                if (max(new_x, rect.x) < min(new_x + w, rect.x + rect.w)) {\n                    new_y = max(new_y, rect.y + rect.h);\n                }\n            }\n        } else { // 'L'\n            new_y = 0;\n            if (action.b != -1) {\n                const auto& ref_rect = p.rects[p_to_idx.at(action.b)];\n                new_y = ref_rect.y + ref_rect.h;\n            }\n            new_x = 0;\n            for (const auto& rect : p.rects) {\n                if (max(new_y, rect.y) < min(new_y + h, rect.y + rect.h)) {\n                    new_x = max(new_x, rect.x + rect.w);\n                }\n            }\n        }\n        p.rects.push_back({new_x, new_y, w, h});\n        p.W = max(p.W, new_x + w);\n        p.H = max(p.H, new_y + h);\n        p_to_idx[action.p] = p.rects.size() - 1;\n    }\n    return {p.W, p.H};\n}\n\n\n// --- Main logic ---\nint N, T;\ndouble SIGMA;\nvector<double> w_obs, h_obs;\nvector<double> w_mean, h_mean;\n\nvector<Plan> exploratory_plans;\nvector<tuple<Plan, long long, long long>> history;\n\nlong long best_score = -1;\nPlan best_plan;\n\nvoid generate_exploratory_plans() {\n    for (int k = 0; k < 4; ++k) {\n        Plan p_L, p_U;\n        for (int i = 0; i < N; ++i) {\n            p_L.push_back({i, (int)(rng() % 2), 'L', i > 0 ? i-1 : -1});\n            p_U.push_back({i, (int)(rng() % 2), 'U', i > 0 ? i-1 : -1});\n        }\n        exploratory_plans.push_back(p_L);\n        exploratory_plans.push_back(p_U);\n    }\n}\n\nvoid update_estimates_by_lsq() {\n    int num_vars = 2 * N;\n    \n    vector<vector<pair<int, double>>> A_rows;\n    vector<double> b_vals;\n\n    for (int i = 0; i < N; ++i) {\n        A_rows.push_back({{i, 1.0}}); b_vals.push_back(w_obs[i]);\n        A_rows.push_back({{N + i, 1.0}}); b_vals.push_back(h_obs[i]);\n    }\n\n    for (const auto& [plan, W_prime, H_prime] : history) {\n        if(plan.size() != N) continue;\n        bool is_sum_plan = true;\n        char first_d = plan[0].d;\n        for(size_t j=1; j<plan.size(); ++j) {\n            if(plan[j].d != first_d) { is_sum_plan = false; break; }\n        }\n        if(!is_sum_plan) continue;\n\n        vector<pair<int, double>> row;\n        if (first_d == 'L') {\n            for (const auto& action : plan) {\n                if (action.r == 0) row.push_back({action.p, 1.0});\n                else row.push_back({N + action.p, 1.0});\n            }\n            A_rows.push_back(row); b_vals.push_back(W_prime);\n        } else {\n            for (const auto& action : plan) {\n                if (action.r == 0) row.push_back({N + action.p, 1.0});\n                else row.push_back({action.p, 1.0});\n            }\n            A_rows.push_back(row); b_vals.push_back(H_prime);\n        }\n    }\n\n    int num_equations = A_rows.size();\n    Eigen::MatrixXd A(num_equations, num_vars);\n    Eigen::VectorXd b(num_equations);\n    A.setZero();\n    for(int i=0; i<num_equations; ++i){\n        for(auto const& [col, val] : A_rows[i]) {\n            A(i, col) = val;\n        }\n        b(i) = b_vals[i];\n    }\n    \n    Eigen::VectorXd x = A.bdcSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(b);\n\n    for (int i = 0; i < N; ++i) {\n        w_mean[i] = max(1.0, x(i));\n        h_mean[i] = max(1.0, x(N + i));\n    }\n}\n\nPlan greedy_search() {\n    Plan plan;\n    SimplePlacement current_p;\n    map<int, int> p_to_idx;\n\n    for (int i = 0; i < N; ++i) {\n        Action best_action;\n        long long best_score = -1;\n        \n        for (int r = 0; r < 2; ++r) {\n            long long w = round((r == 0) ? w_mean[i] : h_mean[i]);\n            long long h = round((r == 0) ? h_mean[i] : w_mean[i]);\n            for (char d : {'U', 'L'}) {\n                for (int b = -1; b < i; ++b) {\n                    SimplePlacement next_p = current_p;\n                    long long new_x, new_y;\n                    if(d == 'U'){\n                        new_x = 0; if (b!=-1) new_x = next_p.rects[b].x + next_p.rects[b].w;\n                        new_y = 0;\n                        for(const auto& rect : next_p.rects) if(max(new_x, rect.x) < min(new_x+w, rect.x+rect.w)) new_y = max(new_y, rect.y+rect.h);\n                    } else {\n                        new_y = 0; if (b!=-1) new_y = next_p.rects[b].y + next_p.rects[b].h;\n                        new_x = 0;\n                        for(const auto& rect : next_p.rects) if(max(new_y, rect.y) < min(new_y+h, rect.y+rect.h)) new_x = max(new_x, rect.x+rect.w);\n                    }\n                    next_p.rects.push_back({new_x, new_y, w, h});\n                    next_p.W = max(next_p.W, new_x+w);\n                    next_p.H = max(next_p.H, new_y+h);\n\n                    long long current_score = next_p.W + next_p.H;\n                    if (best_score == -1 || current_score < best_score) {\n                        best_score = current_score;\n                        best_action = {i, r, d, b};\n                    }\n                }\n            }\n        }\n        \n        plan.push_back(best_action);\n        long long w = round((best_action.r == 0) ? w_mean[i] : h_mean[i]);\n        long long h = round((best_action.r == 0) ? h_mean[i] : w_mean[i]);\n        long long new_x, new_y;\n        if(best_action.d == 'U'){\n            new_x = 0; if (best_action.b!=-1) new_x = current_p.rects[best_action.b].x + current_p.rects[best_action.b].w;\n            new_y = 0;\n            for(const auto& rect : current_p.rects) if(max(new_x, rect.x) < min(new_x+w, rect.x+rect.w)) new_y = max(new_y, rect.y+rect.h);\n        } else {\n            new_y = 0; if (best_action.b!=-1) new_y = current_p.rects[best_action.b].y + current_p.rects[best_action.b].h;\n            new_x = 0;\n            for(const auto& rect : current_p.rects) if(max(new_y, rect.y) < min(new_y+h, rect.y+rect.h)) new_x = max(new_x, rect.x+rect.w);\n        }\n        current_p.rects.push_back({new_x, new_y, w, h});\n        current_p.W = max(current_p.W, new_x+w);\n        current_p.H = max(current_p.H, new_y+h);\n    }\n    return plan;\n}\n\nPlan local_search(Plan initial_plan, int time_limit_ms) {\n    long long turn_start_time = get_time();\n    Plan current_best_plan = initial_plan;\n    auto [W, H] = simulate(N, w_mean, h_mean, current_best_plan);\n    long long best_eval_score = W + H;\n\n    int iter = 0;\n    while(get_time() - turn_start_time < time_limit_ms) {\n        Plan current_plan = current_best_plan;\n        int i = rng() % N;\n        \n        int r = rng() % 2;\n        char d = (rng() % 2 == 0) ? 'U' : 'L';\n        int b = -1;\n        if (i > 0) {\n            b = uniform_int_distribution<int>(-1, i - 1)(rng);\n        }\n        current_plan[i] = {i, r, d, b};\n        \n        auto [cur_W, cur_H] = simulate(N, w_mean, h_mean, current_plan);\n        long long current_eval_score = cur_W + cur_H;\n\n        if (current_eval_score < best_eval_score) {\n            best_eval_score = current_eval_score;\n            current_best_plan = current_plan;\n        }\n        iter++;\n    }\n    return current_best_plan;\n}\n\nvoid solve() {\n    cin >> N >> T >> SIGMA;\n    w_obs.resize(N); h_obs.resize(N);\n    w_mean.resize(N); h_mean.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> w_obs[i] >> h_obs[i];\n        w_mean[i] = w_obs[i];\n        h_mean[i] = h_obs[i];\n    }\n    \n    generate_exploratory_plans();\n    \n    int K = min((int)exploratory_plans.size(), T / 2);\n    \n    for (int t = 0; t < T; ++t) {\n        Plan p_to_submit;\n        if (t < K) {\n            p_to_submit = exploratory_plans[t];\n        } else {\n            if (t == K) {\n                update_estimates_by_lsq();\n                if (!best_plan.empty()){\n                    auto[W_true_est, H_true_est] = simulate(N, w_mean, h_mean, best_plan);\n                    // best_score might be based on noisy W', H', but let's update our belief of its true score\n                }\n            }\n            \n            long long time_left = 2900 - (get_time() - start_time);\n            long long time_per_turn = time_left / (T - t);\n            \n            Plan initial_plan = greedy_search();\n            p_to_submit = local_search(initial_plan, time_per_turn);\n            \n            if (!best_plan.empty()) {\n                auto [w_cand, h_cand] = simulate(N, w_mean, h_mean, p_to_submit);\n                auto [w_best, h_best] = simulate(N, w_mean, h_mean, best_plan);\n                if (w_best + h_best < w_cand + h_cand) {\n                    p_to_submit = best_plan;\n                }\n            }\n        }\n        \n        cout << p_to_submit.size() << endl;\n        for (const auto& action : p_to_submit) {\n            cout << action.p << \" \" << action.r << \" \" << action.d << \" \" << action.b << endl;\n        }\n\n        long long W_prime, H_prime;\n        cin >> W_prime >> H_prime;\n        \n        if (t < K) {\n            history.emplace_back(p_to_submit, W_prime, H_prime);\n        }\n        \n        long long current_score = W_prime + H_prime;\n        if (best_score == -1 || current_score < best_score) {\n            best_score = current_score;\n            best_plan = p_to_submit;\n        }\n    }\n}\n\nint main() {\n    start_time = get_time();\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <cmath>\n#include <tuple>\n\nusing namespace std;\n\n// --- Utilities ---\nstruct XorShift {\n    unsigned int x, y, z, w;\n    XorShift(unsigned int seed) : x(seed), y(362436069), z(521288629), w(88675123) {}\n    unsigned int next() {\n        unsigned int t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));\n    }\n    int next_int(int n) {\n        if (n == 0) return 0;\n        return next() % n;\n    }\n    double next_double() {\n        return (double)next() / ((long long)1 << 32);\n    }\n};\n\nXorShift rnd(12345);\nauto start_time = chrono::steady_clock::now();\n\n// --- Problem data ---\nint N, M, H;\nvector<int> A;\nvector<pair<int, int>> edges;\nvector<vector<int>> adj;\n\n// --- Solution state and helpers ---\nstruct Solution {\n    vector<int> p;\n    long long score;\n\n    vector<vector<int>> children;\n    vector<int> h;\n    vector<int> max_d;\n    vector<long long> sum_A_sub;\n    vector<int> root_of;\n\n    Solution() {}\n\n    void init(int n_nodes) {\n        p.assign(n_nodes, -1);\n        children.assign(n_nodes, {});\n        h.assign(n_nodes, 0);\n        max_d.assign(n_nodes, 0);\n        sum_A_sub.assign(n_nodes, 0);\n        root_of.assign(n_nodes, -1);\n    }\n\n    void compute_properties() {\n        for(int i=0; i<N; ++i) children[i].clear();\n        vector<int> roots;\n        for (int i = 0; i < N; ++i) {\n            if (p[i] == -1) {\n                roots.push_back(i);\n            } else {\n                children[p[i]].push_back(i);\n            }\n        }\n\n        for (int r : roots) {\n            vector<int> q;\n            q.push_back(r);\n            root_of[r] = r;\n            h[r] = 0;\n            \n            int head = 0;\n            while(head < q.size()){\n                int u = q[head++];\n                for(int v : children[u]){\n                    h[v] = h[u] + 1;\n                    root_of[v] = r;\n                    q.push_back(v);\n                }\n            }\n            \n            reverse(q.begin(), q.end());\n            for(int u : q){\n                sum_A_sub[u] = A[u];\n                max_d[u] = 0;\n                for(int v : children[u]){\n                    sum_A_sub[u] += sum_A_sub[v];\n                    max_d[u] = max(max_d[u], max_d[v] + 1);\n                }\n            }\n        }\n        score = 0;\n        for(int i=0; i<N; ++i) {\n            if (h[i] > H) {\n                score = -1; // Invalid\n                return;\n            }\n            score += (long long)(h[i] + 1) * A[i];\n        }\n    }\n};\n\nvoid solve() {\n    Solution sol;\n    sol.init(N);\n    \n    // --- Greedy construction ---\n    double greedy_time_limit = 0.8;\n    int roots_count = N;\n    while(roots_count > 1) {\n        auto current_time = chrono::steady_clock::now();\n        double elapsed_time = chrono::duration_cast<chrono::milliseconds>(current_time - start_time).count() / 1000.0;\n        if (elapsed_time > greedy_time_limit) break;\n\n        sol.compute_properties();\n\n        double best_gain = -1.0;\n        int best_u = -1, best_v = -1;\n\n        for (const auto& edge : edges) {\n            int u1 = edge.first;\n            int v1 = edge.second;\n\n            if (sol.root_of[u1] == sol.root_of[v1]) continue;\n\n            // Try u1 -> v1\n            if (sol.p[v1] == -1) {\n                if (sol.h[u1] + 1 + sol.max_d[v1] <= H) {\n                    double gain = (double)(sol.h[u1] + 1) * sol.sum_A_sub[v1];\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        best_u = u1;\n                        best_v = v1;\n                    }\n                }\n            }\n            // Try v1 -> u1\n            if (sol.p[u1] == -1) {\n                if (sol.h[v1] + 1 + sol.max_d[u1] <= H) {\n                    double gain = (double)(sol.h[v1] + 1) * sol.sum_A_sub[u1];\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        best_u = v1;\n                        best_v = u1;\n                    }\n                }\n            }\n        }\n\n        if (best_u == -1) break;\n        sol.p[best_v] = best_u;\n        roots_count--;\n    }\n\n    sol.compute_properties();\n    Solution best_sol = sol;\n\n    // --- Simulated Annealing ---\n    double time_limit = 1.95;\n    double temp_start = 500.0, temp_end = 0.1;\n\n    while (true) {\n        auto current_time = chrono::steady_clock::now();\n        double elapsed_time = chrono::duration_cast<chrono::milliseconds>(current_time - start_time).count() / 1000.0;\n        if (elapsed_time > time_limit) break;\n\n        double progress = (elapsed_time - greedy_time_limit) / (time_limit - greedy_time_limit);\n        if (progress < 0) progress = 0;\n        if (progress > 1) progress = 1;\n\n        double temp = temp_start * pow(temp_end / temp_start, progress);\n\n        int v = rnd.next_int(N);\n        \n        vector<int> candidates = adj[v];\n        candidates.push_back(-1);\n        int u = candidates[rnd.next_int(candidates.size())];\n\n        int old_p = sol.p[v];\n        if (u == old_p) continue;\n        \n        bool is_ancestor = false;\n        if (u != -1) {\n            int curr = u;\n            while(curr != -1) {\n                if (curr == v) {\n                    is_ancestor = true;\n                    break;\n                }\n                curr = sol.p[curr];\n            }\n        }\n        if (is_ancestor) continue;\n        \n        int u_h = (u == -1) ? -1 : sol.h[u];\n        if (u_h + 1 + sol.max_d[v] > H) continue;\n\n        int old_p_h = (old_p == -1) ? -1 : sol.h[old_p];\n        long long score_delta = (long long)(u_h - old_p_h) * sol.sum_A_sub[v];\n\n        if (score_delta > 0 || (temp > 1e-9 && rnd.next_double() < exp(score_delta / temp))) {\n            sol.p[v] = u;\n            sol.compute_properties();\n            if (sol.score > best_sol.score) {\n                best_sol = sol;\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << best_sol.p[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N >> M >> H;\n    A.resize(N);\n    adj.resize(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        edges.push_back({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    solve();\n\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <array>\n\nusing namespace std;\n\nconst int N = 20;\n\nstruct Piece {\n    int id;\n    int r, c;\n};\n\nstruct Action {\n    char dir;\n    int line_idx;\n    int cost;\n    vector<int> covered_oni_ids;\n};\n\n// Function to calculate safe directions for each Oni based on initial Fukunokami positions\nauto precompute_safe_directions(const vector<Piece>& onis, const vector<Piece>& fukus) {\n    int num_onis = onis.size();\n    vector<array<bool, 4>> safe_dirs(num_onis); // 0:U, 1:D, 2:L, 3:R\n\n    for (int i = 0; i < num_onis; ++i) {\n        const auto& oni = onis[i];\n        bool safe_u = true, safe_d = true, safe_l = true, safe_r = true;\n\n        for (const auto& fuku : fukus) {\n            if (fuku.c == oni.c) {\n                if (fuku.r < oni.r) safe_u = false;\n                if (fuku.r > oni.r) safe_d = false;\n            }\n            if (fuku.r == oni.r) {\n                if (fuku.c < oni.c) safe_l = false;\n                if (fuku.c > oni.c) safe_r = false;\n            }\n        }\n        safe_dirs[i][0] = safe_u;\n        safe_dirs[i][1] = safe_d;\n        safe_dirs[i][2] = safe_l;\n        safe_dirs[i][3] = safe_r;\n    }\n    return safe_dirs;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n_dummy;\n    cin >> n_dummy; // N is fixed at 20, but read it anyway.\n\n    vector<Piece> onis;\n    vector<Piece> fukus;\n\n    int oni_id_counter = 0;\n    for (int i = 0; i < N; ++i) {\n        string row_str;\n        cin >> row_str;\n        for (int j = 0; j < N; ++j) {\n            if (row_str[j] == 'x') {\n                onis.push_back({oni_id_counter++, i, j});\n            } else if (row_str[j] == 'o') {\n                fukus.push_back({-1, i, j});\n            }\n        }\n    }\n\n    auto safe_dirs = precompute_safe_directions(onis, fukus);\n    \n    int num_onis = onis.size();\n    vector<bool> oni_covered(num_onis, false);\n    int uncovered_count = num_onis;\n\n    vector<bool> row_used(N, false);\n    vector<bool> col_used(N, false);\n\n    vector<pair<char, int>> moves;\n\n    while (uncovered_count > 0) {\n        Action best_action = {' ', -1, -1, {}};\n        double best_score = 1e18;\n\n        // Try Up actions for each available column\n        for (int j = 0; j < N; ++j) {\n            if (col_used[j]) continue;\n            \n            int max_cost = 0;\n            vector<int> newly_covered;\n            for (const auto& oni : onis) {\n                if (!oni_covered[oni.id] && oni.c == j && safe_dirs[oni.id][0]) {\n                    newly_covered.push_back(oni.id);\n                    max_cost = max(max_cost, oni.r + 1);\n                }\n            }\n\n            if (!newly_covered.empty()) {\n                double score = (double)max_cost / newly_covered.size();\n                if (score < best_score) {\n                    best_score = score;\n                    best_action = {'U', j, max_cost, newly_covered};\n                }\n            }\n        }\n\n        // Try Down actions for each available column\n        for (int j = 0; j < N; ++j) {\n            if (col_used[j]) continue;\n\n            int max_cost = 0;\n            vector<int> newly_covered;\n            for (const auto& oni : onis) {\n                if (!oni_covered[oni.id] && oni.c == j && safe_dirs[oni.id][1]) {\n                    newly_covered.push_back(oni.id);\n                    max_cost = max(max_cost, N - oni.r);\n                }\n            }\n            \n            if (!newly_covered.empty()) {\n                double score = (double)max_cost / newly_covered.size();\n                if (score < best_score) {\n                    best_score = score;\n                    best_action = {'D', j, max_cost, newly_covered};\n                }\n            }\n        }\n        \n        // Try Left actions for each available row\n        for (int i = 0; i < N; ++i) {\n            if (row_used[i]) continue;\n            \n            int max_cost = 0;\n            vector<int> newly_covered;\n            for (const auto& oni : onis) {\n                if (!oni_covered[oni.id] && oni.r == i && safe_dirs[oni.id][2]) {\n                    newly_covered.push_back(oni.id);\n                    max_cost = max(max_cost, oni.c + 1);\n                }\n            }\n            \n            if (!newly_covered.empty()) {\n                double score = (double)max_cost / newly_covered.size();\n                if (score < best_score) {\n                    best_score = score;\n                    best_action = {'L', i, max_cost, newly_covered};\n                }\n            }\n        }\n\n        // Try Right actions for each available row\n        for (int i = 0; i < N; ++i) {\n            if (row_used[i]) continue;\n            \n            int max_cost = 0;\n            vector<int> newly_covered;\n            for (const auto& oni : onis) {\n                if (!oni_covered[oni.id] && oni.r == i && safe_dirs[oni.id][3]) {\n                    newly_covered.push_back(oni.id);\n                    max_cost = max(max_cost, N - oni.c);\n                }\n            }\n            \n            if (!newly_covered.empty()) {\n                double score = (double)max_cost / newly_covered.size();\n                if (score < best_score) {\n                    best_score = score;\n                    best_action = {'R', i, max_cost, newly_covered};\n                }\n            }\n        }\n\n        if (best_action.line_idx == -1) {\n            // This case should not be reached due to the problem guarantee\n            // that a solution always exists.\n            break; \n        }\n\n        // Apply the best action found in this iteration\n        for (int i = 0; i < best_action.cost; ++i) {\n            moves.push_back({best_action.dir, best_action.line_idx});\n        }\n        \n        for (int id : best_action.covered_oni_ids) {\n            if (!oni_covered[id]) {\n                oni_covered[id] = true;\n                uncovered_count--;\n            }\n        }\n\n        if (best_action.dir == 'U' || best_action.dir == 'D') {\n            col_used[best_action.line_idx] = true;\n        } else {\n            row_used[best_action.line_idx] = true;\n        }\n    }\n\n    for (const auto& move : moves) {\n        cout << move.first << \" \" << move.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <algorithm>\n\n// --- Start of Timer and RNG Utilities ---\nclass Timer {\n    std::chrono::high_resolution_clock::time_point start_time;\npublic:\n    Timer() {\n        start_time = std::chrono::high_resolution_clock::now();\n    }\n    double get_elapsed_sec() {\n        auto now = std::chrono::high_resolution_clock::now();\n        return std::chrono::duration_cast<std::chrono::duration<double>>(now - start_time).count();\n    }\n};\n\nclass XorShiftRng {\n    uint64_t x;\npublic:\n    XorShiftRng() : x(std::chrono::high_resolution_clock::now().time_since_epoch().count()) {}\n    uint64_t next() {\n        x ^= x << 13;\n        x ^= x >> 7;\n        x ^= x << 17;\n        return x;\n    }\n    int next_int(int max) { // [0, max-1]\n        if (max <= 0) return 0;\n        return next() % max;\n    }\n    double next_double() { // [0.0, 1.0)\n        return static_cast<double>(next()) / UINT64_MAX;\n    }\n};\n// --- End of Timer and RNG Utilities ---\n\nconst int N_CONST = 100;\nconst int L_CONST = 500000;\nconst double TIME_LIMIT_SEC = 1.95;\n\nstruct EvalResult {\n    long long error;\n    std::vector<int> t;\n};\n\nEvalResult evaluate(const std::vector<int>& a, const std::vector<int>& b, const std::vector<int>& T) {\n    std::vector<int> t(N_CONST, 0);\n    int cleaner = 0;\n    \n    t[cleaner]++;\n    \n    for (int k = 1; k < L_CONST; ++k) {\n        int last_cleaner = cleaner;\n        int count_of_last_cleaner = t[last_cleaner];\n        \n        if (count_of_last_cleaner % 2 != 0) {\n            cleaner = a[last_cleaner];\n        } else {\n            cleaner = b[last_cleaner];\n        }\n        t[cleaner]++;\n    }\n    \n    long long error = 0;\n    for (int i = 0; i < N_CONST; ++i) {\n        error += std::abs(static_cast<long long>(t[i]) - T[i]);\n    }\n    \n    return {error, std::move(t)};\n}\n\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    Timer timer;\n    \n    int n_in, l_in;\n    std::cin >> n_in >> l_in; \n    std::vector<int> T(N_CONST);\n    for (int i = 0; i < N_CONST; ++i) {\n        std::cin >> T[i];\n    }\n\n    XorShiftRng rng;\n\n    // --- Initial solution ---\n    std::vector<int> a(N_CONST), b(N_CONST);\n    \n    std::mt19937 mt_for_dist(rng.next());\n    std::vector<double> weights(N_CONST);\n    for(int i = 0; i < N_CONST; ++i) {\n         weights[i] = T[i] > 0 ? static_cast<double>(T[i]) : 1.0;\n    }\n    std::discrete_distribution<> dist(weights.begin(), weights.end());\n\n    for (int i = 0; i < N_CONST; ++i) {\n        a[i] = dist(mt_for_dist);\n        b[i] = dist(mt_for_dist);\n    }\n\n    auto current_eval = evaluate(a, b, T);\n    long long current_error = current_eval.error;\n    std::vector<int> current_t = std::move(current_eval.t);\n\n    std::vector<int> best_a = a;\n    std::vector<int> best_b = b;\n    long long best_error = current_error;\n\n    // --- Simulated Annealing ---\n    double T_start = 2000.0;\n    double T_end = 0.1;\n    \n    while (timer.get_elapsed_sec() < TIME_LIMIT_SEC) {\n        double progress = timer.get_elapsed_sec() / TIME_LIMIT_SEC;\n        double temp = T_start * std::pow(T_end / T_start, progress);\n\n        std::vector<int> next_a = a;\n        std::vector<int> next_b = b;\n\n        // --- Generate Neighbor ---\n        int change_i;\n        int change_ab; // 0 for a, 1 for b\n        int new_val;\n        \n        std::vector<int> over_served;\n        std::vector<int> under_served;\n        for(int j=0; j<N_CONST; ++j) {\n            if(current_t[j] > T[j]) over_served.push_back(j);\n            else if (current_t[j] < T[j]) under_served.push_back(j);\n        }\n\n        bool smart_move_possible = !over_served.empty() && !under_served.empty();\n        \n        if (rng.next_double() < 0.1 || !smart_move_possible) { // Random move\n            change_i = rng.next_int(N_CONST);\n            change_ab = rng.next_int(2);\n            new_val = rng.next_int(N_CONST);\n        } else { // Smart move: Reroute an edge from an over-served node to an under-served node\n            std::vector<bool> is_over_served(N_CONST, false);\n            for(int v : over_served) is_over_served[v] = true;\n            \n            std::vector<std::pair<int, int>> redirectable_edges;\n            redirectable_edges.reserve(2 * N_CONST);\n            for (int u = 0; u < N_CONST; ++u) {\n                if (is_over_served[a[u]]) redirectable_edges.push_back({u, 0});\n                if (is_over_served[b[u]]) redirectable_edges.push_back({u, 1});\n            }\n            \n            if (redirectable_edges.empty()) { // Fallback to random move\n                change_i = rng.next_int(N_CONST);\n                change_ab = rng.next_int(2);\n                new_val = rng.next_int(N_CONST);\n            } else {\n                auto& edge_to_change = redirectable_edges[rng.next_int(redirectable_edges.size())];\n                change_i = edge_to_change.first;\n                change_ab = edge_to_change.second;\n                new_val = under_served[rng.next_int(under_served.size())];\n            }\n        }\n\n        if (change_ab == 0) {\n            next_a[change_i] = new_val;\n        } else {\n            next_b[change_i] = new_val;\n        }\n        \n        auto neighbor_eval = evaluate(next_a, next_b, T);\n        long long neighbor_error = neighbor_eval.error;\n\n        double delta_e = static_cast<double>(neighbor_error) - current_error;\n\n        if (delta_e < 0 || rng.next_double() < std::exp(-delta_e / temp)) {\n            a = std::move(next_a);\n            b = std::move(next_b);\n            current_error = neighbor_error;\n            current_t = std::move(neighbor_eval.t);\n            if (current_error < best_error) {\n                best_error = current_error;\n                best_a = a;\n                best_b = b;\n            }\n        }\n    }\n\n    // Output best solution found\n    for (int i = 0; i < N_CONST; ++i) {\n        std::cout << best_a[i] << \" \" << best_b[i] << \"\\n\";\n    }\n    \n    return 0;\n}","ahc045":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <set>\n#include <map>\n#include <queue>\n#include <tuple>\n#include <chrono>\n\n// Start timer\nauto start_time = std::chrono::high_resolution_clock::now();\ndouble time_limit = 1.95; // seconds\n\nstruct City {\n    int id;\n    long long lx, rx, ly, ry;\n    long long cx, cy;\n};\n\n// Z-order curve (Morton code)\nuint64_t z_order(uint32_t x, uint32_t y) {\n    uint64_t z = 0;\n    x &= 0x7FFF; // Max coord is 10000, 15 bits are enough\n    y &= 0x7FFF;\n    for (int i = 0; i < 15; ++i) {\n        z |= (static_cast<uint64_t>(x) & (1u << i)) << (i + 1);\n        z |= (static_cast<uint64_t>(y) & (1u << i)) << i;\n    }\n    return z;\n}\n\nstruct DSU {\n    std::vector<int> parent;\n    DSU(int n) {\n        parent.resize(n);\n        std::iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int i) {\n        if (parent[i] == i)\n            return i;\n        return parent[i] = find(parent[i]);\n    }\n    void unite(int i, int j) {\n        int root_i = find(i);\n        int root_j = find(j);\n        if (root_i != root_j) {\n            parent[root_i] = root_j;\n        }\n    }\n};\n\nlong long dist_sq(const City& a, const City& b) {\n    return (a.cx - b.cx) * (a.cx - b.cx) + (a.cy - b.cy) * (a.cy - b.cy);\n}\n\nstd::vector<std::pair<int, int>> do_query(const std::vector<int>& c) {\n    std::cout << \"? \" << c.size();\n    for (int city_id : c) {\n        std::cout << \" \" << city_id;\n    }\n    std::cout << std::endl;\n\n    std::vector<std::pair<int, int>> edges;\n    if (c.size() > 1) {\n        for (size_t i = 0; i < c.size() - 1; ++i) {\n            int u, v;\n            std::cin >> u >> v;\n            edges.emplace_back(u, v);\n        }\n    }\n    return edges;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\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<City> cities(N);\n    for (int i = 0; i < N; ++i) {\n        cities[i].id = i;\n        std::cin >> cities[i].lx >> cities[i].rx >> cities[i].ly >> cities[i].ry;\n        cities[i].cx = (cities[i].lx + cities[i].rx) / 2;\n        cities[i].cy = (cities[i].ly + cities[i].ry) / 2;\n    }\n\n    // 1. Grouping\n    std::vector<int> city_indices(N);\n    std::iota(city_indices.begin(), city_indices.end(), 0);\n    std::sort(city_indices.begin(), city_indices.end(), [&](int a, int b) {\n        return z_order(cities[a].cx, cities[a].cy) < z_order(cities[b].cx, cities[b].cy);\n    });\n    \n    std::vector<std::vector<int>> groups(M);\n    int current_city_idx = 0;\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < G[i]; ++j) {\n            groups[i].push_back(city_indices[current_city_idx++]);\n        }\n    }\n\n    // 2. Querying\n    int queries_left = Q;\n    std::vector<std::tuple<int, int, int>> all_edges; // u, v, group_idx\n\n    // Main query loop\n    for (int k = 0; k < M; ++k) {\n        if (queries_left == 0) break;\n        if (G[k] < 2) continue;\n        \n        const auto& current_group = groups[k];\n        \n        if (G[k] <= L) {\n            auto edges = do_query(current_group);\n            for (const auto& edge : edges) {\n                all_edges.emplace_back(edge.first, edge.second, k);\n            }\n            queries_left--;\n            continue;\n        }\n\n        int step = L - 1;\n        for (int i = 0; ; ++i) {\n             int start = i * step;\n             if (start >= G[k] - 1) break;\n             if (queries_left == 0) break;\n             \n             int end = std::min(start + L, G[k]);\n             if (end - start < 2) continue;\n             \n             std::vector<int> query_cities;\n             for (int j = start; j < end; ++j) {\n                 query_cities.push_back(current_group[j]);\n             }\n             auto edges = do_query(query_cities);\n             for (const auto& edge : edges) {\n                all_edges.emplace_back(edge.first, edge.second, k);\n             }\n             queries_left--;\n        }\n    }\n\n    // Improvement queries\n    std::mt19937 rng(0);\n    std::vector<int> large_groups_indices;\n    for(int i=0; i<M; ++i) {\n        if (G[i] > L) {\n            large_groups_indices.push_back(i);\n        }\n    }\n    \n    if (!large_groups_indices.empty()) {\n        int large_group_ptr = 0;\n        while(queries_left > 0) {\n            auto now = std::chrono::high_resolution_clock::now();\n            if (std::chrono::duration<double>(now - start_time).count() > time_limit) break;\n\n            int k = large_groups_indices[large_group_ptr];\n            const auto& current_group = groups[k];\n\n            std::vector<int> query_cities_indices(G[k]);\n            std::iota(query_cities_indices.begin(), query_cities_indices.end(), 0);\n            std::shuffle(query_cities_indices.begin(), query_cities_indices.end(), rng);\n            \n            std::vector<int> query_cities;\n            for(int i=0; i < std::min((int)query_cities_indices.size(), L); ++i) {\n                query_cities.push_back(current_group[query_cities_indices[i]]);\n            }\n            \n            if (query_cities.size() < 2) continue;\n            \n            auto edges = do_query(query_cities);\n            for (const auto& edge : edges) {\n                all_edges.emplace_back(edge.first, edge.second, k);\n            }\n            queries_left--;\n            large_group_ptr = (large_group_ptr + 1) % large_groups_indices.size();\n        }\n    }\n    \n    // 3. Output\n    std::cout << \"!\" << std::endl;\n    \n    for (int k = 0; k < M; ++k) {\n        for (size_t i = 0; i < groups[k].size(); ++i) {\n            std::cout << groups[k][i] << (i == groups[k].size() - 1 ? \"\" : \" \");\n        }\n        std::cout << std::endl;\n\n        if (G[k] > 1) {\n            std::vector<std::pair<int,int>> final_edges;\n            DSU dsu(N);\n            for (const auto& [u, v, group_idx] : all_edges) {\n                if (group_idx == k) {\n                    if (dsu.find(u) != dsu.find(v)) {\n                        dsu.unite(u, v);\n                        final_edges.emplace_back(u, v);\n                    }\n                }\n            }\n            \n            std::map<int, std::vector<int>> components;\n            for (int city_id : groups[k]) {\n                components[dsu.find(city_id)].push_back(city_id);\n            }\n\n            if (components.size() > 1) {\n                std::vector<std::tuple<long long, int, int>> candidate_edges;\n                auto it1 = components.begin();\n                while(it1 != components.end()){\n                    auto it2 = std::next(it1);\n                    while(it2 != components.end()){\n                        for(int u : it1->second){\n                            for(int v : it2->second){\n                                candidate_edges.emplace_back(dist_sq(cities[u], cities[v]), u, v);\n                            }\n                        }\n                        it2++;\n                    }\n                    it1++;\n                }\n                \n                std::sort(candidate_edges.begin(), candidate_edges.end());\n\n                for (const auto& [d_sq, u, v] : candidate_edges) {\n                    if (dsu.find(u) != dsu.find(v)) {\n                        dsu.unite(u, v);\n                        final_edges.emplace_back(u, v);\n                        if ((int)final_edges.size() == G[k] - 1) break;\n                    }\n                }\n            }\n            // For groups of size 2 we might not have queried if budget was low\n            if (G[k] == 2 && final_edges.empty()) {\n                 final_edges.emplace_back(groups[k][0], groups[k][1]);\n            }\n\n            for(const auto& edge : final_edges) {\n                std::cout << edge.first << \" \" << edge.second << std::endl;\n            }\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <map>\n#include <set>\n#include <cmath>\n#include <algorithm>\n#include <tuple>\n\nusing namespace std;\n\nconst int N = 20;\nconst int M = 40;\n\nstruct Pos {\n    int r, c;\n\n    bool operator<(const Pos& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n    bool operator==(const Pos& other) const {\n        return r == other.r && c == other.c;\n    }\n};\n\nint manhattan_distance(const Pos& a, const Pos& b) {\n    return abs(a.r - b.r) + abs(a.c - b.c);\n}\n\nbool is_valid(const Pos& p) {\n    return p.r >= 0 && p.r < N && p.c >= 0 && p.c < N;\n}\n\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\nconst char dir_char[] = {'U', 'D', 'L', 'R'};\n\nstruct Action {\n    char act, dir;\n};\n\nmap<Pos, int> dijkstra(const Pos& start, const set<Pos>& blocks) {\n    map<Pos, int> dist;\n    priority_queue<pair<int, Pos>, vector<pair<int, Pos>>, greater<pair<int, Pos>>> pq;\n\n    dist[start] = 0;\n    pq.push({0, start});\n\n    while (!pq.empty()) {\n        auto [cost, pos] = pq.top();\n        pq.pop();\n\n        if (dist.count(pos) && cost > dist.at(pos)) {\n            continue;\n        }\n\n        // Move\n        for (int i = 0; i < 4; ++i) {\n            Pos next_pos = {pos.r + dr[i], pos.c + dc[i]};\n            if (is_valid(next_pos) && !blocks.count(next_pos)) {\n                int next_cost = cost + 1;\n                if (!dist.count(next_pos) || next_cost < dist.at(next_pos)) {\n                    dist[next_pos] = next_cost;\n                    pq.push({next_cost, next_pos});\n                }\n            }\n        }\n        \n        // Slide\n        for (int i = 0; i < 4; ++i) {\n            Pos stop_pos = pos;\n            Pos next_pos = {stop_pos.r + dr[i], stop_pos.c + dc[i]};\n            while (is_valid(next_pos) && !blocks.count(next_pos)) {\n                stop_pos = next_pos;\n                next_pos = {stop_pos.r + dr[i], stop_pos.c + dc[i]};\n            }\n            \n            if (stop_pos == pos) continue;\n\n            int next_cost = cost + 1;\n            if (!dist.count(stop_pos) || next_cost < dist.at(stop_pos)) {\n                dist[stop_pos] = next_cost;\n                pq.push({next_cost, stop_pos});\n            }\n        }\n    }\n    return dist;\n}\n\npair<int, vector<Action>> a_star_full(const Pos& start, const Pos& end, const set<Pos>& blocks) {\n    if (blocks.count(end) && !(start == end)) {\n        return {1000000, {}};\n    }\n    if (start == end) return {0, {}};\n\n    map<Pos, int> dist;\n    map<Pos, Action> parent_action;\n    map<Pos, Pos> parent_pos;\n\n    priority_queue<pair<int, Pos>, vector<pair<int, Pos>>, greater<pair<int, Pos>>> pq;\n\n    dist[start] = 0;\n    pq.push({manhattan_distance(start, end), start});\n\n    while (!pq.empty()) {\n        auto [est_cost_pq, pos] = pq.top();\n        pq.pop();\n        \n        int cost = dist.at(pos);\n\n        if (pos == end) {\n            vector<Action> actions;\n            Pos curr = end;\n            while (!(curr == start)) {\n                actions.push_back(parent_action.at(curr));\n                curr = parent_pos.at(curr);\n            }\n            reverse(actions.begin(), actions.end());\n            return {cost, actions};\n        }\n\n        // Move\n        for (int i = 0; i < 4; ++i) {\n            Pos next_pos = {pos.r + dr[i], pos.c + dc[i]};\n            if (is_valid(next_pos) && !blocks.count(next_pos)) {\n                int next_cost = cost + 1;\n                if (!dist.count(next_pos) || next_cost < dist.at(next_pos)) {\n                    dist[next_pos] = next_cost;\n                    parent_pos[next_pos] = pos;\n                    parent_action[next_pos] = {'M', dir_char[i]};\n                    pq.push({next_cost + manhattan_distance(next_pos, end), next_pos});\n                }\n            }\n        }\n        \n        // Slide\n        for (int i = 0; i < 4; ++i) {\n            Pos stop_pos = pos;\n            Pos next_pos = {stop_pos.r + dr[i], stop_pos.c + dc[i]};\n            while (is_valid(next_pos) && !blocks.count(next_pos)) {\n                stop_pos = next_pos;\n                next_pos = {stop_pos.r + dr[i], stop_pos.c + dc[i]};\n            }\n            \n            if (stop_pos == pos) continue;\n\n            int next_cost = cost + 1;\n            if (!dist.count(stop_pos) || next_cost < dist.at(stop_pos)) {\n                dist[stop_pos] = next_cost;\n                parent_pos[stop_pos] = pos;\n                parent_action[stop_pos] = {'S', dir_char[i]};\n                pq.push({next_cost + manhattan_distance(stop_pos, end), stop_pos});\n            }\n        }\n    }\n\n    return {1000000, {}};\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N_in, M_in;\n    cin >> N_in >> M_in;\n\n    vector<Pos> targets(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> targets[i].r >> targets[i].c;\n    }\n\n    Pos current_pos = targets[0];\n    set<Pos> blocks;\n    vector<Action> total_actions;\n    \n    const int K = 20;\n\n    for (int k = 0; k < M - 1; ++k) {\n        Pos start_node = current_pos;\n        Pos end_node = targets[k + 1];\n\n        int best_cost = 1000000;\n        vector<Action> best_actions;\n        char best_plan_type = ' '; // B=base, A=add, R=remove\n        Pos best_alter_block, best_alter_adj;\n        \n        auto [base_cost, base_acts] = a_star_full(start_node, end_node, blocks);\n        if (base_cost < best_cost) {\n            best_cost = base_cost;\n            best_actions = base_acts;\n            best_plan_type = 'B';\n        }\n\n        auto dist_from_start = dijkstra(start_node, blocks);\n\n        set<Pos> cand_targets;\n        cand_targets.insert(end_node);\n        cand_targets.insert({start_node.r, end_node.c});\n        cand_targets.insert({end_node.r, start_node.c});\n        \n        set<Pos> cand_add_blocks;\n        for(const auto& t : cand_targets) {\n            for(int i=0; i<4; ++i) {\n                cand_add_blocks.insert({t.r + dr[i], t.c + dc[i]});\n            }\n        }\n\n        for (const auto& b : cand_add_blocks) {\n            if (!is_valid(b) || blocks.count(b)) continue;\n\n            set<Pos> next_blocks = blocks;\n            next_blocks.insert(b);\n            auto dist_to_end = dijkstra(end_node, next_blocks);\n            \n            for (int i = 0; i < 4; ++i) {\n                Pos adj_b = {b.r - dr[i], b.c - dc[i]};\n                if (!is_valid(adj_b) || blocks.count(adj_b)) continue;\n                \n                if (dist_from_start.count(adj_b) && dist_to_end.count(adj_b)) {\n                    int cost = dist_from_start.at(adj_b) + 1 + dist_to_end.at(adj_b);\n                    if (cost < best_cost) {\n                        best_cost = cost;\n                        best_plan_type = 'A';\n                        best_alter_block = b;\n                        best_alter_adj = adj_b;\n                    }\n                }\n            }\n        }\n\n        for (const auto& b : blocks) {\n            bool in_way = (b.r >= min(start_node.r, end_node.r) && b.r <= max(start_node.r, end_node.r) &&\n                          (b.c == start_node.c || b.c == end_node.c)) ||\n                          (b.c >= min(start_node.c, end_node.c) && b.c <= max(start_node.c, end_node.c) &&\n                          (b.r == start_node.r || b.r == end_node.r)) ||\n                          (b == end_node);\n            if (!in_way) continue;\n\n            set<Pos> next_blocks = blocks;\n            next_blocks.erase(b);\n            auto dist_to_end = dijkstra(end_node, next_blocks);\n\n            for (int i = 0; i < 4; ++i) {\n                Pos adj_b = {b.r - dr[i], b.c - dc[i]};\n                if (!is_valid(adj_b) || (blocks.count(adj_b) && !(adj_b == start_node) ) ) continue;\n                \n                if (dist_from_start.count(adj_b) && dist_to_end.count(adj_b)) {\n                    int cost = dist_from_start.at(adj_b) + 1 + dist_to_end.at(adj_b);\n                     if (cost < best_cost) {\n                        best_cost = cost;\n                        best_plan_type = 'R';\n                        best_alter_block = b;\n                        best_alter_adj = adj_b;\n                    }\n                }\n            }\n        }\n        \n        if (best_plan_type == 'B') {\n            total_actions.insert(total_actions.end(), best_actions.begin(), best_actions.end());\n        } else {\n            auto [c1, p1] = a_star_full(start_node, best_alter_adj, blocks);\n            total_actions.insert(total_actions.end(), p1.begin(), p1.end());\n            \n            char alter_dir = ' ';\n            for (int j = 0; j < 4; ++j) {\n                if (best_alter_block.r == best_alter_adj.r + dr[j] && best_alter_block.c == best_alter_adj.c + dc[j]) {\n                    alter_dir = dir_char[j];\n                    break;\n                }\n            }\n            total_actions.push_back({'A', alter_dir});\n\n            if (best_plan_type == 'A') {\n                blocks.insert(best_alter_block);\n            } else { // 'R'\n                blocks.erase(best_alter_block);\n            }\n            auto [c2, p2] = a_star_full(best_alter_adj, end_node, blocks);\n            total_actions.insert(total_actions.end(), p2.begin(), p2.end());\n        }\n        current_pos = end_node;\n\n        if (blocks.size() > K) {\n            Pos to_evict;\n            long long max_score = -1;\n\n            for (const auto& b : blocks) {\n                long long current_score = 0;\n                for (int i = k + 2; i < M; ++i) {\n                    current_score += manhattan_distance(b, targets[i]);\n                }\n                if (current_score > max_score) {\n                    max_score = current_score;\n                    to_evict = b;\n                }\n            }\n            \n            Pos adj_to_evict;\n            int min_dist = 1000000;\n            \n            auto dist_from_curr = dijkstra(current_pos, blocks);\n            \n            for (int i = 0; i < 4; ++i) {\n                Pos adj_b = {to_evict.r - dr[i], to_evict.c - dc[i]};\n                if (is_valid(adj_b) && !blocks.count(adj_b)) {\n                    if (dist_from_curr.count(adj_b)) {\n                        int d = dist_from_curr.at(adj_b);\n                        if (d < min_dist) {\n                            min_dist = d;\n                            adj_to_evict = adj_b;\n                        }\n                    }\n                }\n            }\n\n            if (min_dist < 1000000) {\n                auto [c, p] = a_star_full(current_pos, adj_to_evict, blocks);\n                total_actions.insert(total_actions.end(), p.begin(), p.end());\n                current_pos = adj_to_evict;\n\n                char alter_dir = ' ';\n                 for (int j = 0; j < 4; ++j) {\n                    if (to_evict.r == current_pos.r + dr[j] && to_evict.c == current_pos.c + dc[j]) {\n                        alter_dir = dir_char[j];\n                        break;\n                    }\n                }\n                total_actions.push_back({'A', alter_dir});\n                blocks.erase(to_evict);\n            }\n        }\n    }\n\n    for (const auto& action : total_actions) {\n        cout << action.act << \" \" << action.dir << \"\\n\";\n    }\n\n    return 0;\n}"},"2":{"ahc001":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <cfloat>\n\nstruct Company {\n    int id;\n    int x, y;\n    long long r;\n};\n\nstruct Rect {\n    int x1, y1, x2, y2;\n};\n\nstd::vector<Company> companies;\nstd::vector<Rect> result;\nstd::vector<bool> is_in_partition1;\n\nvoid solve(int x1, int y1, int x2, int y2, std::vector<int>& indices_by_x, std::vector<int>& indices_by_y) {\n    int n = indices_by_x.size();\n    if (n == 0) {\n        return;\n    }\n    if (n == 1) {\n        result[indices_by_x[0]] = {x1, y1, x2, y2};\n        return;\n    }\n\n    // --- Try vertical split ---\n    int best_k_v = -1;\n    int best_x_split = -1;\n    double min_badness_v = DBL_MAX;\n    \n    bool can_split_vert = companies[indices_by_x.front()].x < companies[indices_by_x.back()].x;\n\n    if (can_split_vert) {\n        long long total_r = 0;\n        for (int idx : indices_by_x) total_r += companies[idx].r;\n\n        long long current_r_sum = 0;\n        for (int k = 1; k < n; ++k) {\n            current_r_sum += companies[indices_by_x[k - 1]].r;\n            if (companies[indices_by_x[k - 1]].x < companies[indices_by_x[k]].x) {\n                double target_ratio = (double)current_r_sum / total_r;\n                double ideal_x_split = x1 + (double)(x2 - x1) * target_ratio;\n\n                long long lower_bound = companies[indices_by_x[k - 1]].x + 1;\n                long long upper_bound = companies[indices_by_x[k]].x;\n                \n                int x_split = round(ideal_x_split);\n                x_split = std::max((int)lower_bound, std::min((int)upper_bound, x_split));\n\n                double actual_ratio = (double)(x_split - x1) / (x2 - x1);\n                double diff = actual_ratio - target_ratio;\n                double badness = diff * diff;\n\n                if (badness < min_badness_v) {\n                    min_badness_v = badness;\n                    best_k_v = k;\n                    best_x_split = x_split;\n                }\n            }\n        }\n    }\n\n    // --- Try horizontal split ---\n    int best_k_h = -1;\n    int best_y_split = -1;\n    double min_badness_h = DBL_MAX;\n    \n    bool can_split_horiz = companies[indices_by_y.front()].y < companies[indices_by_y.back()].y;\n    \n    if (can_split_horiz) {\n        long long total_r = 0;\n        for (int idx : indices_by_y) total_r += companies[idx].r;\n\n        long long current_r_sum = 0;\n        for (int k = 1; k < n; ++k) {\n            current_r_sum += companies[indices_by_y[k - 1]].r;\n            if (companies[indices_by_y[k - 1]].y < companies[indices_by_y[k]].y) {\n                double target_ratio = (double)current_r_sum / total_r;\n                double ideal_y_split = y1 + (double)(y2 - y1) * target_ratio;\n\n                long long lower_bound = companies[indices_by_y[k - 1]].y + 1;\n                long long upper_bound = companies[indices_by_y[k]].y;\n\n                int y_split = round(ideal_y_split);\n                y_split = std::max((int)lower_bound, std::min((int)upper_bound, y_split));\n\n                double actual_ratio = (double)(y_split - y1) / (y2 - y1);\n                double diff = actual_ratio - target_ratio;\n                double badness = diff * diff;\n                \n                if (badness < min_badness_h) {\n                    min_badness_h = badness;\n                    best_k_h = k;\n                    best_y_split = y_split;\n                }\n            }\n        }\n    }\n    \n    // --- Decide and perform split ---\n    bool perform_vertical_split;\n    if (!can_split_vert) {\n        perform_vertical_split = false;\n    } else if (!can_split_horiz) {\n        perform_vertical_split = true;\n    } else {\n        if (min_badness_v < min_badness_h) {\n            perform_vertical_split = true;\n        } else if (min_badness_h < min_badness_v) {\n            perform_vertical_split = false;\n        } else {\n            // Tie-break by splitting the longer side\n            perform_vertical_split = (x2 - x1) >= (y2 - y1);\n        }\n    }\n\n    if (perform_vertical_split) {\n        int k = best_k_v;\n        for (int i = 0; i < k; ++i) is_in_partition1[indices_by_x[i]] = true;\n        for (int i = k; i < n; ++i) is_in_partition1[indices_by_x[i]] = false;\n\n        std::vector<int> left_indices_by_x(indices_by_x.begin(), indices_by_x.begin() + k);\n        std::vector<int> right_indices_by_x(indices_by_x.begin() + k, indices_by_x.end());\n\n        std::vector<int> left_indices_by_y, right_indices_by_y;\n        left_indices_by_y.reserve(k);\n        right_indices_by_y.reserve(n - k);\n        for (int idx : indices_by_y) {\n            if (is_in_partition1[idx]) {\n                left_indices_by_y.push_back(idx);\n            } else {\n                right_indices_by_y.push_back(idx);\n            }\n        }\n        solve(x1, y1, best_x_split, y2, left_indices_by_x, left_indices_by_y);\n        solve(best_x_split, y1, x2, y2, right_indices_by_x, right_indices_by_y);\n    } else { // Horizontal split\n        int k = best_k_h;\n        for (int i = 0; i < k; ++i) is_in_partition1[indices_by_y[i]] = true;\n        for (int i = k; i < n; ++i) is_in_partition1[indices_by_y[i]] = false;\n\n        std::vector<int> bottom_indices_by_y(indices_by_y.begin(), indices_by_y.begin() + k);\n        std::vector<int> top_indices_by_y(indices_by_y.begin() + k, indices_by_y.end());\n\n        std::vector<int> bottom_indices_by_x, top_indices_by_x;\n        bottom_indices_by_x.reserve(k);\n        top_indices_by_x.reserve(n - k);\n\n        for (int idx : indices_by_x) {\n            if (is_in_partition1[idx]) {\n                bottom_indices_by_x.push_back(idx);\n            } else {\n                top_indices_by_x.push_back(idx);\n            }\n        }\n        solve(x1, y1, x2, best_y_split, bottom_indices_by_x, bottom_indices_by_y);\n        solve(x1, best_y_split, x2, y2, top_indices_by_x, top_indices_by_y);\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int n;\n    std::cin >> n;\n    companies.resize(n);\n    result.resize(n);\n    is_in_partition1.resize(n);\n\n    std::vector<int> indices_by_x(n), indices_by_y(n);\n    for (int i = 0; i < n; ++i) {\n        companies[i].id = i;\n        std::cin >> companies[i].x >> companies[i].y >> companies[i].r;\n        indices_by_x[i] = i;\n        indices_by_y[i] = i;\n    }\n\n    std::sort(indices_by_x.begin(), indices_by_x.end(), [&](int a, int b) {\n        if (companies[a].x != companies[b].x) return companies[a].x < companies[b].x;\n        return companies[a].y < companies[b].y;\n    });\n    std::sort(indices_by_y.begin(), indices_by_y.end(), [&](int a, int b) {\n        if (companies[a].y != companies[b].y) return companies[a].y < companies[b].y;\n        return companies[a].x < companies[b].x;\n    });\n\n    solve(0, 0, 10000, 10000, indices_by_x, indices_by_y);\n\n    for (int i = 0; i < n; ++i) {\n        std::cout << result[i].x1 << \" \" << result[i].y1 << \" \" << result[i].x2 << \" \" << result[i].y2 << \"\\n\";\n    }\n\n    return 0;\n}","ahc002":"#include <iostream>\n#include <vector>\n#include <string>\n#include <map>\n#include <utility>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n\n// Fast I/O\nvoid fast_io() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n}\n\n// Timer\nstruct Timer {\n    std::chrono::steady_clock::time_point start_time;\n    Timer() : start_time(std::chrono::steady_clock::now()) {}\n    long long get_ms() {\n        return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count();\n    }\n};\n\nconstexpr int N = 50;\n\n#ifdef LOCAL_TEST\nconstexpr int TIME_LIMIT_MS = 1980;\nconstexpr int BEAM_WIDTH = 200;\n#else\nconstexpr int TIME_LIMIT_MS = 1980;\nconstexpr int BEAM_WIDTH = 2000;\n#endif\n\nint si, sj;\nint t[N][N];\nint p[N][N];\n\nstruct Tile {\n    int id;\n    std::vector<std::pair<int, int>> squares;\n};\n\nint tile_id_map[N][N];\nstd::vector<Tile> tiles;\nint M; // number of tiles\n\nstruct State {\n    long long score;\n    std::pair<int, int> pos;\n    std::vector<bool> visited_tiles;\n\n    int prev_idx_in_history;\n    std::string path_segment;\n};\n\nchar get_move_char(const std::pair<int, int>& from, const std::pair<int, int>& to) {\n    if (to.first == from.first - 1 && to.second == from.second) return 'U';\n    if (to.first == from.first + 1 && to.second == from.second) return 'D';\n    if (to.second == from.second - 1 && to.first == from.first) return 'L';\n    if (to.second == from.second + 1 && to.first == from.first) return 'R';\n    return ' '; // Should not happen\n}\n\nvoid solve() {\n    Timer timer;\n\n    std::cin >> si >> sj;\n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) std::cin >> t[i][j];\n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) std::cin >> p[i][j];\n\n    std::map<int, int> raw_id_to_my_id;\n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) {\n        if (raw_id_to_my_id.find(t[i][j]) == raw_id_to_my_id.end()) {\n            raw_id_to_my_id[t[i][j]] = raw_id_to_my_id.size();\n        }\n    }\n    M = raw_id_to_my_id.size();\n    tiles.resize(M);\n    for (int i=0; i<M; ++i) tiles[i].id = i;\n\n    for (int i=0; i<N; ++i) for(int j=0; j<N; ++j) {\n        int my_id = raw_id_to_my_id[t[i][j]];\n        tile_id_map[i][j] = my_id;\n        tiles[my_id].squares.push_back({i,j});\n    }\n\n    State initial_state;\n    int start_tile_id = tile_id_map[si][sj];\n    const auto& start_tile = tiles[start_tile_id];\n    \n    initial_state.score = 0;\n    initial_state.visited_tiles.assign(M, false);\n    initial_state.visited_tiles[start_tile_id] = true;\n    initial_state.prev_idx_in_history = -1;\n\n    std::pair<int, int> current_pos = {si, sj};\n    initial_state.score += p[si][sj];\n\n    if (start_tile.squares.size() == 2) {\n        std::pair<int, int> other_pos = (start_tile.squares[0] == current_pos) ? start_tile.squares[1] : start_tile.squares[0];\n        char move = get_move_char(current_pos, other_pos);\n        initial_state.path_segment += move;\n        initial_state.score += p[other_pos.first][other_pos.second];\n        current_pos = other_pos;\n    }\n    initial_state.pos = current_pos;\n\n    long long best_score = initial_state.score;\n    std::pair<int, int> best_state_locus = {0, 0};\n\n    std::vector<std::vector<State>> history;\n    std::vector<State> beam;\n    beam.push_back(std::move(initial_state));\n    history.push_back(std::move(beam));\n    \n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n    char move_chars[] = {'U', 'D', 'L', 'R'};\n\n    while (timer.get_ms() < TIME_LIMIT_MS) {\n        const auto& current_beam = history.back();\n        std::vector<State> candidates;\n        \n        for (int i = 0; i < current_beam.size(); ++i) {\n            const auto& s = current_beam[i];\n            int r = s.pos.first;\n            int c = s.pos.second;\n\n            for (int k = 0; k < 4; ++k) {\n                int nr = r + dr[k];\n                int nc = c + dc[k];\n\n                if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n\n                int next_tile_id = tile_id_map[nr][nc];\n                if (s.visited_tiles[next_tile_id]) continue;\n\n                State new_s;\n                new_s.visited_tiles = s.visited_tiles;\n                new_s.visited_tiles[next_tile_id] = true;\n\n                std::string path_ext;\n                long long score_ext = 0;\n                std::pair<int, int> next_pos = {nr, nc};\n\n                path_ext += move_chars[k];\n                score_ext += p[nr][nc];\n\n                const auto& next_tile = tiles[next_tile_id];\n                if (next_tile.squares.size() == 2) {\n                    std::pair<int, int> other_pos = (next_tile.squares[0] == next_pos) ? next_tile.squares[1] : next_tile.squares[0];\n                    char move = get_move_char(next_pos, other_pos);\n                    path_ext += move;\n                    score_ext += p[other_pos.first][other_pos.second];\n                    next_pos = other_pos;\n                }\n                \n                new_s.score = s.score + score_ext;\n                new_s.pos = next_pos;\n                new_s.path_segment = path_ext;\n                new_s.prev_idx_in_history = i;\n                candidates.push_back(std::move(new_s));\n            }\n        }\n\n        if (candidates.empty()) break;\n\n        size_t sort_end_idx = std::min((size_t)candidates.size(), (size_t)BEAM_WIDTH);\n        std::partial_sort(candidates.begin(), candidates.begin() + sort_end_idx, candidates.end(), \n            [](const State& a, const State& b){ return a.score > b.score; });\n\n        std::vector<State> next_beam;\n        next_beam.reserve(sort_end_idx);\n        for (int i = 0; i < sort_end_idx; ++i) {\n            next_beam.push_back(std::move(candidates[i]));\n        }\n        \n        if (next_beam[0].score > best_score) {\n            best_score = next_beam[0].score;\n            best_state_locus = {(int)history.size(), 0};\n        }\n        history.push_back(std::move(next_beam));\n    }\n    \n    std::string final_path = \"\";\n    int hist_idx = best_state_locus.first;\n    int beam_idx = best_state_locus.second;\n    while (hist_idx >= 0) {\n        const auto& s = history[hist_idx][beam_idx];\n        final_path = s.path_segment + final_path;\n        if (s.prev_idx_in_history == -1) break;\n        beam_idx = s.prev_idx_in_history;\n        hist_idx--;\n    }\n    std::cout << final_path << std::endl;\n}\n\nint main() {\n    fast_io();\n    solve();\n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <numeric>\n#include <random>\n#include <algorithm>\n#include <iomanip>\n#include <chrono>\n\n// Constants\nconstexpr int GRID_SIZE = 30;\nconstexpr int NUM_QUERIES = 1000;\n\n// Grid coordinates\nstruct Point {\n    int r, c;\n    bool operator==(const Point& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Point& other) const {\n        return !(*this == other);\n    }\n};\n\n// For priority queue in Dijkstra\nstruct State {\n    Point pos;\n    double dist;\n\n    bool operator>(const State& other) const {\n        return dist > other.dist;\n    }\n};\n\n// Global state for our estimates and models\ndouble est_h[GRID_SIZE][GRID_SIZE - 1]; // Raw estimates\ndouble est_v[GRID_SIZE - 1][GRID_SIZE];\ndouble model_h[GRID_SIZE][GRID_SIZE - 1]; // Smoothed/model-based estimates\ndouble model_v[GRID_SIZE - 1][GRID_SIZE];\nint updates_h[GRID_SIZE][GRID_SIZE - 1];\nint updates_v[GRID_SIZE - 1][GRID_SIZE];\n\n// Randomness\nstd::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// Helper function to check bounds\nbool is_valid(int r, int c) {\n    return r >= 0 && r < GRID_SIZE && c >= 0 && c < GRID_SIZE;\n}\n\n// Dijkstra's algorithm\nPoint parent[GRID_SIZE][GRID_SIZE];\nchar move_char[GRID_SIZE][GRID_SIZE];\ndouble dist[GRID_SIZE][GRID_SIZE];\n\nstd::string find_path(Point start, Point goal, int k) {\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            dist[i][j] = 1e18;\n        }\n    }\n\n    std::priority_queue<State, std::vector<State>, std::greater<State>> pq;\n\n    dist[start.r][start.c] = 0;\n    pq.push({start, 0.0});\n\n    double progress = static_cast<double>(k) / (NUM_QUERIES - 1);\n    double C_k = 0.3 * (1.0 - std::pow(progress, 1.5));\n    if (k > NUM_QUERIES - 50) C_k = 0;\n\n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n    char moves[] = {'U', 'D', 'L', 'R'};\n\n    while (!pq.empty()) {\n        State current = pq.top();\n        pq.pop();\n\n        Point pos = current.pos;\n\n        if (current.dist > dist[pos.r][pos.c]) {\n            continue;\n        }\n\n        if (pos == goal) {\n            break;\n        }\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = pos.r + dr[i];\n            int nc = pos.c + dc[i];\n\n            if (!is_valid(nr, nc)) {\n                continue;\n            }\n\n            double edge_cost;\n            if (i == 0) { // Up\n                edge_cost = model_v[nr][nc];\n            } else if (i == 1) { // Down\n                edge_cost = model_v[pos.r][pos.c];\n            } else if (i == 2) { // Left\n                edge_cost = model_h[nr][nc];\n            } else { // Right\n                edge_cost = model_h[pos.r][pos.c];\n            }\n            \n            std::uniform_real_distribution<double> dist_expl(1.0 - C_k, 1.0 + C_k);\n            double noisy_cost = edge_cost * dist_expl(rng);\n            \n            if (dist[pos.r][pos.c] + noisy_cost < dist[nr][nc]) {\n                dist[nr][nc] = dist[pos.r][pos.c] + noisy_cost;\n                parent[nr][nc] = pos;\n                move_char[nr][nc] = moves[i];\n                pq.push({{nr, nc}, dist[nr][nc]});\n            }\n        }\n    }\n\n    std::string path_str = \"\";\n    Point current = goal;\n    while (current != start) {\n        path_str += move_char[current.r][current.c];\n        current = parent[current.r][current.c];\n    }\n    std::reverse(path_str.begin(), path_str.end());\n    return path_str;\n}\n\nvoid update_estimates(const std::string& path_str, Point start, long long noisy_path_length, int k) {\n    if (path_str.empty()) return;\n\n    double estimated_length = 0;\n    double Z = 0.0;\n    \n    Point current = start;\n    // First pass: calculate estimated length and normalization factor Z for weighted SGD\n    for (char move : path_str) {\n        Point next = current;\n        if (move == 'U') {\n            next.r--;\n            estimated_length += est_v[next.r][next.c];\n            Z += 1.0 / (updates_v[next.r][next.c] + 1.0);\n        } else if (move == 'D') {\n            estimated_length += est_v[current.r][current.c];\n            Z += 1.0 / (updates_v[current.r][current.c] + 1.0);\n            next.r++;\n        } else if (move == 'L') {\n            next.c--;\n            estimated_length += est_h[next.r][next.c];\n            Z += 1.0 / (updates_h[next.r][next.c] + 1.0);\n        } else if (move == 'R') {\n            estimated_length += est_h[current.r][current.c];\n            Z += 1.0 / (updates_h[current.r][current.c] + 1.0);\n            next.c++;\n        }\n        current = next;\n    }\n    \n    if (Z < 1e-9) return;\n\n    double error = static_cast<double>(noisy_path_length) - estimated_length;\n    double alpha_k = 0.5 * std::pow(0.01, static_cast<double>(k) / (NUM_QUERIES - 1));\n    double base_update = alpha_k * error / Z;\n\n    current = start;\n    // Second pass: apply updates\n    for (char move : path_str) {\n        Point next = current;\n        if (move == 'U') {\n            next.r--;\n            double weight = 1.0 / (updates_v[next.r][next.c] + 1.0);\n            est_v[next.r][next.c] += base_update * weight;\n            est_v[next.r][next.c] = std::clamp(est_v[next.r][next.c], 100.0, 15000.0);\n            updates_v[next.r][next.c]++;\n        } else if (move == 'D') {\n            double weight = 1.0 / (updates_v[current.r][current.c] + 1.0);\n            est_v[current.r][current.c] += base_update * weight;\n            est_v[current.r][current.c] = std::clamp(est_v[current.r][current.c], 100.0, 15000.0);\n            updates_v[current.r][current.c]++;\n            next.r++;\n        } else if (move == 'L') {\n            next.c--;\n            double weight = 1.0 / (updates_h[next.r][next.c] + 1.0);\n            est_h[next.r][next.c] += base_update * weight;\n            est_h[next.r][next.c] = std::clamp(est_h[next.r][next.c], 100.0, 15000.0);\n            updates_h[next.r][next.c]++;\n        } else if (move == 'R') {\n            double weight = 1.0 / (updates_h[current.r][current.c] + 1.0);\n            est_h[current.r][current.c] += base_update * weight;\n            est_h[current.r][current.c] = std::clamp(est_h[current.r][current.c], 100.0, 15000.0);\n            updates_h[current.r][current.c]++;\n            next.c++;\n        }\n        current = next;\n    }\n}\n\nvoid update_model() {\n    // Horizontal edges\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        std::vector<double> val_pref(GRID_SIZE - 1, 0.0);\n        std::vector<double> sq_val_pref(GRID_SIZE - 1, 0.0);\n        std::vector<int> count_pref(GRID_SIZE - 1, 0);\n\n        if (updates_h[i][0] > 0) {\n            val_pref[0] = est_h[i][0];\n            sq_val_pref[0] = est_h[i][0] * est_h[i][0];\n            count_pref[0] = 1;\n        }\n        for (int j = 1; j < GRID_SIZE - 1; ++j) {\n            val_pref[j] = val_pref[j - 1];\n            sq_val_pref[j] = sq_val_pref[j - 1];\n            count_pref[j] = count_pref[j - 1];\n            if (updates_h[i][j] > 0) {\n                val_pref[j] += est_h[i][j];\n                sq_val_pref[j] += est_h[i][j] * est_h[i][j];\n                count_pref[j]++;\n            }\n        }\n\n        int total_count = count_pref[GRID_SIZE - 2];\n        if (total_count == 0) continue;\n\n        double total_sum = val_pref[GRID_SIZE - 2];\n        double total_sq_sum = sq_val_pref[GRID_SIZE - 2];\n        double mean1 = total_sum / total_count;\n        double sse1 = total_sq_sum - total_sum * mean1;\n\n        for (int j = 0; j < GRID_SIZE - 1; ++j) model_h[i][j] = mean1;\n        \n        if (total_count >= 2) {\n            double best_sse2 = 1e18;\n            int best_split = -1;\n            double best_mean_l = 0, best_mean_r = 0;\n\n            for (int split = 1; split < GRID_SIZE - 1; ++split) {\n                int count_l = count_pref[split - 1];\n                int count_r = total_count - count_l;\n                if (count_l < 1 || count_r < 1) continue;\n\n                double sum_l = val_pref[split - 1];\n                double sq_sum_l = sq_val_pref[split - 1];\n                double mean_l = sum_l / count_l;\n                double sse_l = sq_sum_l - sum_l * mean_l;\n\n                double sum_r = total_sum - sum_l;\n                double sq_sum_r = total_sq_sum - sq_sum_l;\n                double mean_r = sum_r / count_r;\n                double sse_r = sq_sum_r - sum_r * mean_r;\n                \n                if (sse_l + sse_r < best_sse2) {\n                    best_sse2 = sse_l + sse_r;\n                    best_split = split;\n                    best_mean_l = mean_l;\n                    best_mean_r = mean_r;\n                }\n            }\n\n            if (best_split != -1 && sse1 > 1e-9) {\n                if (total_count * log(best_sse2 / sse1) < -log(static_cast<double>(total_count))) {\n                    for (int j = 0; j < best_split; ++j) model_h[i][j] = best_mean_l;\n                    for (int j = best_split; j < GRID_SIZE - 1; ++j) model_h[i][j] = best_mean_r;\n                }\n            }\n        }\n    }\n\n    // Vertical edges\n    for (int j = 0; j < GRID_SIZE; ++j) {\n        std::vector<double> val_pref(GRID_SIZE - 1, 0.0);\n        std::vector<double> sq_val_pref(GRID_SIZE - 1, 0.0);\n        std::vector<int> count_pref(GRID_SIZE - 1, 0);\n\n        if (updates_v[0][j] > 0) {\n            val_pref[0] = est_v[0][j];\n            sq_val_pref[0] = est_v[0][j] * est_v[0][j];\n            count_pref[0] = 1;\n        }\n        for (int i = 1; i < GRID_SIZE - 1; ++i) {\n            val_pref[i] = val_pref[i - 1];\n            sq_val_pref[i] = sq_val_pref[i - 1];\n            count_pref[i] = count_pref[i - 1];\n            if (updates_v[i][j] > 0) {\n                val_pref[i] += est_v[i][j];\n                sq_val_pref[i] += est_v[i][j] * est_v[i][j];\n                count_pref[i]++;\n            }\n        }\n\n        int total_count = count_pref[GRID_SIZE - 2];\n        if (total_count == 0) continue;\n\n        double total_sum = val_pref[GRID_SIZE - 2];\n        double total_sq_sum = sq_val_pref[GRID_SIZE - 2];\n        double mean1 = total_sum / total_count;\n        double sse1 = total_sq_sum - total_sum * mean1;\n        \n        for (int i = 0; i < GRID_SIZE - 1; ++i) model_v[i][j] = mean1;\n        \n        if (total_count >= 2) {\n            double best_sse2 = 1e18;\n            int best_split = -1;\n            double best_mean_u = 0, best_mean_d = 0;\n\n            for (int split = 1; split < GRID_SIZE - 1; ++split) {\n                int count_u = count_pref[split - 1];\n                int count_d = total_count - count_u;\n                if (count_u < 1 || count_d < 1) continue;\n\n                double sum_u = val_pref[split - 1];\n                double sq_sum_u = sq_val_pref[split - 1];\n                double mean_u = sum_u / count_u;\n                double sse_u = sq_sum_u - sum_u * mean_u;\n\n                double sum_d = total_sum - sum_u;\n                double sq_sum_d = total_sq_sum - sq_sum_u;\n                double mean_d = sum_d / count_d;\n                double sse_d = sq_sum_d - sum_d * mean_d;\n                \n                if (sse_u + sse_d < best_sse2) {\n                    best_sse2 = sse_u + sse_d;\n                    best_split = split;\n                    best_mean_u = mean_u;\n                    best_mean_d = mean_d;\n                }\n            }\n            \n            if (best_split != -1 && sse1 > 1e-9) {\n                 if (total_count * log(best_sse2 / sse1) < -log(static_cast<double>(total_count))) {\n                    for (int i = 0; i < best_split; ++i) model_v[i][j] = best_mean_u;\n                    for (int i = best_split; i < GRID_SIZE - 1; ++i) model_v[i][j] = best_mean_d;\n                }\n            }\n        }\n    }\n}\n\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE - 1; ++j) {\n            est_h[i][j] = model_h[i][j] = 5000.0;\n            updates_h[i][j] = 0;\n        }\n    }\n    for (int i = 0; i < GRID_SIZE - 1; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            est_v[i][j] = model_v[i][j] = 5000.0;\n            updates_v[i][j] = 0;\n        }\n    }\n\n    for (int k = 0; k < NUM_QUERIES; ++k) {\n        Point start, goal;\n        std::cin >> start.r >> start.c >> goal.r >> goal.c;\n\n        std::string path = find_path(start, goal, k);\n        std::cout << path << std::endl;\n\n        long long noisy_path_length;\n        std::cin >> noisy_path_length;\n\n        update_estimates(path, start, noisy_path_length, k);\n        update_model();\n    }\n\n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <chrono>\n#include <random>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <map>\n\n// --- Constants and Globals ---\nconstexpr int N_CONST = 20;\nconstexpr int NUM_CHARS = 8;\nconstexpr long long W_CONFLICT = 10000;\nconst double TIME_LIMIT = 2.95;\n\nint N_in, M;\nstd::vector<std::string> S;\nstd::vector<int> S_len;\nstd::vector<std::vector<int>> S_int;\n\nstd::mt19937 rng;\nstd::chrono::steady_clock::time_point start_time;\n\nstruct Placement {\n    int r, c, dir; // dir=0: horizontal, dir=1: vertical\n    bool operator==(const Placement& other) const {\n        return r == other.r && c == other.c && dir == other.dir;\n    }\n};\n\n// --- State Representation ---\nstd::vector<Placement> current_placements;\nstd::vector<Placement> best_placements;\nlong long current_energy;\nlong long best_energy;\n\nint counts[N_CONST][N_CONST][NUM_CHARS];\nint covered_count[N_CONST][N_CONST];\n\n// --- Utilities ---\nint ctoi(char c) { return c - 'A'; }\nchar itoc(int i) { return (char)('A' + i); }\n\n// --- Core Logic ---\nstd::pair<long long, int> get_cell_energy_contrib(int r, int c) {\n    if (covered_count[r][c] == 0) {\n        return {0, 0};\n    }\n    int max_c = 0;\n    for (int k = 0; k < NUM_CHARS; ++k) {\n        max_c = std::max(max_c, counts[r][c][k]);\n    }\n    long long conflict_contrib = covered_count[r][c] - max_c;\n    int covered_contrib = 1;\n    return {conflict_contrib, covered_contrib};\n}\n\nvoid update_state_for_move(int str_idx, const Placement& p, int sign) {\n    const auto& s = S_int[str_idx];\n    int len = S_len[str_idx];\n    if (p.dir == 0) { // Horizontal\n        for (int i = 0; i < len; ++i) {\n            int r = p.r;\n            int c = (p.c + i) % N_CONST;\n            counts[r][c][s[i]] += sign;\n            covered_count[r][c] += sign;\n        }\n    } else { // Vertical\n        for (int i = 0; i < len; ++i) {\n            int r = (p.r + i) % N_CONST;\n            int c = p.c;\n            counts[r][c][s[i]] += sign;\n            covered_count[r][c] += sign;\n        }\n    }\n}\n\nlong long calculate_delta_energy(int str_idx, const Placement& old_p, const Placement& new_p) {\n    long long delta = 0;\n    const auto& s = S_int[str_idx];\n    int len = S_len[str_idx];\n    \n    std::vector<std::pair<int, int>> affected_coords;\n    if (old_p.dir == 0) for (int i=0; i<len; ++i) affected_coords.push_back({old_p.r, (old_p.c+i)%N_CONST});\n    else for (int i=0; i<len; ++i) affected_coords.push_back({(old_p.r+i)%N_CONST, old_p.c});\n    \n    if (new_p.dir == 0) for (int i=0; i<len; ++i) affected_coords.push_back({new_p.r, (new_p.c+i)%N_CONST});\n    else for (int i=0; i<len; ++i) affected_coords.push_back({(new_p.r+i)%N_CONST, new_p.c});\n\n    std::sort(affected_coords.begin(), affected_coords.end());\n    affected_coords.erase(std::unique(affected_coords.begin(), affected_coords.end()), affected_coords.end());\n\n    for (const auto& cell : affected_coords) {\n        int r = cell.first;\n        int c = cell.second;\n\n        auto [conflicts_before, covered_before] = get_cell_energy_contrib(r, c);\n        delta -= (conflicts_before * W_CONFLICT + covered_before);\n\n        int old_p_char = -1, new_p_char = -1;\n        if (old_p.dir == 0) {\n            if (r == old_p.r && (c - old_p.c + N_CONST)%N_CONST < len) old_p_char = s[(c-old_p.c+N_CONST)%N_CONST];\n        } else {\n            if (c == old_p.c && (r - old_p.r + N_CONST)%N_CONST < len) old_p_char = s[(r-old_p.r+N_CONST)%N_CONST];\n        }\n        if (new_p.dir == 0) {\n            if (r == new_p.r && (c - new_p.c + N_CONST)%N_CONST < len) new_p_char = s[(c-new_p.c+N_CONST)%N_CONST];\n        } else {\n            if (c == new_p.c && (r - new_p.r + N_CONST)%N_CONST < len) new_p_char = s[(r-new_p.r+N_CONST)%N_CONST];\n        }\n        \n        int new_covered_total = covered_count[r][c];\n        if(old_p_char != -1) new_covered_total--;\n        if(new_p_char != -1) new_covered_total++;\n\n        if (new_covered_total > 0) {\n            int max_c = 0;\n            for (int k=0; k<NUM_CHARS; ++k) {\n                int current_cnt = counts[r][c][k];\n                if(k == old_p_char) current_cnt--;\n                if(k == new_p_char) current_cnt++;\n                max_c = std::max(max_c, current_cnt);\n            }\n            long long conflicts_after = new_covered_total - max_c;\n            delta += (conflicts_after * W_CONFLICT + 1);\n        }\n    }\n    return delta;\n}\n\nvoid greedy_initialization() {\n    current_placements.resize(M);\n    std::vector<int> p(M);\n    std::iota(p.begin(), p.end(), 0);\n    std::sort(p.begin(), p.end(), [&](int i, int j){ return S_len[i] > S_len[j]; });\n\n    std::vector<std::vector<int>> grid(N_CONST, std::vector<int>(N_CONST, -1));\n\n    for (int str_idx : p) {\n        Placement best_p;\n        int min_conflicts = 1e9;\n        for (int r = 0; r < N_CONST; ++r) {\n        for (int c = 0; c < N_CONST; ++c) {\n        for (int dir = 0; dir < 2; ++dir) {\n            int current_conflicts = 0;\n            const auto& s = S_int[str_idx];\n            int len = S_len[str_idx];\n            if (dir == 0) {\n                for (int i = 0; i < len; ++i) {\n                    if (grid[r][(c + i) % N_CONST] != -1 && grid[r][(c + i) % N_CONST] != s[i]) current_conflicts++;\n                }\n            } else {\n                for (int i = 0; i < len; ++i) {\n                    if (grid[(r + i) % N_CONST][c] != -1 && grid[(r + i) % N_CONST][c] != s[i]) current_conflicts++;\n                }\n            }\n            if (current_conflicts < min_conflicts) {\n                min_conflicts = current_conflicts;\n                best_p = {r, c, dir};\n            }\n        }}}\n        current_placements[str_idx] = best_p;\n        const auto& s = S_int[str_idx];\n        int len = S_len[str_idx];\n        if (best_p.dir == 0) for(int i=0; i<len; ++i) grid[best_p.r][(best_p.c+i)%N_CONST] = s[i];\n        else for(int i=0; i<len; ++i) grid[(best_p.r+i)%N_CONST][best_p.c] = s[i];\n    }\n}\n\nlong long calculate_full_energy() {\n    long long total_conflicts = 0;\n    int total_covered = 0;\n    for (int r = 0; r < N_CONST; ++r) {\n        for (int c = 0; c < N_CONST; ++c) {\n            auto [conflicts, covered] = get_cell_energy_contrib(r, c);\n            total_conflicts += conflicts;\n            total_covered += covered;\n        }\n    }\n    return total_conflicts * W_CONFLICT + total_covered;\n}\n\n\nvoid solve() {\n    start_time = std::chrono::steady_clock::now();\n    rng.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    S_int.resize(M); S_len.resize(M);\n    for (int i = 0; i < M; ++i) {\n        S_len[i] = S[i].length();\n        S_int[i].resize(S_len[i]);\n        for (int j = 0; j < S_len[i]; ++j) S_int[i][j] = ctoi(S[i][j]);\n    }\n\n    greedy_initialization();\n    for (int i = 0; i < M; ++i) {\n        update_state_for_move(i, current_placements[i], +1);\n    }\n    \n    current_energy = calculate_full_energy();\n    best_energy = current_energy;\n    best_placements = current_placements;\n\n    double start_temp = 5000.0;\n    double end_temp = 0.1;\n    \n    while (true) {\n        auto now = std::chrono::steady_clock::now();\n        double elapsed_time = std::chrono::duration_cast<std::chrono::duration<double>>(now - start_time).count();\n        if (elapsed_time > TIME_LIMIT) break;\n\n        double temp = start_temp * std::pow(end_temp / start_temp, elapsed_time / TIME_LIMIT);\n\n        int str_idx = std::uniform_int_distribution<int>(0, M - 1)(rng);\n        Placement old_p = current_placements[str_idx];\n        Placement new_p;\n\n        double p_powerful = 0.2 + 0.6 * (elapsed_time / TIME_LIMIT);\n\n        if (std::uniform_real_distribution<double>(0.0, 1.0)(rng) < p_powerful) {\n            // Powerful move: local search for the best placement\n            Placement best_p_candidate = old_p;\n            long long min_delta = 0;\n\n            for (int r = 0; r < N_CONST; ++r) {\n            for (int c = 0; c < N_CONST; ++c) {\n            for (int dir = 0; dir < 2; ++dir) {\n                Placement p_candidate = {r, c, dir};\n                if (p_candidate == old_p) continue;\n                long long delta = calculate_delta_energy(str_idx, old_p, p_candidate);\n                if (delta < min_delta) {\n                    min_delta = delta;\n                    best_p_candidate = p_candidate;\n                }\n            }}}\n            new_p = best_p_candidate;\n\n        } else {\n            // Simple move\n            if (std::uniform_real_distribution<>(0.0, 1.0)(rng) < 0.1) { // local\n                 new_p = old_p;\n                 int move_type = std::uniform_int_distribution<int>(0, 2)(rng);\n                 if (move_type == 0) new_p.r = (new_p.r + std::uniform_int_distribution<int>(-2, 2)(rng) + N_CONST) % N_CONST;\n                 else if (move_type == 1) new_p.c = (new_p.c + std::uniform_int_distribution<int>(-2, 2)(rng) + N_CONST) % N_CONST;\n                 else new_p.dir = 1 - new_p.dir;\n            } else { // random\n                new_p = {\n                    std::uniform_int_distribution<int>(0, N_CONST - 1)(rng),\n                    std::uniform_int_distribution<int>(0, N_CONST - 1)(rng),\n                    std::uniform_int_distribution<int>(0, 1)(rng)\n                };\n            }\n        }\n        \n        if (old_p == new_p) continue;\n        \n        long long delta_energy = calculate_delta_energy(str_idx, old_p, new_p);\n\n        if (delta_energy <= 0 || std::uniform_real_distribution<double>(0.0, 1.0)(rng) < std::exp(-delta_energy / temp)) {\n            current_energy += delta_energy;\n            update_state_for_move(str_idx, old_p, -1);\n            update_state_for_move(str_idx, new_p, +1);\n            current_placements[str_idx] = new_p;\n\n            if (current_energy < best_energy) {\n                best_energy = current_energy;\n                best_placements = current_placements;\n            }\n        }\n    }\n\n    // Bug fix: Reconstruct grid using best_placements and majority vote\n    std::fill(&counts[0][0][0], &counts[0][0][0] + sizeof(counts)/sizeof(int), 0);\n    std::fill(&covered_count[0][0], &covered_count[0][0] + sizeof(covered_count)/sizeof(int), 0);\n    for(int i=0; i<M; ++i) {\n        update_state_for_move(i, best_placements[i], +1);\n    }\n    \n    std::vector<std::string> final_grid(N_CONST, std::string(N_CONST, '.'));\n    for (int r = 0; r < N_CONST; ++r) {\n        for (int c = 0; c < N_CONST; ++c) {\n            if (covered_count[r][c] > 0) {\n                int max_k = 0, max_cnt = 0;\n                for (int k = 0; k < NUM_CHARS; ++k) {\n                    if (counts[r][c][k] > max_cnt) {\n                        max_cnt = counts[r][c][k];\n                        max_k = k;\n                    }\n                }\n                final_grid[r][c] = itoc(max_k);\n            }\n        }\n    }\n\n    for (int i = 0; i < N_CONST; ++i) {\n        std::cout << final_grid[i] << std::endl;\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    std::cin >> N_in >> M;\n    S.resize(M);\n    for (int i = 0; i < M; ++i) std::cin >> S[i];\n    solve();\n    return 0;\n}","ahc005":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <map>\n#include <set>\n#include <algorithm>\n#include <chrono>\n#include <random>\n\nusing namespace std;\n\n// Timer\nchrono::high_resolution_clock::time_point start_time;\n\n// Constants\nconst int INF = 1e9;\nconst int DR[] = {-1, 1, 0, 0};\nconst int DC[] = {0, 0, -1, 1};\nconst char MOVES[] = {'U', 'D', 'L', 'R'};\n\n// Globals\nint N, si, sj;\nvector<string> grid;\nvector<pair<int, int>> road_squares;\nmap<pair<int, int>, int> coord_to_id;\nvector<vector<pair<int, int>>> adj;\n\nstruct Segment {\n    int id;\n    vector<pair<int, int>> squares;\n};\nvector<Segment> segments;\n\n// Pre-computation functions\nvoid find_road_squares_and_build_graph() {\n    int current_id = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != '#') {\n                road_squares.push_back({i, j});\n                coord_to_id[{i, j}] = current_id++;\n            }\n        }\n    }\n\n    adj.resize(road_squares.size());\n    for (size_t i = 0; i < road_squares.size(); ++i) {\n        auto [r, c] = road_squares[i];\n        for (int move = 0; move < 4; ++move) {\n            int nr = r + DR[move];\n            int nc = c + DC[move];\n            if (nr >= 0 && nr < N && nc >= 0 && nc < N && grid[nr][nc] != '#') {\n                int neighbor_id = coord_to_id.at({nr, nc});\n                int cost = grid[nr][nc] - '0';\n                adj[i].push_back({neighbor_id, cost});\n            }\n        }\n    }\n}\n\nvoid find_segments() {\n    map<pair<int, int>, bool> visited_horz, visited_vert;\n    int seg_id_counter = 0;\n    for (const auto& p : road_squares) {\n        int r = p.first;\n        int c = p.second;\n\n        if (visited_horz.find(p) == visited_horz.end()) {\n            Segment seg;\n            seg.id = seg_id_counter++;\n            int c_start = c;\n            while (c_start > 0 && grid[r][c_start - 1] != '#') {\n                c_start--;\n            }\n            int c_end = c;\n            while (c_end < N - 1 && grid[r][c_end + 1] != '#') {\n                c_end++;\n            }\n            for (int j = c_start; j <= c_end; ++j) {\n                seg.squares.push_back({r, j});\n                visited_horz[{r, j}] = true;\n            }\n            segments.push_back(seg);\n        }\n\n        if (visited_vert.find(p) == visited_vert.end()) {\n            Segment seg;\n            seg.id = seg_id_counter++;\n            int r_start = r;\n            while (r_start > 0 && grid[r_start - 1][c] != '#') {\n                r_start--;\n            }\n            int r_end = r;\n            while (r_end < N - 1 && grid[r_end + 1][c] != '#') {\n                r_end++;\n            }\n            for (int i = r_start; i <= r_end; ++i) {\n                seg.squares.push_back({i, c});\n                visited_vert[{i, c}] = true;\n            }\n            segments.push_back(seg);\n        }\n    }\n}\n\n\n// Dijkstra for APSP\npair<vector<int>, vector<int>> dijkstra(int start_node_id) {\n    int n = road_squares.size();\n    vector<int> dist(n, INF);\n    vector<int> parent(n, -1);\n    dist[start_node_id] = 0;\n\n    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;\n    pq.push({0, start_node_id});\n\n    while (!pq.empty()) {\n        auto [d, u] = pq.top();\n        pq.pop();\n\n        if (d > dist[u]) continue;\n\n        for (auto& edge : adj[u]) {\n            int v = edge.first;\n            int weight = edge.second;\n            if (dist[u] + weight < dist[v]) {\n                dist[v] = dist[u] + weight;\n                parent[v] = u;\n                pq.push({dist[v], v});\n            }\n        }\n    }\n    return {dist, parent};\n}\n\n// Main logic\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    start_time = chrono::high_resolution_clock::now();\n\n    cin >> N >> si >> sj;\n    grid.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> grid[i];\n    }\n\n    find_road_squares_and_build_graph();\n    find_segments();\n    \n    // Step 3: Define Key Points and Solve Set Cover\n    set<pair<int, int>> key_points_set;\n    key_points_set.insert({si, sj});\n\n    for (const auto& seg : segments) {\n        key_points_set.insert(seg.squares.front());\n        if(seg.squares.size() > 1) {\n            key_points_set.insert(seg.squares.back());\n        }\n    }\n\n    for (int r = 0; r < N; r+=1) {\n        for (int c = 0; c < N; c+=1) {\n            if (grid[r][c] != '#') {\n                bool has_horz = false, has_vert = false;\n                if (c > 0 && grid[r][c-1] != '#') has_horz = true;\n                if (c < N-1 && grid[r][c+1] != '#') has_horz = true;\n                if (r > 0 && grid[r-1][c] != '#') has_vert = true;\n                if (r < N-1 && grid[r+1][c] != '#') has_vert = true;\n                if(has_horz && has_vert) {\n                     bool is_straight = (c > 0 && grid[r][c-1] != '#' && c < N-1 && grid[r][c+1] != '#') && !(r > 0 && grid[r-1][c] != '#') && !(r < N-1 && grid[r+1][c] != '#');\n                     is_straight |= (r > 0 && grid[r-1][c] != '#' && r < N-1 && grid[r+1][c] != '#') && !(c > 0 && grid[r][c-1] != '#') && !(c < N-1 && grid[r][c+1] != '#');\n                     if(!is_straight) key_points_set.insert({r,c});\n                }\n            }\n        }\n    }\n    \n    vector<pair<int, int>> key_points(key_points_set.begin(), key_points_set.end());\n    map<pair<int, int>, int> kp_to_idx;\n    for(size_t i=0; i<key_points.size(); ++i) kp_to_idx[key_points[i]] = i;\n\n    vector<vector<int>> kp_covers(key_points.size());\n    vector<vector<int>> seg_covered_by(segments.size());\n\n    for(size_t i=0; i<key_points.size(); ++i) {\n        for(const auto& seg : segments) {\n            for(const auto& sq : seg.squares) {\n                if(sq == key_points[i]) {\n                    kp_covers[i].push_back(seg.id);\n                    seg_covered_by[seg.id].push_back(i);\n                    break;\n                }\n            }\n        }\n    }\n    \n    set<int> segments_to_cover;\n    for (size_t i = 0; i < segments.size(); ++i) segments_to_cover.insert(i);\n\n    vector<int> kp_uncovered_count(key_points.size());\n    for(size_t i=0; i<key_points.size(); ++i) {\n        kp_uncovered_count[i] = kp_covers[i].size();\n    }\n    \n    set<pair<int, int>> target_kps_set;\n    while(!segments_to_cover.empty()) {\n        int best_kp_idx = -1;\n        int max_cover = -1;\n        \n        for(size_t i=0; i<key_points.size(); ++i) {\n            if(kp_uncovered_count[i] > max_cover) {\n                max_cover = kp_uncovered_count[i];\n                best_kp_idx = i;\n            }\n        }\n        \n        if (best_kp_idx == -1) break;\n\n        pair<int,int> best_kp_coord = key_points[best_kp_idx];\n        target_kps_set.insert(best_kp_coord);\n        \n        vector<int> segs_just_covered;\n        for(int seg_id : kp_covers[best_kp_idx]) {\n            if(segments_to_cover.count(seg_id)) {\n                segs_just_covered.push_back(seg_id);\n            }\n        }\n\n        for(int seg_id : segs_just_covered) {\n            segments_to_cover.erase(seg_id);\n            for(int kp_idx : seg_covered_by[seg_id]) {\n                kp_uncovered_count[kp_idx]--;\n            }\n        }\n    }\n\n    target_kps_set.insert({si, sj});\n    vector<pair<int, int>> V_tsp_coords(target_kps_set.begin(), target_kps_set.end());\n    int num_tsp_nodes = V_tsp_coords.size();\n    map<pair<int, int>, int> tsp_coord_to_idx;\n    for(int i=0; i<num_tsp_nodes; ++i) tsp_coord_to_idx[V_tsp_coords[i]] = i;\n\n    // Step 4: APSP\n    vector<vector<int>> dist_matrix(num_tsp_nodes, vector<int>(num_tsp_nodes));\n    vector<vector<int>> parents_matrix(num_tsp_nodes, vector<int>(road_squares.size()));\n\n    for(int i=0; i<num_tsp_nodes; ++i) {\n        int start_node_id = coord_to_id.at(V_tsp_coords[i]);\n        auto [dist, parent] = dijkstra(start_node_id);\n        parents_matrix[i] = parent;\n        for(int j=0; j<num_tsp_nodes; ++j) {\n            int end_node_id = coord_to_id.at(V_tsp_coords[j]);\n            dist_matrix[i][j] = dist[end_node_id];\n        }\n    }\n\n    // Step 5: Solve TSP\n    int start_tsp_idx = tsp_coord_to_idx.at({si, sj});\n    vector<int> tour;\n    tour.push_back(start_tsp_idx);\n    vector<bool> visited(num_tsp_nodes, false);\n    visited[start_tsp_idx] = true;\n\n    int current_tsp_idx = start_tsp_idx;\n    while(tour.size() < (size_t)num_tsp_nodes) {\n        int next_tsp_idx = -1;\n        int min_dist = INF;\n        for(int i=0; i<num_tsp_nodes; ++i) {\n            if(!visited[i]) {\n                if(dist_matrix[current_tsp_idx][i] < min_dist) {\n                    min_dist = dist_matrix[current_tsp_idx][i];\n                    next_tsp_idx = i;\n                }\n            }\n        }\n        if (next_tsp_idx == -1) break; // All remaining are unreachable\n        tour.push_back(next_tsp_idx);\n        visited[next_tsp_idx] = true;\n        current_tsp_idx = next_tsp_idx;\n    }\n    \n    // 2-opt\n    bool improved = true;\n    while(improved) {\n        auto elapsed_time = chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count();\n        if (elapsed_time > 2800) break;\n        improved = false;\n        for(int i=0; i<num_tsp_nodes; ++i) {\n            for(int j=i+2; j<num_tsp_nodes; ++j) {\n                if (i == 0 && j == num_tsp_nodes - 1) continue;\n                \n                int u1 = tour[i], v1 = tour[(i+1)%num_tsp_nodes];\n                int u2 = tour[j], v2 = tour[(j+1)%num_tsp_nodes];\n                \n                long long current_dist = dist_matrix[u1][v1] + dist_matrix[u2][v2];\n                long long new_dist = dist_matrix[u1][u2] + dist_matrix[v1][v2];\n                \n                if(new_dist < current_dist) {\n                    reverse(tour.begin() + i + 1, tour.begin() + j + 1);\n                    improved = true;\n                }\n            }\n        }\n    }\n    \n    auto it = find(tour.begin(), tour.end(), start_tsp_idx);\n    rotate(tour.begin(), it, tour.end());\n\n    // Step 6: Generate Output\n    string path_str = \"\";\n    for(size_t i=0; i<tour.size(); ++i) {\n        int u_tsp_idx = tour[i];\n        int v_tsp_idx = tour[(i+1)%tour.size()];\n        \n        int u_node_id = coord_to_id.at(V_tsp_coords[u_tsp_idx]);\n        int v_node_id = coord_to_id.at(V_tsp_coords[v_tsp_idx]);\n\n        vector<int> path;\n        int curr = v_node_id;\n        while(curr != -1 && curr != u_node_id) {\n            path.push_back(curr);\n            curr = parents_matrix[u_tsp_idx][curr];\n        }\n        reverse(path.begin(), path.end());\n        \n        pair<int, int> last_coord = V_tsp_coords[u_tsp_idx];\n        for(int node_id : path) {\n            auto [r, c] = road_squares[node_id];\n            if(r < last_coord.first) path_str += 'U';\n            else if(r > last_coord.first) path_str += 'D';\n            else if(c < last_coord.second) path_str += 'L';\n            else if(c > last_coord.second) path_str += 'R';\n            last_coord = {r, c};\n        }\n    }\n\n    cout << path_str << endl;\n\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <string>\n#include <sstream>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <functional>\n\n#include <atcoder/mincostflow>\n\n// Constants\nconstexpr int N_TASKS = 1000;\nconstexpr int M_MEMBERS = 20;\nconstexpr int MAX_DAYS = 2000;\n\n// Hyperparameters\nconst double INITIAL_SKILL_ESTIMATE = 0.0;\nconst double SKILL_UPDATE_LEARNING_RATE = 0.15; // Tuned from 0.1\nconst double EXPLORATION_DECAY_DAYS = 400.0;   // Tuned from 600.0\nconst double EXPLORATION_LAMBDA_0 = 0.5;\nconst double OVERESTIMATE_CORRECTION_FACTOR = 0.1;\nconst int CANDIDATE_TASK_POOL_SIZE = 3 * M_MEMBERS; // Increased from 2*M\n\n// Problem data\nint K, R;\nstd::vector<std::vector<int>> D; // Task difficulties\nstd::vector<std::vector<int>> adj; // Task dependencies (u -> v means u must be done before v)\nstd::vector<std::vector<int>> rev_adj; // Reverse dependencies\n\n// State\nenum class TaskStatus { NOT_STARTED, IN_PROGRESS, COMPLETED };\nstd::vector<TaskStatus> task_status;\nint completed_task_count;\n\nstruct Member {\n    bool is_busy = false;\n    int task_id = -1;\n    int start_day = -1;\n};\nstd::vector<Member> members;\n\nstd::vector<std::vector<double>> estimated_skills;\nstd::vector<std::vector<int>> skill_lower_bounds;\nstd::vector<std::vector<int>> max_d_seen;\n\n// --- Function Declarations ---\ndouble estimate_work(int task_id, int member_id);\ndouble estimate_time(int task_id, int member_id);\nvoid read_initial_input();\nvoid initialize_state();\nvoid update_skills(int member_id, int task_id, int duration);\n\n// --- Main Logic ---\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int N_dummy, M_dummy;\n    std::cin >> N_dummy >> M_dummy;\n    \n    read_initial_input();\n    initialize_state();\n\n    for (int day = 1; day <= MAX_DAYS; ++day) {\n        // --- Find free members and schedulable tasks ---\n        std::vector<int> free_members_ids;\n        for (int i = 0; i < M_MEMBERS; ++i) {\n            if (!members[i].is_busy) {\n                free_members_ids.push_back(i);\n            }\n        }\n\n        std::vector<int> schedulable_tasks_ids;\n        if (!free_members_ids.empty()) {\n            for (int i = 0; i < N_TASKS; ++i) {\n                if (task_status[i] == TaskStatus::NOT_STARTED) {\n                    bool all_deps_done = true;\n                    for (int dep : rev_adj[i]) {\n                        if (task_status[dep] != TaskStatus::COMPLETED) {\n                            all_deps_done = false;\n                            break;\n                        }\n                    }\n                    if (all_deps_done) {\n                        schedulable_tasks_ids.push_back(i);\n                    }\n                }\n            }\n        }\n\n        std::vector<std::pair<int, int>> assignments;\n        if (!free_members_ids.empty() && !schedulable_tasks_ids.empty()) {\n            \n            // --- Dynamic Longest Path (DLP) calculation ---\n            std::vector<double> best_time_for_task(N_TASKS);\n            for (int i = 0; i < N_TASKS; ++i) {\n                if (task_status[i] == TaskStatus::COMPLETED) {\n                    best_time_for_task[i] = 0;\n                } else {\n                    double min_t = 1e9;\n                    for (int j = 0; j < M_MEMBERS; ++j) {\n                        min_t = std::min(min_t, estimate_time(i, j));\n                    }\n                    best_time_for_task[i] = min_t;\n                }\n            }\n            std::vector<double> dlp(N_TASKS, 0.0);\n            for (int i = N_TASKS - 1; i >= 0; --i) {\n                double max_succ_dlp = 0.0;\n                for (int neighbor : adj[i]) {\n                    max_succ_dlp = std::max(max_succ_dlp, dlp[neighbor]);\n                }\n                dlp[i] = best_time_for_task[i] + max_succ_dlp;\n            }\n\n            // --- Candidate Task Selection ---\n            std::sort(schedulable_tasks_ids.begin(), schedulable_tasks_ids.end(), [&](int a, int b) {\n                if (std::abs(dlp[a] - dlp[b]) > 1e-9) return dlp[a] > dlp[b];\n                return a < b;\n            });\n            if (schedulable_tasks_ids.size() > CANDIDATE_TASK_POOL_SIZE) {\n                schedulable_tasks_ids.resize(CANDIDATE_TASK_POOL_SIZE);\n            }\n\n            // --- Bipartite Matching using Min-Cost Max-Flow ---\n            int num_free_members = free_members_ids.size();\n            int num_cand_tasks = schedulable_tasks_ids.size();\n            atcoder::mcf_graph<int, long long> graph(num_free_members + num_cand_tasks + 2);\n            int s = num_free_members + num_cand_tasks;\n            int t = s + 1;\n            \n            double lambda = EXPLORATION_LAMBDA_0 * exp(-(double)day / EXPLORATION_DECAY_DAYS);\n\n            for (int i = 0; i < num_free_members; ++i) graph.add_edge(s, i, 1, 0);\n            for (int i = 0; i < num_cand_tasks; ++i) graph.add_edge(num_free_members + i, t, 1, 0);\n\n            for (int i = 0; i < num_free_members; ++i) {\n                int member_id = free_members_ids[i];\n                for (int j = 0; j < num_cand_tasks; ++j) {\n                    int task_id = schedulable_tasks_ids[j];\n                    double t_est = estimate_time(task_id, member_id);\n                    double novelty = 0;\n                    for (int k = 0; k < K; ++k) {\n                        novelty += std::max(0, D[task_id][k] - max_d_seen[member_id][k]);\n                    }\n                    long long cost = static_cast<long long>(round(100.0 * t_est - 100.0 * lambda * novelty));\n                    graph.add_edge(i, num_free_members + j, 1, cost);\n                }\n            }\n\n            graph.flow(s, t, std::min(num_free_members, num_cand_tasks));\n            for (const auto& edge : graph.edges()) {\n                if (edge.from >= 0 && edge.from < num_free_members && \n                    edge.to >= num_free_members && edge.to < s && edge.flow > 0) {\n                    int member_idx = edge.from;\n                    int task_idx = edge.to - num_free_members;\n                    assignments.emplace_back(free_members_ids[member_idx], schedulable_tasks_ids[task_idx]);\n                }\n            }\n        }\n        \n        // --- Output assignments ---\n        std::cout << assignments.size();\n        for (const auto& p : assignments) {\n            int member_id = p.first;\n            int task_id = p.second;\n            std::cout << \" \" << member_id + 1 << \" \" << task_id + 1;\n            members[member_id] = {true, task_id, day};\n            task_status[task_id] = TaskStatus::IN_PROGRESS;\n        }\n        std::cout << std::endl;\n\n        // --- Read daily feedback ---\n        int n_finished;\n        std::cin >> n_finished;\n        if (n_finished == -1) break;\n        \n        for (int i = 0; i < n_finished; ++i) {\n            int finished_member_id;\n            std::cin >> finished_member_id;\n            --finished_member_id;\n\n            int task_id = members[finished_member_id].task_id;\n            int start_day = members[finished_member_id].start_day;\n            int duration = day - start_day + 1;\n\n            members[finished_member_id] = {false, -1, -1};\n            task_status[task_id] = TaskStatus::COMPLETED;\n            completed_task_count++;\n            \n            update_skills(finished_member_id, task_id, duration);\n        }\n    }\n    return 0;\n}\n\n// --- Function Implementations ---\ndouble estimate_work(int task_id, int member_id) {\n    double work = 0;\n    for (int k = 0; k < K; ++k) {\n        work += std::max(0.0, (double)D[task_id][k] - estimated_skills[member_id][k]);\n    }\n    return work;\n}\n\ndouble estimate_time(int task_id, int member_id) {\n    double work = estimate_work(task_id, member_id);\n    return std::max(1.0, work);\n}\n\nvoid read_initial_input() {\n    std::cin >> K >> R;\n    D.resize(N_TASKS, std::vector<int>(K));\n    for (int i = 0; i < N_TASKS; ++i) {\n        for (int j = 0; j < K; ++j) {\n            std::cin >> D[i][j];\n        }\n    }\n    adj.assign(N_TASKS, std::vector<int>());\n    rev_adj.assign(N_TASKS, std::vector<int>());\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        std::cin >> u >> v;\n        --u; --v;\n        adj[u].push_back(v);\n        rev_adj[v].push_back(u);\n    }\n}\n\nvoid initialize_state() {\n    task_status.assign(N_TASKS, TaskStatus::NOT_STARTED);\n    completed_task_count = 0;\n    members.resize(M_MEMBERS);\n    estimated_skills.assign(M_MEMBERS, std::vector<double>(K, INITIAL_SKILL_ESTIMATE));\n    skill_lower_bounds.assign(M_MEMBERS, std::vector<int>(K, 0));\n    max_d_seen.assign(M_MEMBERS, std::vector<int>(K, 0));\n}\n\nvoid update_skills(int member_id, int task_id, int duration) {\n    for (int k = 0; k < K; ++k) {\n        max_d_seen[member_id][k] = std::max(max_d_seen[member_id][k], D[task_id][k]);\n    }\n\n    double predicted_w = estimate_work(task_id, member_id);\n    \n    if (duration == 1) {\n        for (int k = 0; k < K; ++k) {\n            skill_lower_bounds[member_id][k] = std::max(skill_lower_bounds[member_id][k], D[task_id][k]);\n            estimated_skills[member_id][k] = std::max(estimated_skills[member_id][k], (double)skill_lower_bounds[member_id][k]);\n        }\n    } else {\n        double observed_w = duration;\n        \n        if (predicted_w < 1e-6) { // Predicted T=1, but was wrong\n            std::vector<int> candidate_k;\n            for(int k=0; k<K; ++k) {\n                if(D[task_id][k] > 0) candidate_k.push_back(k);\n            }\n\n            if (!candidate_k.empty()) {\n                std::vector<double> blame_weights;\n                double total_blame = 0;\n                for (int k : candidate_k) {\n                    double weight = exp(-OVERESTIMATE_CORRECTION_FACTOR * (estimated_skills[member_id][k] - D[task_id][k]));\n                    blame_weights.push_back(weight);\n                    total_blame += weight;\n                }\n                \n                if (total_blame > 1e-9) {\n                    for (size_t i = 0; i < candidate_k.size(); ++i) {\n                        int k = candidate_k[i];\n                        double blamed_deficiency = observed_w * blame_weights[i] / total_blame;\n                        double target_s_k = (double)D[task_id][k] - blamed_deficiency;\n                        estimated_skills[member_id][k] = (1.0 - SKILL_UPDATE_LEARNING_RATE) * estimated_skills[member_id][k] \n                                                        + SKILL_UPDATE_LEARNING_RATE * target_s_k;\n                    }\n                }\n            }\n        } else { // Standard update\n            double error = observed_w - predicted_w;\n            std::vector<int> deficient_skills;\n            double total_predicted_deficiency = 0;\n            for (int k = 0; k < K; ++k) {\n                if (D[task_id][k] > estimated_skills[member_id][k]) {\n                    deficient_skills.push_back(k);\n                    total_predicted_deficiency += (D[task_id][k] - estimated_skills[member_id][k]);\n                }\n            }\n\n            if (!deficient_skills.empty() && total_predicted_deficiency > 1e-9) {\n                for (int k : deficient_skills) {\n                    double current_deficiency = D[task_id][k] - estimated_skills[member_id][k];\n                    double adjustment = error * (current_deficiency / total_predicted_deficiency);\n                    estimated_skills[member_id][k] -= SKILL_UPDATE_LEARNING_RATE * adjustment;\n                }\n            }\n        }\n    }\n\n    for (int k = 0; k < K; ++k) {\n        estimated_skills[member_id][k] = std::max((double)skill_lower_bounds[member_id][k], estimated_skills[member_id][k]);\n        estimated_skills[member_id][k] = std::max(0.0, estimated_skills[member_id][k]);\n    }\n    \n    std::cout << \"#s \" << member_id + 1;\n    for (int k = 0; k < K; ++k) {\n        std::cout << \" \" << static_cast<int>(round(estimated_skills[member_id][k]));\n    }\n    std::cout << std::endl;\n}","ahc006":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n#include <chrono>\n#include <random>\n\n// A fast random number generator\nclass Xoshiro256pp {\npublic:\n    using result_type = uint64_t;\n    static constexpr result_type min() { return std::numeric_limits<result_type>::min(); }\n    static constexpr result_type max() { return std::numeric_limits<result_type>::max(); }\n\n    Xoshiro256pp() : Xoshiro256pp(std::random_device{}()) {}\n    explicit Xoshiro256pp(uint64_t seed) {\n        s[0] = seed; s[1] = 0; s[2] = 0; s[3] = 0;\n    }\n\n    result_type operator()() {\n        const uint64_t result = rotl(s[0] + s[3], 23) + s[0];\n        const uint64_t t = s[1] << 17;\n        s[2] ^= s[0]; s[3] ^= s[1]; s[1] ^= s[2]; s[0] ^= s[3];\n        s[2] ^= t; s[3] = rotl(s[3], 45);\n        return result;\n    }\n\n    int next_int(int min, int max) {\n        return min + operator()() % (uint64_t)(max - min + 1);\n    }\n\n    double next_double() {\n        return (operator()() >> 11) * (1.0 / (1ULL << 53));\n    }\n\nprivate:\n    static inline uint64_t rotl(const uint64_t x, int k) {\n        return (x << k) | (x >> (64 - k));\n    }\n    uint64_t s[4];\n};\n\nXoshiro256pp rng;\n\nstruct Point {\n    int x, y;\n};\n\nstruct Order {\n    int id;\n    Point p, d;\n};\n\nconst int NUM_ORDERS_TOTAL = 1000;\nconst int ORDERS_TO_DELIVER = 50;\nconst int PATH_LEN = ORDERS_TO_DELIVER * 2;\nconst Point OFFICE = {400, 400};\nstd::vector<Order> ALL_ORDERS;\n\nint manhattan(Point p1, Point p2) {\n    return std::abs(p1.x - p2.x) + std::abs(p1.y - p2.y);\n}\n\nstruct State {\n    std::vector<int> selected_g_indices;\n    std::vector<int> path;\n    std::vector<int> pos;\n    long long cost;\n\n    State() : pos(PATH_LEN) {}\n\n    void update_pos() {\n        for (int i = 0; i < PATH_LEN; ++i) {\n            pos[path[i]] = i;\n        }\n    }\n};\n\nPoint get_coord_by_node(int node_id, const std::vector<int>& selected_g_indices) {\n    if (node_id < 0) return OFFICE;\n    if (node_id < ORDERS_TO_DELIVER) {\n        return ALL_ORDERS[selected_g_indices[node_id]].p;\n    } else {\n        return ALL_ORDERS[selected_g_indices[node_id - ORDERS_TO_DELIVER]].d;\n    }\n}\n\nlong long calculate_cost(const std::vector<int>& path, const std::vector<int>& selected_g_indices) {\n    if (path.empty()) return 0;\n    long long total_dist = 0;\n    total_dist += manhattan(OFFICE, get_coord_by_node(path[0], selected_g_indices));\n    for (size_t i = 0; i < path.size() - 1; ++i) {\n        total_dist += manhattan(get_coord_by_node(path[i], selected_g_indices), get_coord_by_node(path[i+1], selected_g_indices));\n    }\n    total_dist += manhattan(get_coord_by_node(path.back(), selected_g_indices), OFFICE);\n    return total_dist;\n}\n\nvoid solve() {\n    auto start_time = std::chrono::steady_clock::now();\n\n    ALL_ORDERS.resize(NUM_ORDERS_TOTAL);\n    for (int i = 0; i < NUM_ORDERS_TOTAL; ++i) {\n        ALL_ORDERS[i].id = i + 1;\n        std::cin >> ALL_ORDERS[i].p.x >> ALL_ORDERS[i].p.y >> ALL_ORDERS[i].d.x >> ALL_ORDERS[i].d.y;\n    }\n\n    // --- Initial Solution ---\n    State current_state;\n    std::vector<int> order_indices(NUM_ORDERS_TOTAL);\n    std::iota(order_indices.begin(), order_indices.end(), 0);\n    std::sort(order_indices.begin(), order_indices.end(), [&](int a, int b) {\n        Point center_a = {(ALL_ORDERS[a].p.x + ALL_ORDERS[a].d.x) / 2, (ALL_ORDERS[a].p.y + ALL_ORDERS[a].d.y) / 2};\n        Point center_b = {(ALL_ORDERS[b].p.x + ALL_ORDERS[b].d.x) / 2, (ALL_ORDERS[b].p.y + ALL_ORDERS[b].d.y) / 2};\n        return manhattan(OFFICE, center_a) < manhattan(OFFICE, center_b);\n    });\n    current_state.selected_g_indices.assign(order_indices.begin(), order_indices.begin() + ORDERS_TO_DELIVER);\n\n    for (int i = 0; i < ORDERS_TO_DELIVER; ++i) {\n        int p_node = i;\n        int d_node = i + ORDERS_TO_DELIVER;\n        \n        long long min_p_cost_increase = -1;\n        int best_p_pos = 0;\n        for (int j = 0; j <= (int)current_state.path.size(); ++j) {\n            Point prev = (j == 0) ? OFFICE : get_coord_by_node(current_state.path[j - 1], current_state.selected_g_indices);\n            Point next = (j == (int)current_state.path.size()) ? OFFICE : get_coord_by_node(current_state.path[j], current_state.selected_g_indices);\n            Point current = get_coord_by_node(p_node, current_state.selected_g_indices);\n            long long cost_increase = manhattan(prev, current) + manhattan(current, next) - manhattan(prev, next);\n            if (min_p_cost_increase == -1 || cost_increase < min_p_cost_increase) {\n                min_p_cost_increase = cost_increase;\n                best_p_pos = j;\n            }\n        }\n        current_state.path.insert(current_state.path.begin() + best_p_pos, p_node);\n\n        long long min_d_cost_increase = -1;\n        int best_d_pos = 0;\n        for (int j = best_p_pos + 1; j <= (int)current_state.path.size(); ++j) {\n            Point prev = get_coord_by_node(current_state.path[j - 1], current_state.selected_g_indices);\n            Point next = (j == (int)current_state.path.size()) ? OFFICE : get_coord_by_node(current_state.path[j], current_state.selected_g_indices);\n            Point current = get_coord_by_node(d_node, current_state.selected_g_indices);\n            long long cost_increase = manhattan(prev, current) + manhattan(current, next) - manhattan(prev, next);\n            if (min_d_cost_increase == -1 || cost_increase < min_d_cost_increase) {\n                min_d_cost_increase = cost_increase;\n                best_d_pos = j;\n            }\n        }\n        current_state.path.insert(current_state.path.begin() + best_d_pos, d_node);\n    }\n    \n    current_state.cost = calculate_cost(current_state.path, current_state.selected_g_indices);\n    current_state.update_pos();\n    State best_state = current_state;\n\n    std::vector<int> not_selected_g_indices;\n    {\n        std::vector<bool> is_selected_flags(NUM_ORDERS_TOTAL, false);\n        for(int g_idx : current_state.selected_g_indices) is_selected_flags[g_idx] = true;\n        not_selected_g_indices.reserve(NUM_ORDERS_TOTAL - ORDERS_TO_DELIVER);\n        for(int i=0; i<NUM_ORDERS_TOTAL; ++i) if(!is_selected_flags[i]) not_selected_g_indices.push_back(i);\n    }\n    \n    // --- Simulated Annealing ---\n    double T_start = 5000;\n    double T_end = 2;\n    double time_limit = 1.95;\n    \n    while (true) {\n        auto current_time = std::chrono::steady_clock::now();\n        double elapsed_time = std::chrono::duration<double>(current_time - start_time).count();\n        if (elapsed_time > time_limit) break;\n        double T = T_start * std::pow(T_end / T_start, elapsed_time / time_limit);\n        \n        double move_type = rng.next_double();\n        \n        if (move_type < 0.4) { // Move 1: Replace Order\n            int local_idx = rng.next_int(0, ORDERS_TO_DELIVER - 1);\n            int g_idx_to_remove = current_state.selected_g_indices[local_idx];\n            int not_selected_vec_idx = rng.next_int(0, not_selected_g_indices.size() - 1);\n            int g_idx_to_add = not_selected_g_indices[not_selected_vec_idx];\n\n            int p_node = local_idx;\n            int d_node = local_idx + ORDERS_TO_DELIVER;\n            int p_pos = current_state.pos[p_node];\n            int d_pos = current_state.pos[d_node];\n\n            Point p_old = ALL_ORDERS[g_idx_to_remove].p;\n            Point d_old = ALL_ORDERS[g_idx_to_remove].d;\n            Point p_new = ALL_ORDERS[g_idx_to_add].p;\n            Point d_new = ALL_ORDERS[g_idx_to_add].d;\n            long long delta = 0;\n            \n            Point p_prev_coord = (p_pos == 0) ? OFFICE : get_coord_by_node(current_state.path[p_pos-1], current_state.selected_g_indices);\n            Point p_next_coord = get_coord_by_node(current_state.path[p_pos+1], current_state.selected_g_indices);\n            Point d_prev_coord = get_coord_by_node(current_state.path[d_pos-1], current_state.selected_g_indices);\n            Point d_next_coord = (d_pos == PATH_LEN-1) ? OFFICE : get_coord_by_node(current_state.path[d_pos+1], current_state.selected_g_indices);\n\n            if (d_pos == p_pos + 1) { // adjacent\n                delta -= manhattan(p_prev_coord, p_old) + manhattan(p_old, d_old) + manhattan(d_old, d_next_coord);\n                delta += manhattan(p_prev_coord, p_new) + manhattan(p_new, d_new) + manhattan(d_new, d_next_coord);\n            } else {\n                delta -= manhattan(p_prev_coord, p_old) + manhattan(p_old, p_next_coord);\n                delta += manhattan(p_prev_coord, p_new) + manhattan(p_new, p_next_coord);\n                delta -= manhattan(d_prev_coord, d_old) + manhattan(d_old, d_next_coord);\n                delta += manhattan(d_prev_coord, d_new) + manhattan(d_new, d_next_coord);\n            }\n\n            if (delta < 0 || rng.next_double() < std::exp(-delta / T)) {\n                current_state.selected_g_indices[local_idx] = g_idx_to_add;\n                not_selected_g_indices[not_selected_vec_idx] = g_idx_to_remove;\n                current_state.cost += delta;\n                if (current_state.cost < best_state.cost) {\n                    best_state = current_state;\n                }\n            }\n        } else if (move_type < 0.8) { // Move 2: 2-opt\n            int i = rng.next_int(0, PATH_LEN - 1);\n            int j = rng.next_int(0, PATH_LEN - 1);\n            if (i == j) continue;\n            if (i > j) std::swap(i, j);\n            if (j <= i + 1) continue;\n            \n            bool possible = true;\n            for (int k = 0; k < ORDERS_TO_DELIVER; ++k) {\n                if (current_state.pos[k] >= i && current_state.pos[k] <= j && current_state.pos[k + ORDERS_TO_DELIVER] >= i && current_state.pos[k + ORDERS_TO_DELIVER] <= j) {\n                    possible = false;\n                    break;\n                }\n            }\n            if (!possible) continue;\n            \n            Point p_i = get_coord_by_node(current_state.path[i], current_state.selected_g_indices);\n            Point p_j = get_coord_by_node(current_state.path[j], current_state.selected_g_indices);\n            Point p_i_prev = (i > 0) ? get_coord_by_node(current_state.path[i - 1], current_state.selected_g_indices) : OFFICE;\n            Point p_j_next = (j < PATH_LEN - 1) ? get_coord_by_node(current_state.path[j + 1], current_state.selected_g_indices) : OFFICE;\n\n            long long delta = manhattan(p_i_prev, p_j) + manhattan(p_i, p_j_next) - manhattan(p_i_prev, p_i) - manhattan(p_j, p_j_next);\n\n            if (delta < 0 || rng.next_double() < std::exp(-delta / T)) {\n                std::reverse(current_state.path.begin() + i, current_state.path.begin() + j + 1);\n                for(int k=i; k<=j; ++k) current_state.pos[current_state.path[k]] = k;\n                current_state.cost += delta;\n                if (current_state.cost < best_state.cost) {\n                    best_state = current_state;\n                }\n            }\n        } else { // Move 3: Relocate\n            int i = rng.next_int(0, PATH_LEN - 1);\n            int node_to_move = current_state.path[i];\n\n            int order_idx = node_to_move % ORDERS_TO_DELIVER;\n            int p_pos = current_state.pos[order_idx];\n            int d_pos = current_state.pos[order_idx + ORDERS_TO_DELIVER];\n\n            int min_j, max_j;\n            if (node_to_move < ORDERS_TO_DELIVER) { // is a pickup\n                min_j = 0; max_j = d_pos;\n            } else { // is a delivery\n                min_j = p_pos + 1; max_j = PATH_LEN;\n            }\n\n            if (max_j - min_j <= 1) continue;\n            int j = rng.next_int(min_j, max_j);\n            if (j == i || j == i + 1) continue;\n\n            Point Pi = get_coord_by_node(current_state.path[i], current_state.selected_g_indices);\n            Point Pi_prev = (i > 0) ? get_coord_by_node(current_state.path[i - 1], current_state.selected_g_indices) : OFFICE;\n            Point Pi_next = (i < PATH_LEN - 1) ? get_coord_by_node(current_state.path[i + 1], current_state.selected_g_indices) : OFFICE;\n            \n            long long delta;\n            if (i < j) {\n                Point Pj_prev = get_coord_by_node(current_state.path[j - 1], current_state.selected_g_indices);\n                Point Pj = (j < PATH_LEN) ? get_coord_by_node(current_state.path[j], current_state.selected_g_indices) : OFFICE;\n                delta = manhattan(Pi_prev, Pi_next) + manhattan(Pj_prev, Pi) + manhattan(Pi, Pj)\n                      - manhattan(Pi_prev, Pi) - manhattan(Pi, Pi_next) - manhattan(Pj_prev, Pj);\n            } else { // i > j\n                Point Pj = get_coord_by_node(current_state.path[j], current_state.selected_g_indices);\n                Point Pj_prev = (j > 0) ? get_coord_by_node(current_state.path[j - 1], current_state.selected_g_indices) : OFFICE;\n                delta = manhattan(Pj_prev, Pi) + manhattan(Pi, Pj) + manhattan(Pi_prev, Pi_next)\n                      - manhattan(Pj_prev, Pj) - manhattan(Pi_prev, Pi) - manhattan(Pi, Pi_next);\n            }\n            \n            if (delta < 0 || rng.next_double() < std::exp(-delta / T)) {\n                current_state.path.erase(current_state.path.begin() + i);\n                current_state.path.insert(current_state.path.begin() + j - (i < j ? 1 : 0), node_to_move);\n                current_state.update_pos();\n                current_state.cost += delta;\n                if (current_state.cost < best_state.cost) {\n                    best_state = current_state;\n                }\n            }\n        }\n    }\n    \n    // Output best found solution\n    std::cout << ORDERS_TO_DELIVER;\n    for (int g_idx : best_state.selected_g_indices) {\n        std::cout << \" \" << ALL_ORDERS[g_idx].id;\n    }\n    std::cout << std::endl;\n\n    std::cout << best_state.path.size() + 2;\n    std::cout << \" \" << OFFICE.x << \" \" << OFFICE.y;\n    for (int node_id : best_state.path) {\n        Point p = get_coord_by_node(node_id, best_state.selected_g_indices);\n        std::cout << \" \" << p.x << \" \" << p.y;\n    }\n    std::cout << \" \" << OFFICE.x << \" \" << OFFICE.y;\n    std::cout << std::endl;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <map>\n#include <tuple>\n#include <iterator> // For std::make_move_iterator\n\n// Using AtCoder Library's DSU\n#include <atcoder/dsu>\n\nstruct Point {\n    int x, y;\n};\n\nstruct Edge {\n    int u, v, id;\n    int original_d;\n};\n\nlong long dist_sq(const Point& p1, const Point& p2) {\n    long long dx = p1.x - p2.x;\n    long long dy = p1.y - p2.y;\n    return dx * dx + dy * dy;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    const int N = 400;\n    const int M = 1995;\n\n    std::vector<Point> vertices(N);\n    for (int i = 0; i < N; ++i) {\n        std::cin >> vertices[i].x >> vertices[i].y;\n    }\n\n    std::vector<Edge> edges(M);\n    // Use std::map for edge_to_id because it's convenient for arbitrary pairs.\n    // The problem statement guarantees u < v, so we don't need min/max here.\n    std::map<std::pair<int, int>, int> edge_to_id;\n    for (int i = 0; i < M; ++i) {\n        edges[i].id = i;\n        std::cin >> edges[i].u >> edges[i].v;\n        edges[i].original_d = std::round(std::sqrt(dist_sq(vertices[edges[i].u], vertices[edges[i].v])));\n        edge_to_id[{edges[i].u, edges[i].v}] = i;\n    }\n\n    // --- Preprocessing ---\n\n    // 1. Calculate importance levels\n    std::vector<int> importance(M, 0);\n    {\n        std::vector<std::tuple<int, int, int>> all_possible_edges;\n        all_possible_edges.reserve(N * (N - 1) / 2);\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) {\n                int d = std::round(std::sqrt(dist_sq(vertices[i], vertices[j])));\n                all_possible_edges.emplace_back(d, i, j);\n            }\n        }\n        std::sort(all_possible_edges.begin(), all_possible_edges.end());\n\n        std::vector<bool> used_in_mst(all_possible_edges.size(), false);\n        for (int k = 1; k <= 5; ++k) {\n            atcoder::dsu dsu_mst(N);\n            int edges_in_tree = 0;\n            for (size_t i = 0; i < all_possible_edges.size(); ++i) {\n                if (used_in_mst[i]) continue;\n                auto [d, u, v] = all_possible_edges[i];\n                if (dsu_mst.same(u, v)) continue;\n\n                dsu_mst.merge(u, v); // FIX: unite -> merge\n                used_in_mst[i] = true;\n                \n                if (edge_to_id.count({u, v})) {\n                    int original_id = edge_to_id.at({u, v});\n                    if (importance[original_id] == 0) {\n                        importance[original_id] = k;\n                    }\n                }\n                edges_in_tree++;\n                if (edges_in_tree == N - 1) break;\n            }\n        }\n    }\n\n    // 2. Group edges by vertex pairs for quick lookup during \"last chance\" check\n    std::map<std::pair<int, int>, std::vector<int>> edges_by_pair;\n    for (int i = 0; i < M; ++i) {\n        edges_by_pair[{edges[i].u, edges[i].v}].push_back(i);\n    }\n    for (auto& pair_vec : edges_by_pair) {\n        std::sort(pair_vec.second.begin(), pair_vec.second.end());\n    }\n\n    // --- Main Loop ---\n    atcoder::dsu dsu_main(N);\n    // Keep track of vertices in each component to speed up \"last chance\" check\n    std::vector<std::vector<int>> component_members(N);\n    for(int i = 0; i < N; ++i) {\n        component_members[i] = {i};\n    }\n\n    for (int i = 0; i < M; ++i) {\n        int l;\n        std::cin >> l;\n\n        int u = edges[i].u;\n        int v = edges[i].v;\n\n        if (dsu_main.same(u, v)) {\n            std::cout << 0 << std::endl;\n            continue;\n        }\n\n        // \"Last chance\" check: are there any future edges connecting the two components?\n        bool has_alternative = false;\n        int root_u = dsu_main.leader(u);\n        int root_v = dsu_main.leader(v);\n\n        // Helper lambda to check for future edges between two components\n        auto check_alternatives = [&](const std::vector<int>& comp1, const std::vector<int>& comp2) {\n            for (int member1 : comp1) {\n                for (int member2 : comp2) {\n                    int p1 = std::min(member1, member2);\n                    int p2 = std::max(member1, member2);\n                    if (edges_by_pair.count({p1, p2})) {\n                        auto const& candidates = edges_by_pair.at({p1, p2});\n                        // Find first candidate edge with ID > current edge ID\n                        auto it = std::upper_bound(candidates.begin(), candidates.end(), i);\n                        if (it != candidates.end()) {\n                            return true; // Found a future alternative\n                        }\n                    }\n                }\n            }\n            return false;\n        };\n        \n        // Optimization: iterate over the smaller component\n        if (component_members[root_u].size() < component_members[root_v].size()) {\n            has_alternative = check_alternatives(component_members[root_u], component_members[root_v]);\n        } else {\n            has_alternative = check_alternatives(component_members[root_v], component_members[root_u]);\n        }\n        \n        bool take_edge = false;\n        if (!has_alternative) {\n            // Must take this edge to ensure connectivity\n            take_edge = true;\n        } else {\n            // Heuristic decision based on importance and cost\n            int imp = importance[i];\n            if (imp == 0) imp = 6; // Fallback for edges not in top 5 MSTs\n            \n            double threshold_multiplier;\n            switch(imp) {\n                case 1: threshold_multiplier = 3.1; break; // Very willing to take important edges\n                case 2: threshold_multiplier = 2.6; break;\n                case 3: threshold_multiplier = 2.2; break;\n                case 4: threshold_multiplier = 1.8; break;\n                case 5: threshold_multiplier = 1.4; break; // More picky for less important edges\n                default: threshold_multiplier = 1.0; break; // Almost never take (only if l < d, which is impossible)\n            }\n\n            if (l < threshold_multiplier * edges[i].original_d) {\n                take_edge = true;\n            }\n        }\n        \n        if (take_edge) {\n            std::cout << 1 << std::endl;\n            \n            int old_root_u = dsu_main.leader(u);\n            int old_root_v = dsu_main.leader(v);\n            \n            dsu_main.merge(u, v); // FIX: unite -> merge\n            int new_root = dsu_main.leader(u);\n\n            // Merge the lists of component members efficiently\n            if (new_root == old_root_u) { // v's component merged into u's\n                component_members[old_root_u].insert(component_members[old_root_u].end(),\n                    std::make_move_iterator(component_members[old_root_v].begin()),\n                    std::make_move_iterator(component_members[old_root_v].end()));\n                component_members[old_root_v].clear();\n            } else { // u's component merged into v's\n                component_members[old_root_v].insert(component_members[old_root_v].end(),\n                    std::make_move_iterator(component_members[old_root_u].begin()),\n                    std::make_move_iterator(component_members[old_root_u].end()));\n                component_members[old_root_u].clear();\n            }\n        } else {\n            std::cout << 0 << std::endl;\n        }\n    }\n\n    return 0;\n}","ahc008":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <queue>\n#include <map>\n#include <chrono>\n#include <tuple>\n#include <numeric>\n\nusing namespace std;\n\n// --- Utilities ---\nstruct Point {\n    int r, c;\n\n    bool operator==(const Point& other) const { return r == other.r && c == other.c; }\n    bool operator!=(const Point& other) const { return !(*this == other); }\n    bool operator<(const Point& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n};\n\nnamespace std {\n    template <> struct hash<Point> {\n        size_t operator()(const Point& p) const { return hash<int>()(p.r * 31 + p.c); }\n    };\n}\n\nconst int H = 30, W = 30;\nconst int DR[] = {-1, 1, 0, 0};\nconst int DC[] = {0, 0, -1, 1};\nconst char MOVE_CH[] = {'U', 'D', 'L', 'R'};\nconst char BUILD_CH[] = {'u', 'd', 'l', 'r'};\n\nint N, M;\nvector<Point> pet_pos;\nvector<int> pet_type;\nvector<Point> human_pos;\nbool is_impassable[H][W];\n\nint dist(Point p1, Point p2) {\n    return abs(p1.r - p2.r) + abs(p1.c - p2.c);\n}\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < H && c >= 0 && c < W;\n}\n\n// --- Game State & Strategy ---\nPoint rendezvous_point;\nbool is_safe[H][W];\nvector<double> danger_map(H * W, 0.0);\nint current_turn = 0;\n\nenum Phase { EXPANSION, SEALING, CONSOLIDATION };\n\n// --- A* Pathfinder ---\nstruct Node {\n    Point p;\n    int g;\n    double h;\n    double cost;\n    bool operator>(const Node& other) const { return cost > other.cost; }\n};\n\nvector<Point> find_path(Point start, Point end, const vector<Point>& temp_impassable) {\n    priority_queue<Node, vector<Node>, greater<Node>> pq;\n    map<Point, Point> parent;\n    map<Point, int> g_score;\n\n    g_score[start] = 0;\n    pq.push({start, 0, (double)dist(start, end), (double)dist(start, end)});\n\n    bool found = false;\n    while (!pq.empty()) {\n        Node current = pq.top();\n        pq.pop();\n\n        if (current.p == end) {\n            found = true;\n            break;\n        }\n\n        if (g_score.count(current.p) && current.g > g_score[current.p]) continue;\n\n        for (int i = 0; i < 4; ++i) {\n            Point next_p = {current.p.r + DR[i], current.p.c + DC[i]};\n\n            if (!is_valid(next_p.r, next_p.c) || is_impassable[next_p.r][next_p.c]) continue;\n            bool is_temp_impassable = false;\n            for(const auto& obs : temp_impassable) if(obs == next_p) is_temp_impassable = true;\n            if(is_temp_impassable) continue;\n\n            int new_g = current.g + 1;\n            if (!g_score.count(next_p) || new_g < g_score[next_p]) {\n                g_score[next_p] = new_g;\n                parent[next_p] = current.p;\n                double h_val = dist(next_p, end);\n                const double DANGER_WEIGHT = 10.0;\n                double cost = new_g + h_val + DANGER_WEIGHT * danger_map[next_p.r * W + next_p.c];\n                pq.push({next_p, new_g, h_val, cost});\n            }\n        }\n    }\n\n    if (!found) return {};\n    vector<Point> path;\n    Point curr = end;\n    while (curr != start) {\n        path.push_back(curr);\n        curr = parent[curr];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nvoid initial_plan() {\n    double pet_com_r = 0, pet_com_c = 0;\n    for (const auto& p : pet_pos) { pet_com_r += p.r; pet_com_c += p.c; }\n    pet_com_r /= N;\n    pet_com_c /= N;\n\n    vector<Point> corners = {{0, 0}, {0, W - 1}, {H - 1, 0}, {H - 1, W - 1}};\n    double max_dist = -1;\n    for (const auto& corner : corners) {\n        double d = pow(corner.r - pet_com_r, 2) + pow(corner.c - pet_com_c, 2);\n        if (d > max_dist) {\n            max_dist = d;\n            rendezvous_point = corner;\n        }\n    }\n    fill(&is_safe[0][0], &is_safe[0][0] + H * W, false);\n}\n\nvoid update_danger_map() {\n    fill(danger_map.begin(), danger_map.end(), 0.0);\n    int pet_moves[] = {0, 1, 2, 3, 2, 2}; \n    for (int i = 0; i < N; ++i) {\n        int radius = pet_moves[pet_type[i]] + 1;\n        for (int r = 0; r < H; ++r) {\n            for (int c = 0; c < W; ++c) {\n                if (dist(pet_pos[i], {r, c}) < radius) {\n                    danger_map[r * W + c] += 1.0;\n                }\n            }\n        }\n    }\n}\n\nvoid update_safe_zone() {\n    bool new_safe[H][W];\n    fill(&new_safe[0][0], &new_safe[0][0] + H * W, false);\n    queue<Point> q;\n    \n    Point start_node = rendezvous_point;\n    if(is_impassable[start_node.r][start_node.c]) {\n        bool found_any_passable = false;\n        for(int r=0; r<H && !found_any_passable; ++r) for(int c=0; c<W; ++c) {\n            if(!is_impassable[r][c]) {\n                start_node = {r,c};\n                found_any_passable = true;\n                break;\n            }\n        }\n        if(!found_any_passable) {\n            copy(&new_safe[0][0], &new_safe[0][0] + H*W, &is_safe[0][0]);\n            return;\n        }\n    }\n    q.push(start_node);\n    new_safe[start_node.r][start_node.c] = true;\n\n    while (!q.empty()) {\n        Point curr = q.front(); q.pop();\n        for (int i = 0; i < 4; ++i) {\n            Point next_p = {curr.r + DR[i], curr.c + DC[i]};\n            if (is_valid(next_p.r, next_p.c) && !is_impassable[next_p.r][next_p.c] && !new_safe[next_p.r][next_p.c]) {\n                new_safe[next_p.r][next_p.c] = true;\n                q.push(next_p);\n            }\n        }\n    }\n    copy(&new_safe[0][0], &new_safe[0][0] + H*W, &is_safe[0][0]);\n}\n\nvoid check_and_reset_plan() {\n    if (current_turn > 50 && current_turn % 20 == 0) {\n        int safe_zone_size = 0;\n        for(int r=0; r<H; ++r) for(int c=0; c<W; ++c) if(is_safe[r][c]) safe_zone_size++;\n\n        bool pet_in_safe_zone = false;\n        for (const auto& p_pos : pet_pos) {\n            if (is_safe[p_pos.r][p_pos.c]) {\n                pet_in_safe_zone = true;\n                break;\n            }\n        }\n        if (pet_in_safe_zone && safe_zone_size > 20) initial_plan();\n    }\n}\n\nstring solve() {\n    const int PHASE1_END = 260;\n    const int PHASE2_END = 290;\n    \n    if (current_turn == 0) initial_plan();\n    else check_and_reset_plan();\n\n    Phase current_phase = EXPANSION;\n    if (current_turn >= PHASE1_END) current_phase = SEALING;\n    if (current_turn >= PHASE2_END) current_phase = CONSOLIDATION;\n\n    update_danger_map();\n    update_safe_zone();\n    \n    vector<bool> can_build(H * W, true);\n    for(int r=0; r<H; ++r) for(int c=0; c<W; ++c) {\n        if (is_impassable[r][c]) can_build[r*W+c] = false;\n    }\n    for (const auto& p : human_pos) can_build[p.r*W+p.c] = false;\n    for (const auto& p : pet_pos) {\n        can_build[p.r*W+p.c] = false;\n        for (int i=0; i<4; ++i) {\n            Point adj = {p.r+DR[i], p.c+DC[i]};\n            if (is_valid(adj.r, adj.c)) can_build[adj.r*W+adj.c] = false;\n        }\n    }\n\n    vector<Point> tasks;\n    if (current_phase == EXPANSION || current_phase == SEALING) {\n        for (int r=0; r<H; ++r) for (int c=0; c<W; ++c) {\n            if (!is_safe[r][c] && !is_impassable[r][c]) {\n                for (int i=0; i<4; ++i) {\n                    Point adj = {r+DR[i], c+DC[i]};\n                    if (is_valid(adj.r, adj.c) && is_safe[adj.r][adj.c]) {\n                        tasks.push_back({r,c});\n                        break;\n                    }\n                }\n            }\n        }\n    } else { // CONSOLIDATION\n        double center_r=0, center_c=0; int count=0;\n        for (int r=0; r<H; ++r) for (int c=0; c<W; ++c) if (is_safe[r][c]) { center_r+=r; center_c+=c; count++; }\n        if (count > 0) tasks.push_back({(int)round(center_r/count), (int)round(center_c/count)});\n        else tasks.push_back(rendezvous_point);\n    }\n    \n    vector<int> human_task(M, -1);\n    using AssignmentCand = tuple<int, int, int>;\n    vector<AssignmentCand> candidates;\n    if (!tasks.empty()){\n        for (int i=0; i<M; ++i) {\n            for (int j=0; j<(int)tasks.size(); ++j) {\n                if (current_phase == CONSOLIDATION) {\n                    candidates.emplace_back(dist(human_pos[i], tasks[j]), i, j);\n                } else {\n                    int min_build_site_dist = 1e9;\n                    for(int k=0; k<4; ++k) {\n                        Point site = {tasks[j].r+DR[k], tasks[j].c+DC[k]};\n                        if(is_valid(site.r, site.c) && is_safe[site.r][site.c])\n                             min_build_site_dist = min(min_build_site_dist, dist(human_pos[i], site));\n                    }\n                    if(min_build_site_dist != 1e9) candidates.emplace_back(min_build_site_dist, i, j);\n                }\n            }\n        }\n    }\n    sort(candidates.begin(), candidates.end());\n    vector<bool> task_assigned(tasks.size(), false); vector<bool> human_assigned(M, false);\n    for(const auto& cand : candidates){\n        int d, h_id, t_id; tie(d, h_id, t_id) = cand;\n        if(!human_assigned[h_id] && !task_assigned[t_id]){\n            human_task[h_id] = t_id; human_assigned[h_id] = true; task_assigned[t_id] = true;\n        }\n    }\n    \n    string actions_str(M, '.'); vector<Point> planned_walls;\n    for (int i=0; i<M; ++i) {\n        Point current_pos = human_pos[i];\n        if (!is_safe[current_pos.r][current_pos.c] && current_phase != CONSOLIDATION) {\n            Point closest_safe_spot = {-1,-1}; int min_dist_to_safe = 1e9;\n            for(int r=0; r<H; ++r) for(int c=0; c<W; ++c) if(is_safe[r][c]) {\n                int d = dist(current_pos, {r,c});\n                if(d < min_dist_to_safe) {min_dist_to_safe = d; closest_safe_spot = {r,c};}\n            }\n            if(closest_safe_spot.r != -1) {\n                vector<Point> path = find_path(current_pos, closest_safe_spot, planned_walls);\n                if (!path.empty()) {\n                    Point next_pos = path[0];\n                    for (int d=0; d<4; ++d) if (current_pos.r+DR[d]==next_pos.r && current_pos.c+DC[d]==next_pos.c) { actions_str[i] = MOVE_CH[d]; break; }\n                }\n            }\n            continue;\n        }\n\n        if (human_task[i] == -1) continue;\n        Point task_pos = tasks[human_task[i]];\n        \n        if (current_phase == CONSOLIDATION) {\n            vector<Point> path = find_path(current_pos, task_pos, planned_walls);\n            if (!path.empty()) {\n                Point next_pos = path[0];\n                for (int d=0; d<4; ++d) if (current_pos.r+DR[d]==next_pos.r && current_pos.c+DC[d]==next_pos.c) { actions_str[i] = MOVE_CH[d]; break;}\n            }\n        } else {\n            Point best_build_site = {-1,-1}; int min_dist = 1e9;\n            for (int d=0; d<4; ++d) {\n                Point site = {task_pos.r+DR[d], task_pos.c+DC[d]};\n                if (is_valid(site.r, site.c) && is_safe[site.r][site.c]) {\n                    if (dist(current_pos, site) < min_dist) { min_dist = dist(current_pos, site); best_build_site = site;}\n                }\n            }\n            if(best_build_site.r == -1) continue;\n            \n            if (current_pos == best_build_site) {\n                if (can_build[task_pos.r*W+task_pos.c]) {\n                    for (int d=0; d<4; ++d) if (current_pos.r+DR[d]==task_pos.r && current_pos.c+DC[d]==task_pos.c) {\n                        actions_str[i] = BUILD_CH[d]; planned_walls.push_back(task_pos); break;\n                    }\n                } else {\n                    double max_flee_score = -1e9; int best_dir = -1;\n                    for (int d=0; d<4; ++d) {\n                        Point next_p = {current_pos.r+DR[d], current_pos.c+DC[d]};\n                        if (is_valid(next_p.r, next_p.c) && !is_impassable[next_p.r][next_p.c] && is_safe[next_p.r][next_p.c]) {\n                            double min_dist_to_pet = 1e9;\n                            for(const auto& p : pet_pos) min_dist_to_pet = min(min_dist_to_pet, (double)dist(p, next_p));\n                            double score = min_dist_to_pet - danger_map[next_p.r * W + next_p.c];\n                            if (score > max_flee_score) { max_flee_score = score; best_dir = d; }\n                        }\n                    }\n                    if (best_dir != -1) actions_str[i] = MOVE_CH[best_dir];\n                }\n            } else {\n                vector<Point> path = find_path(current_pos, best_build_site, planned_walls);\n                if (!path.empty()) {\n                    Point next_pos = path[0];\n                    for (int d=0; d<4; ++d) if (current_pos.r+DR[d]==next_pos.r && current_pos.c+DC[d]==next_pos.c) { actions_str[i] = MOVE_CH[d]; break;}\n                }\n            }\n        }\n    }\n    return actions_str;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false); cin.tie(NULL);\n    cin >> N;\n    pet_pos.resize(N); pet_type.resize(N);\n    for (int i=0; i<N; ++i) { cin >> pet_pos[i].r >> pet_pos[i].c >> pet_type[i]; pet_pos[i].r--; pet_pos[i].c--; }\n    cin >> M;\n    human_pos.resize(M);\n    for (int i=0; i<M; ++i) { cin >> human_pos[i].r >> human_pos[i].c; human_pos[i].r--; human_pos[i].c--; }\n    fill(&is_impassable[0][0], &is_impassable[0][0]+H*W, false);\n\n    for (int t=0; t<300; ++t) {\n        current_turn = t;\n        string actions = solve();\n        cout << actions << endl;\n        \n        vector<Point> planned_walls;\n        for(int i=0; i<M; ++i) {\n            char act = actions[i]; Point p = human_pos[i];\n            if (act == 'u') planned_walls.push_back({p.r-1, p.c}); else if (act == 'd') planned_walls.push_back({p.r+1, p.c});\n            else if (act == 'l') planned_walls.push_back({p.r, p.c-1}); else if (act == 'r') planned_walls.push_back({p.r, p.c+1});\n        }\n        for(int i=0; i<M; ++i) {\n            char act = actions[i]; Point& p = human_pos[i]; Point next_p = p;\n            if (act == 'U') next_p.r--; else if (act == 'D') next_p.r++; else if (act == 'L') next_p.c--; else if (act == 'R') next_p.c++;\n            bool blocked = false; for(const auto& w : planned_walls) if(next_p == w) blocked = true;\n            if (act >= 'A' && act <= 'Z' && !blocked) p = next_p;\n            else if (act >= 'a' && act <= 'z') {\n                if (act == 'u') is_impassable[p.r-1][p.c] = true; else if (act == 'd') is_impassable[p.r+1][p.c] = true;\n                else if (act == 'l') is_impassable[p.r][p.c-1] = true; else if (act == 'r') is_impassable[p.r][p.c+1] = true;\n            }\n        }\n        for (int i=0; i<N; ++i) {\n            string move_str; cin >> move_str;\n            for (char move : move_str) {\n                if (move == 'U') pet_pos[i].r--; else if (move == 'D') pet_pos[i].r++;\n                else if (move == 'L') pet_pos[i].c--; else if (move == 'R') pet_pos[i].c++;\n            }\n        }\n    }\n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <array>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\n// Using long double for better precision\nusing ld = long double;\n\nconstexpr int N = 20;\nconstexpr int MAX_TURNS = 200;\nconstexpr int BEAM_WIDTH = 30; // Tunable parameter\n\nstruct State {\n    int r, c;\n    bool operator==(const State& other) const {\n        return r == other.r && c == other.c;\n    }\n};\n\nState start_pos, target_pos;\nld forget_prob;\narray<array<bool, N - 1>, N> h_walls;\narray<array<bool, N>, N - 1> v_walls;\narray<array<int, N>, N> dist_to_target;\n\nconst int DR[] = {-1, 1, 0, 0}; // U, D, L, R\nconst int DC[] = {0, 0, -1, 1};\nconst char DIRS[] = \"UDLR\";\nconst int DIRS_ORDER[] = {1, 3, 0, 2}; // D, R, U, L\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N;\n}\n\nState move_state(State s, int dir_idx) {\n    int nr = s.r + DR[dir_idx];\n    int nc = s.c + DC[dir_idx];\n\n    if (!is_valid(nr, nc)) {\n        return s;\n    }\n\n    if (DR[dir_idx] == -1 && v_walls[s.r - 1][s.c]) return s; // U\n    if (DR[dir_idx] == 1 && v_walls[s.r][s.c]) return s;    // D\n    if (DC[dir_idx] == -1 && h_walls[s.r][s.c - 1]) return s; // L\n    if (DC[dir_idx] == 1 && h_walls[s.r][s.c]) return s;    // R\n\n    return {nr, nc};\n}\n\nvoid bfs_from_target() {\n    for (auto& row : dist_to_target) row.fill(-1);\n    \n    queue<State> q;\n    q.push(target_pos);\n    dist_to_target[target_pos.r][target_pos.c] = 0;\n    \n    while (!q.empty()) {\n        State u = q.front();\n        q.pop();\n        \n        for (int i = 0; i < 4; ++i) {\n            State neighbor = {u.r + DR[i], u.c + DC[i]};\n            if (!is_valid(neighbor.r, neighbor.c)) continue;\n            \n            State moved = move_state(u, i);\n            if (moved == u) continue; // Wall between u and neighbor, cannot reach it\n            \n            if (dist_to_target[neighbor.r][neighbor.c] == -1) {\n                dist_to_target[neighbor.r][neighbor.c] = dist_to_target[u.r][u.c] + 1;\n                q.push(neighbor);\n            }\n        }\n    }\n}\n\nusing ProbDist = array<array<ld, N>, N>;\n\nstruct Candidate {\n    string moves;\n    ProbDist prob;\n    ld accumulated_score;\n    ld heuristic_score;\n\n    void calculate_heuristic_score(int turn) {\n        ld expected_dist = 0;\n        ld remaining_prob = 0;\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                if (prob[r][c] > 1e-25) { // Pruning small probabilities\n                    expected_dist += prob[r][c] * dist_to_target[r][c];\n                    remaining_prob += prob[r][c];\n                }\n            }\n        }\n\n        if (remaining_prob < 1e-18) {\n            heuristic_score = accumulated_score;\n            return;\n        }\n        \n        ld avg_dist = expected_dist / remaining_prob;\n        ld expected_turns_to_reach = avg_dist / (1.0L - forget_prob);\n        \n        ld future_score = remaining_prob * max((ld)0.0, 401.0L - (turn + expected_turns_to_reach));\n        heuristic_score = accumulated_score + future_score;\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> start_pos.r >> start_pos.c >> target_pos.r >> target_pos.c;\n    double p_double;\n    cin >> p_double;\n    forget_prob = p_double;\n\n    for (int i = 0; i < N; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < N - 1; ++j) {\n            h_walls[i][j] = (row[j] == '1');\n        }\n    }\n    for (int i = 0; i < N - 1; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < N; ++j) {\n            v_walls[i][j] = (row[j] == '1');\n        }\n    }\n\n    bfs_from_target();\n\n    vector<Candidate> beam;\n    {\n        Candidate initial_candidate;\n        initial_candidate.moves = \"\";\n        for(auto& row : initial_candidate.prob) row.fill(0.0L);\n        initial_candidate.prob[start_pos.r][start_pos.c] = 1.0L;\n        initial_candidate.accumulated_score = 0.0L;\n        initial_candidate.calculate_heuristic_score(1);\n        beam.push_back(initial_candidate);\n    }\n    \n    for (int t = 1; t <= MAX_TURNS; ++t) {\n        vector<Candidate> next_candidates;\n        next_candidates.reserve(beam.size() * 4);\n\n        for (const auto& cand : beam) {\n            ld total_prob_mass = 0;\n             for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    total_prob_mass += cand.prob[r][c];\n                }\n            }\n            if(total_prob_mass < 1e-18) {\n                next_candidates.push_back(cand);\n                continue;\n            }\n\n            for (int dir_idx : DIRS_ORDER) {\n                Candidate next_cand;\n                next_cand.moves = cand.moves + DIRS[dir_idx];\n                for(auto& row : next_cand.prob) row.fill(0.0L);\n                \n                ld prob_reaching_this_turn = 0.0L;\n\n                for (int r = 0; r < N; ++r) {\n                    for (int c = 0; c < N; ++c) {\n                        if (cand.prob[r][c] < 1e-25) continue; // Pruning\n                        \n                        // Forgotten move\n                        next_cand.prob[r][c] += cand.prob[r][c] * forget_prob;\n\n                        // Successful move\n                        State next_pos = move_state({r, c}, dir_idx);\n                        if (next_pos == target_pos) {\n                            prob_reaching_this_turn += cand.prob[r][c] * (1.0L - forget_prob);\n                        } else {\n                            next_cand.prob[next_pos.r][next_pos.c] += cand.prob[r][c] * (1.0L - forget_prob);\n                        }\n                    }\n                }\n                \n                next_cand.accumulated_score = cand.accumulated_score + prob_reaching_this_turn * (401 - t);\n                next_cand.calculate_heuristic_score(t + 1);\n                next_candidates.push_back(move(next_cand));\n            }\n        }\n\n        sort(next_candidates.begin(), next_candidates.end(), [](const Candidate& a, const Candidate& b) {\n            return a.heuristic_score > b.heuristic_score;\n        });\n\n        if (next_candidates.size() > BEAM_WIDTH) {\n            next_candidates.resize(BEAM_WIDTH);\n        }\n        beam = move(next_candidates);\n    }\n\n    Candidate best_candidate;\n    ld max_score = -1.0;\n    for (const auto& cand : beam) {\n        if (cand.accumulated_score > max_score) {\n            max_score = cand.accumulated_score;\n            best_candidate = cand;\n        }\n    }\n\n    cout << best_candidate.moves << endl;\n\n    return 0;\n}","ahc010":"#include <iostream>\n#include <vector>\n#include <string>\n#include <array>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <cmath>\n#include <tuple>\n\n// --- Utilities ---\n\nclass Timer {\n    std::chrono::time_point<std::chrono::high_resolution_clock> start_time;\npublic:\n    Timer() {\n        start_time = std::chrono::high_resolution_clock::now();\n    }\n    double get_elapsed_sec() {\n        auto now = std::chrono::high_resolution_clock::now();\n        return std::chrono::duration<double>(now - start_time).count();\n    }\n};\n\nstruct Rng {\n    std::mt19937 mt;\n    Rng() : mt(std::chrono::high_resolution_clock::now().time_since_epoch().count()) {}\n    int get_int(int min, int max) {\n        std::uniform_int_distribution<int> dist(min, max);\n        return dist(mt);\n    }\n    double get_double(double min, double max) {\n        std::uniform_real_distribution<double> dist(min, max);\n        return dist(mt);\n    }\n};\n\n// --- Problem Constants & Globals ---\nconstexpr int N = 30;\nconstexpr int di[] = {0, -1, 0, 1}; // L, U, R, D\nconstexpr int dj[] = {-1, 0, 1, 0};\n\nconst int to[8][4] = {\n\t{1, 0, -1, -1}, {3, -1, -1, 0}, {-1, -1, 3, 2}, {-1, 2, 1, -1},\n\t{1, 0, 3, 2},   {3, 2, 1, 0},   {2, -1, 0, -1}, {-1, 3, -1, 1},\n};\n\nint t_rot[8][4];\nstd::array<std::array<int, N>, N> initial_tiles;\n\nvoid precompute_rotations() {\n    for (int i = 0; i < 8; ++i) {\n        t_rot[i][0] = i;\n    }\n    for (int r = 1; r < 4; ++r) {\n        for (int i = 0; i < 8; ++i) {\n            int prev_t = t_rot[i][r - 1];\n            int next_t;\n            if (0 <= prev_t && prev_t <= 3) {\n                next_t = (prev_t + 1) % 4;\n            } else if (prev_t == 4) next_t = 5;\n            else if (prev_t == 5) next_t = 4;\n            else if (prev_t == 6) next_t = 7;\n            else next_t = 6;\n            t_rot[i][r] = next_t;\n        }\n    }\n}\n\n// --- Core Logic ---\n\nusing RotationsGrid = std::array<std::array<int, N>, N>;\n\nstruct ScoreInfo {\n    long long product_score = 0;\n    long long total_path_len_score = 0;\n};\n\nScoreInfo calculate_scores(const RotationsGrid& rotations) {\n    std::array<std::array<int, N>, N> tiles;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            tiles[i][j] = t_rot[initial_tiles[i][j]][rotations[i][j]];\n        }\n    }\n\n    bool visited_edge[N][N][4] = {};\n    std::vector<int> loop_lengths;\n    long long total_path_len = 0;\n\n    for (int si = 0; si < N; ++si) {\n        for (int sj = 0; sj < N; ++sj) {\n            for (int sd = 0; sd < 4; ++sd) {\n                if (visited_edge[si][sj][sd]) continue;\n\n                int ci = si, cj = sj, cd = sd;\n                int length = 0;\n                \n                std::vector<std::tuple<int, int, int>> path_history;\n                bool is_loop = false;\n\n                for(int k=0; k < N*N*2 + 5; ++k) {\n                    if (visited_edge[ci][cj][cd]) break;\n                    path_history.emplace_back(ci, cj, cd);\n                    \n                    int d_out = to[tiles[ci][cj]][cd];\n                    if (d_out == -1) break;\n\n                    int ni = ci + di[d_out];\n                    int nj = cj + dj[d_out];\n                    \n                    if (ni < 0 || ni >= N || nj < 0 || nj >= N) break;\n                    \n                    length++;\n                    ci = ni; cj = nj; cd = (d_out + 2) % 4;\n\n                    if (ci == si && cj == sj && cd == sd) {\n                        is_loop = true;\n                        break;\n                    }\n                }\n                \n                if (is_loop) loop_lengths.push_back(length);\n                total_path_len += length;\n                \n                for (const auto& [pi, pj, pd] : path_history) {\n                    visited_edge[pi][pj][pd] = true;\n                }\n            }\n        }\n    }\n    \n    ScoreInfo info;\n    info.total_path_len_score = total_path_len;\n    if (loop_lengths.size() >= 2) {\n        std::sort(loop_lengths.rbegin(), loop_lengths.rend());\n        info.product_score = static_cast<long long>(loop_lengths[0]) * loop_lengths[1];\n    }\n\n    return info;\n}\n\nvoid solve() {\n    Timer timer;\n    Rng rng;\n    \n    for (int i = 0; i < N; ++i) {\n        std::string row;\n        std::cin >> row;\n        for (int j = 0; j < N; ++j) {\n            initial_tiles[i][j] = row[j] - '0';\n        }\n    }\n\n    precompute_rotations();\n\n    RotationsGrid current_rotations;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            current_rotations[i][j] = rng.get_int(0, 3);\n        }\n    }\n\n    RotationsGrid best_rotations_ever = current_rotations;\n    ScoreInfo current_scores = calculate_scores(current_rotations);\n    long long best_prod_score_ever = current_scores.product_score;\n\n    const double time_limit = 1.95;\n    const double phase1_time_limit = 0.8;\n\n    // --- Phase 1: Optimize for total path length ---\n    double T_start1 = 50, T_end1 = 1;\n    long long current_eval_score = current_scores.total_path_len_score;\n\n    while (timer.get_elapsed_sec() < phase1_time_limit) {\n        double progress = timer.get_elapsed_sec() / phase1_time_limit;\n        double T = T_start1 * std::pow(T_end1 / T_start1, progress);\n\n        RotationsGrid next_rotations = current_rotations;\n        \n        if (rng.get_double(0.0, 1.0) < 0.2) { // 20% 2x2 move\n            int r = rng.get_int(0, N - 2);\n            int c = rng.get_int(0, N - 2);\n            for(int i=0; i<2; ++i) for(int j=0; j<2; ++j) {\n                 next_rotations[r+i][c+j] = rng.get_int(0,3);\n            }\n        } else { // 80% single move\n            int r = rng.get_int(0, N - 1);\n            int c = rng.get_int(0, N - 1);\n            int old_rot = next_rotations[r][c];\n            int new_rot;\n            do { new_rot = rng.get_int(0, 3); } while (new_rot == old_rot);\n            next_rotations[r][c] = new_rot;\n        }\n\n        ScoreInfo new_scores = calculate_scores(next_rotations);\n        long long new_eval_score = new_scores.total_path_len_score;\n        double delta = static_cast<double>(new_eval_score - current_eval_score);\n        \n        if (delta >= 0 || rng.get_double(0.0, 1.0) < std::exp(delta / T)) {\n            current_rotations = next_rotations;\n            current_eval_score = new_eval_score;\n        }\n        \n        if (new_scores.product_score > best_prod_score_ever) {\n            best_prod_score_ever = new_scores.product_score;\n            best_rotations_ever = next_rotations;\n        }\n    }\n    \n    // --- Phase 2: Optimize for product of two largest loops ---\n    current_rotations = best_rotations_ever;\n    current_scores = calculate_scores(current_rotations);\n    long long current_prod_score = current_scores.product_score;\n    \n    double T_start2 = 5000, T_end2 = 10;\n\n    while (timer.get_elapsed_sec() < time_limit) {\n        double elapsed_in_phase2 = timer.get_elapsed_sec() - phase1_time_limit;\n        double phase2_duration = time_limit - phase1_time_limit;\n        double progress = elapsed_in_phase2 / phase2_duration;\n        double T = T_start2 * std::pow(T_end2 / T_start2, progress);\n\n        RotationsGrid next_rotations = current_rotations;\n        \n        if (rng.get_double(0.0, 1.0) < 0.05) { // 5% 2x2 move\n            int r = rng.get_int(0, N - 2);\n            int c = rng.get_int(0, N - 2);\n            for(int i=0; i<2; ++i) for(int j=0; j<2; ++j) {\n                 next_rotations[r+i][c+j] = rng.get_int(0,3);\n            }\n        } else { // 95% single move\n            int r = rng.get_int(0, N - 1);\n            int c = rng.get_int(0, N - 1);\n            int old_rot = next_rotations[r][c];\n            int new_rot;\n            do { new_rot = rng.get_int(0, 3); } while (new_rot == old_rot);\n            next_rotations[r][c] = new_rot;\n        }\n        \n        ScoreInfo new_scores = calculate_scores(next_rotations);\n        long long new_prod_score = new_scores.product_score;\n        double delta = static_cast<double>(new_prod_score - current_prod_score);\n        \n        if (delta >= 0 || rng.get_double(0.0, 1.0) < std::exp(delta / T)) {\n            current_rotations = next_rotations;\n            current_prod_score = new_prod_score;\n            if (current_prod_score > best_prod_score_ever) {\n                best_prod_score_ever = current_prod_score;\n                best_rotations_ever = current_rotations;\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            std::cout << best_rotations_ever[i][j];\n        }\n    }\n    std::cout << std::endl;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc011":"#include <iostream>\n#include <vector>\n#include <string>\n#include <array>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <cmath>\n#include <map>\n#include <queue>\n#include <unordered_map>\n\n#include <atcoder/mincostflow>\n\nusing namespace std;\n\n// --- Timer ---\nusing namespace std::chrono;\nauto start_time = high_resolution_clock::now();\ndouble time_limit = 2.95;\n\nbool is_time_over() {\n    auto current_time = high_resolution_clock::now();\n    duration<double> elapsed = current_time - start_time;\n    return elapsed.count() > time_limit;\n}\n\n// --- Random Number Generator ---\nmt19937 rng(0);\n\n// --- Constants and Type Definitions ---\nconstexpr int MAX_N = 10;\nconstexpr int MAX_N2 = 100;\n\nint N, T;\narray<int, 4> dr = {-1, 1, 0, 0}; // U, D, L, R\narray<int, 4> dc = {0, 0, -1, 1};\nstring move_chars = \"UDLR\";\narray<int, 4> opposite_move = {1, 0, 3, 2};\n\n// Directions bits: 1:left, 2:up, 4:right, 8:down\n// L:1, U:2, R:4, D:8\narray<int, 4> dir_bit = {1, 2, 4, 8}; // L, U, R, D mapped from my dc, dr\narray<int, 4> move_dir_map = {2, 8, 1, 4}; // U,D,L,R -> up,down,left,right bits\narray<int, 4> required_bit = {8, 2, 4, 1}; // Tile at (r,c) needs bit for move U, D, L, R from (r,c)\n\nint char_to_hex(char c) {\n    if (c >= '0' && c <= '9') return c - '0';\n    return c - 'a' + 10;\n}\n\nstruct DSU {\n    vector<int> parent;\n    vector<int> sz;\n    int num_sets;\n    DSU(int n) {\n        parent.resize(n);\n        sz.resize(n);\n        num_sets = n;\n        for (int i = 0; i < n; i++) {\n            parent[i] = i;\n            sz[i] = 1;\n        }\n    }\n    int find(int i) {\n        if (parent[i] == i) return i;\n        return parent[i] = find(parent[i]);\n    }\n    void unite(int i, int j) {\n        int root_i = find(i);\n        int root_j = find(j);\n        if (root_i != root_j) {\n            if (sz[root_i] < sz[root_j]) swap(root_i, root_j);\n            parent[root_j] = root_i;\n            sz[root_i] += sz[root_j];\n            num_sets--;\n        }\n    }\n};\n\nstruct Board {\n    array<int, MAX_N2> grid;\n    int empty_pos = -1;\n\n    Board() = default;\n\n    void find_empty() {\n        for (int i = 0; i < N * N; ++i) {\n            if (grid[i] == 0) {\n                empty_pos = i;\n                return;\n            }\n        }\n    }\n};\n\nstruct AStarState {\n    array<uint8_t, MAX_N2> board_config; // tile_id at pos\n    uint8_t empty_pos;\n    uint16_t g;\n    uint16_t h;\n    AStarState* parent;\n    char move_char;\n\n    int f() const { return g + h; }\n\n    bool operator>(const AStarState& other) const {\n        if (f() != other.f()) {\n            return f() > other.f();\n        }\n        return h > other.h;\n    }\n};\n\n// Custom hash for A* state\nstruct AStarStateHasher {\n    size_t operator()(const AStarState* s) const {\n        size_t h = 0;\n        for (int i = 0; i < N * N; ++i) {\n            h ^= hash<uint8_t>()(s->board_config[i]) + 0x9e3779b9 + (h << 6) + (h >> 2);\n        }\n        return h;\n    }\n};\n\nstruct AStarStateComparator {\n    bool operator()(const AStarState* a, const AStarState* b) const {\n        return std::equal(a->board_config.begin(), a->board_config.begin() + N*N, b->board_config.begin());\n    }\n};\n\n\n// --- Global state ---\nBoard initial_board;\narray<int, 16> initial_tile_counts{};\nvector<pair<int, int>> initial_pos_by_type[16];\n\n// --- Phase 1: SA for Target Configuration ---\narray<int, MAX_N2> best_target_grid;\nlong long best_dist_score = -1;\n\nvoid evaluate_target(const array<int, MAX_N2>& target_grid, long long& connectivity_score, long long& dist_score) {\n    DSU dsu(N * N);\n    int edges = 0;\n    int max_comp_size = 0;\n    \n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int pos = r * N + c;\n            if (target_grid[pos] == 0) continue;\n\n            // Down\n            if (r + 1 < N) {\n                int next_pos = (r + 1) * N + c;\n                if (target_grid[next_pos] != 0) {\n                    if ((target_grid[pos] & 8) && (target_grid[next_pos] & 2)) {\n                        if (dsu.find(pos) == dsu.find(next_pos)) { // cycle\n                            connectivity_score -= 10000000;\n                        } else {\n                            dsu.unite(pos, next_pos);\n                            edges++;\n                        }\n                    }\n                }\n            }\n            // Right\n            if (c + 1 < N) {\n                int next_pos = r * N + c + 1;\n                if (target_grid[next_pos] != 0) {\n                    if ((target_grid[pos] & 4) && (target_grid[next_pos] & 1)) {\n                         if (dsu.find(pos) == dsu.find(next_pos)) { // cycle\n                            connectivity_score -= 10000000;\n                        } else {\n                            dsu.unite(pos, next_pos);\n                            edges++;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    int non_empty_cells = N * N - 1;\n    for(int i = 0; i < N * N; ++i) {\n        if(target_grid[i] != 0 && dsu.parent[i] == i) {\n            max_comp_size = max(max_comp_size, dsu.sz[i]);\n        }\n    }\n    \n    connectivity_score += (long long)max_comp_size * 100000;\n    if (max_comp_size == non_empty_cells && edges == non_empty_cells - 1) {\n        connectivity_score += 100000000;\n    }\n\n    // Distance score calculation\n    vector<int> target_pos_by_type[16];\n    for(int i=0; i<N*N; ++i) {\n        if(target_grid[i] != 0) {\n            target_pos_by_type[target_grid[i]].push_back(i);\n        }\n    }\n    \n    dist_score = 0;\n    for (int type = 1; type <= 15; ++type) {\n        if (initial_tile_counts[type] == 0) continue;\n        \n        vector<pair<int, int>> s_coords, d_coords;\n        for (auto p : initial_pos_by_type[type]) s_coords.push_back({p.first, p.second});\n        for (auto pos : target_pos_by_type[type]) d_coords.push_back({pos / N, pos % N});\n\n        sort(s_coords.begin(), s_coords.end());\n        sort(d_coords.begin(), d_coords.end());\n        \n        for (size_t i = 0; i < s_coords.size(); ++i) {\n            dist_score += abs(s_coords[i].first - d_coords[i].first) + abs(s_coords[i].second - d_coords[i].second);\n        }\n    }\n}\n\nvoid run_sa() {\n    array<int, MAX_N2> current_grid;\n    vector<int> tiles;\n    int empty_final_pos = N*N - 1;\n\n    for (int type = 1; type <= 15; ++type) {\n        for (int i = 0; i < initial_tile_counts[type]; ++i) {\n            tiles.push_back(type);\n        }\n    }\n    \n    shuffle(tiles.begin(), tiles.end(), rng);\n    \n    int tile_idx = 0;\n    for(int i=0; i<N*N; ++i) {\n        if (i == empty_final_pos) {\n            current_grid[i] = 0;\n        } else {\n            current_grid[i] = tiles[tile_idx++];\n        }\n    }\n\n    long long current_conn_score=0, current_dist_score=0;\n    evaluate_target(current_grid, current_conn_score, current_dist_score);\n    long long best_conn_score = -1e18;\n\n    double start_temp = 1000, end_temp = 0.1;\n    int iter_count = 0;\n\n    while (!is_time_over()) {\n        iter_count++;\n        double temp = start_temp * pow(end_temp / start_temp, (double)(duration_cast<milliseconds>(high_resolution_clock::now() - start_time).count()) / (time_limit * 1000.0));\n        \n        int p1 = rng() % (N * N);\n        int p2 = rng() % (N * N);\n        if (p1 == p2 || current_grid[p1] == 0 || current_grid[p2] == 0) continue;\n\n        swap(current_grid[p1], current_grid[p2]);\n\n        long long new_conn_score=0, new_dist_score=0;\n        evaluate_target(current_grid, new_conn_score, new_dist_score);\n\n        long long current_score = current_conn_score - current_dist_score;\n        long long new_score = new_conn_score - new_dist_score;\n\n        if (new_score > current_score || uniform_real_distribution<>(0.0, 1.0)(rng) < exp((new_score - current_score) / temp)) {\n            current_conn_score = new_conn_score;\n            current_dist_score = new_dist_score;\n            if (current_conn_score > best_conn_score) {\n                best_conn_score = current_conn_score;\n                best_dist_score = current_dist_score;\n                best_target_grid = current_grid;\n            } else if (current_conn_score == best_conn_score && current_dist_score < best_dist_score) {\n                best_dist_score = current_dist_score;\n                best_target_grid = current_grid;\n            }\n        } else {\n            swap(current_grid[p1], current_grid[p2]);\n        }\n    }\n}\n\n\n// --- Phase 2: A* Search ---\nstring solve_puzzle() {\n    array<int, MAX_N2> tile_id_at_pos;\n    array<int, MAX_N2> type_of_tile_id;\n    array<int, MAX_N2> pos_of_tile_id;\n\n    int current_id = 0;\n    for(int r=0; r<N; ++r) {\n        for(int c=0; c<N; ++c) {\n            int pos = r*N+c;\n            int type = initial_board.grid[pos];\n            if (type != 0) {\n                tile_id_at_pos[pos] = current_id;\n                type_of_tile_id[current_id] = type;\n                pos_of_tile_id[current_id] = pos;\n                current_id++;\n            } else {\n                tile_id_at_pos[pos] = -1; // empty\n            }\n        }\n    }\n\n    // Assignment using min-cost-flow\n    array<int, MAX_N2> dest_of_tile_id;\n    vector<int> target_pos_by_type[16];\n    for (int i = 0; i < N * N; ++i) {\n        if (best_target_grid[i] != 0) {\n            target_pos_by_type[best_target_grid[i]].push_back(i);\n        }\n    }\n\n    vector<pair<int, int>> initial_id_pos_by_type[16];\n    for (int id = 0; id < N * N - 1; ++id) {\n        initial_id_pos_by_type[type_of_tile_id[id]].push_back({id, pos_of_tile_id[id]});\n    }\n\n    for (int type = 1; type <= 15; ++type) {\n        int count = initial_tile_counts[type];\n        if (count == 0) continue;\n\n        atcoder::mcf_graph<int, int> graph(2 * count + 2);\n        int s = 2 * count, t = 2 * count + 1;\n\n        for (int i = 0; i < count; ++i) {\n            graph.add_edge(s, i, 1, 0);\n            graph.add_edge(i + count, t, 1, 0);\n            for (int j = 0; j < count; ++j) {\n                int start_pos = initial_id_pos_by_type[type][i].second;\n                int target_pos = target_pos_by_type[type][j];\n                int dist = abs(start_pos / N - target_pos / N) + abs(start_pos % N - target_pos % N);\n                graph.add_edge(i, j + count, 1, dist);\n            }\n        }\n        graph.flow(s, t, count);\n        for (auto edge : graph.edges()) {\n            if (edge.from < count && edge.to >= count && edge.to < 2*count && edge.flow > 0) {\n                int tile_id = initial_id_pos_by_type[type][edge.from].first;\n                int dest_pos = target_pos_by_type[type][edge.to - count];\n                dest_of_tile_id[tile_id] = dest_pos;\n            }\n        }\n    }\n    \n    // A* search\n    priority_queue<AStarState*, vector<AStarState*>, greater<AStarState>> pq;\n    unordered_map<AStarState*, int, AStarStateHasher, AStarStateComparator> dist;\n    vector<AStarState> state_pool;\n    state_pool.reserve(2000000);\n\n    auto make_state = [&](const array<uint8_t, MAX_N2>& board, uint8_t empty, uint16_t g, uint16_t h, AStarState* p, char move) -> AStarState* {\n        state_pool.emplace_back(AStarState{board, empty, g, h, p, move});\n        return &state_pool.back();\n    };\n\n    AStarState* initial_state = new AStarState();\n    initial_state->g = 0;\n    initial_state->parent = nullptr;\n    initial_state->empty_pos = initial_board.empty_pos;\n    uint16_t initial_h = 0;\n    for (int i = 0; i < N * N; ++i) {\n        int tile_id = tile_id_at_pos[i];\n        if (tile_id != -1) {\n            initial_state->board_config[i] = tile_id;\n            initial_h += abs(i / N - dest_of_tile_id[tile_id] / N) + abs(i % N - dest_of_tile_id[tile_id] % N);\n        }\n    }\n    initial_state->h = initial_h;\n    \n    pq.push(initial_state);\n    dist[initial_state] = 0;\n\n    AStarState* final_state = nullptr;\n\n    int states_explored = 0;\n    while (!pq.empty()) {\n        if (is_time_over() || states_explored > 300000) {\n             break;\n        }\n        states_explored++;\n\n        AStarState* current = pq.top();\n        pq.pop();\n\n        if (dist.count(current) && dist[current] < current->g) {\n            continue;\n        }\n\n        if (current->h == 0) {\n            final_state = current;\n            break;\n        }\n\n        int r = current->empty_pos / N;\n        int c = current->empty_pos % N;\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n\n            if(current->parent != nullptr) {\n                if (nr*N+nc == current->parent->empty_pos) continue;\n            }\n\n            int next_empty_pos = nr * N + nc;\n            \n            array<uint8_t, MAX_N2> next_board = current->board_config;\n            swap(next_board[current->empty_pos], next_board[next_empty_pos]);\n\n            int moved_tile_id = current->board_config[next_empty_pos];\n            int moved_tile_dest = dest_of_tile_id[moved_tile_id];\n\n            uint16_t next_h = current->h;\n            next_h -= (abs(next_empty_pos / N - moved_tile_dest / N) + abs(next_empty_pos % N - moved_tile_dest % N));\n            next_h += (abs(current->empty_pos / N - moved_tile_dest / N) + abs(current->empty_pos % N - moved_tile_dest % N));\n            \n            AStarState temp_state;\n            temp_state.board_config = next_board;\n            auto it = dist.find(&temp_state);\n\n            if (it == dist.end() || it->second > current->g + 1) {\n                AStarState* next_state = make_state(next_board, next_empty_pos, current->g + 1, next_h, current, move_chars[i]);\n                pq.push(next_state);\n                dist[next_state] = current->g + 1;\n            }\n        }\n    }\n\n    if (final_state) {\n        string path = \"\";\n        AStarState* curr = final_state;\n        while (curr->parent != nullptr) {\n            path += curr->move_char;\n            curr = curr->parent;\n        }\n        reverse(path.begin(), path.end());\n        return path;\n    }\n\n    return \"\";\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N >> T;\n    for (int i = 0; i < N; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < N; ++j) {\n            int type = char_to_hex(row[j]);\n            initial_board.grid[i * N + j] = type;\n            if (type != 0) {\n                initial_tile_counts[type]++;\n                initial_pos_by_type[type].push_back({i, j});\n            }\n        }\n    }\n    initial_board.find_empty();\n\n    time_limit = (N<=7) ? 2.95 : 2.95;\n\n    run_sa();\n    \n    long long final_conn_score=0, final_dist_score=0;\n    evaluate_target(best_target_grid, final_conn_score, final_dist_score);\n\n    if (final_conn_score < 100000000) {\n        cout << \"\" << endl; // Failed to find a tree, output empty\n        return 0;\n    }\n\n    string solution = solve_puzzle();\n    cout << solution << endl;\n\n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <map>\n#include <unordered_map>\n\n// --- Utilities ---\nstruct XorShift {\n    unsigned int x, y, z, w;\n\n    XorShift() {\n        std::random_device rd;\n        x = rd();\n        y = rd();\n        z = rd();\n        w = rd();\n    }\n\n    unsigned int next() {\n        unsigned int t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));\n    }\n\n    double next_double() {\n        return next() / 4294967295.0;\n    }\n\n    int next_int(int max_val) { // [0, max_val-1]\n        return next() % max_val;\n    }\n};\n\nXorShift rnd;\nauto start_time = std::chrono::high_resolution_clock::now();\ndouble TIME_LIMIT = 2.95;\n\ndouble get_time() {\n    auto now = std::chrono::high_resolution_clock::now();\n    return std::chrono::duration_cast<std::chrono::duration<double>>(now - start_time).count();\n}\n\n// --- Data Structures ---\nconst long long INF_COORD = 1000000000;\nconst double PI = acos(-1.0L);\n\nstruct Point {\n    long long x, y;\n};\n\nstruct Line {\n    long double a, b, c; // ax+by+c=0\n};\n\nstruct LinePolar {\n    double theta, rho; // rho = x*cos(theta) + y*sin(theta)\n};\n\nstruct VectorHasher {\n    std::size_t operator()(const std::vector<int>& v) const {\n        std::size_t seed = v.size();\n        for (int i : v) {\n            seed ^= (std::size_t)i + 0x9e3779b9 + (seed << 6) + (seed >> 2);\n        }\n        return seed;\n    }\n};\n\n// --- Problem Data ---\nint N, K;\nstd::vector<int> target_a;\nstd::vector<Point> strawberries;\nstd::vector<std::vector<int>> clusters;\n\n// --- Geometry ---\nLine points_to_line(Point p1, Point p2) {\n    long double a = (long double)p1.y - p2.y;\n    long double b = (long double)p2.x - p1.x;\n    long double c = -a * p1.x - b * p1.y;\n    return {a, b, c};\n}\n\nLine perturb_line(Line l, double amount) {\n    l.c += amount;\n    return l;\n}\n\nint get_side(const Line& l, const Point& p) {\n    long double val = l.a * p.x + l.b * p.y + l.c;\n    if (std::abs(val) < 1e-9) return 0;\n    return val > 0 ? 1 : -1;\n}\n\nLine to_cartesian(LinePolar lp) {\n    return {std::cos((long double)lp.theta), std::sin((long double)lp.theta), (long double)-lp.rho};\n}\n\nLinePolar to_polar(Line l) {\n    if (std::abs(l.a) < 1e-12 && std::abs(l.b) < 1e-12) return {0,0};\n    long double norm = std::sqrt(l.a * l.a + l.b * l.b);\n    long double a_ = l.a / norm;\n    long double b_ = l.b / norm;\n    long double c_ = l.c / norm;\n    \n    double rho = -c_;\n    double theta = std::atan2((double)b_, (double)a_);\n\n    if (theta < 0) theta += 2 * PI;\n    theta = fmod(theta, 2*PI);\n    if (theta >= PI) {\n        theta -= PI;\n        rho = -rho;\n    }\n    return {(double)theta, (double)rho};\n}\n\n// --- Candidate Generation ---\nPoint get_centroid(const std::vector<int>& strawberry_indices) {\n    if (strawberry_indices.empty()) return {0, 0};\n    long long sum_x = 0, sum_y = 0;\n    for (int idx : strawberry_indices) {\n        sum_x += strawberries[idx].x;\n        sum_y += strawberries[idx].y;\n    }\n    return {sum_x / (long long)strawberry_indices.size(), sum_y / (long long)strawberry_indices.size()};\n}\n\nLine gen_candidate_p2p() {\n    int c1_idx = rnd.next_int(clusters.size());\n    int c2_idx = rnd.next_int(clusters.size());\n    if (clusters.size() > 1 && c1_idx == c2_idx) {\n        c2_idx = (c1_idx + 1) % clusters.size();\n    }\n    \n    if (clusters[c1_idx].empty() || clusters[c2_idx].empty()) {\n        Point p1 = {(long long)rnd.next_int(20001) - 10000, (long long)rnd.next_int(20001) - 10000};\n        Point p2 = {(long long)rnd.next_int(20001) - 10000, (long long)rnd.next_int(20001) - 10000};\n        if (p1.x == p2.x && p1.y == p2.y) p2.x++;\n        return points_to_line(p1, p2);\n    }\n    \n    int s1_idx = clusters[c1_idx][rnd.next_int(clusters[c1_idx].size())];\n    int s2_idx = clusters[c2_idx][rnd.next_int(clusters[c2_idx].size())];\n    Line l = points_to_line(strawberries[s1_idx], strawberries[s2_idx]);\n    return perturb_line(l, (rnd.next_double() * 2 - 1) * 0.1);\n}\n\nLine gen_candidate_centroid() {\n    int c1_idx = rnd.next_int(clusters.size());\n    int c2_idx = rnd.next_int(clusters.size());\n    if (clusters.size() > 1 && c1_idx == c2_idx) {\n        c2_idx = (c1_idx + 1) % clusters.size();\n    }\n\n    Point centroid1 = get_centroid(clusters[c1_idx]);\n    Point centroid2 = get_centroid(clusters[c2_idx]);\n    \n    if (centroid1.x == centroid2.x && centroid1.y == centroid2.y) {\n        return gen_candidate_p2p();\n    }\n\n    Point mid_point = {(centroid1.x + centroid2.x) / 2, (centroid1.y + centroid2.y) / 2};\n    Point p_on_perp = {mid_point.x - (centroid2.y - centroid1.y), mid_point.y + (centroid2.x - centroid1.x)};\n\n    Line l = points_to_line(mid_point, p_on_perp);\n    double angle = (rnd.next_double() * 2 - 1) * PI / 12.0;\n    long double cosa = cos(angle), sina = sin(angle);\n    long double new_a = l.a * cosa - l.b * sina;\n    long double new_b = l.a * sina + l.b * cosa;\n    long double new_c = -new_a * mid_point.x - new_b * mid_point.y;\n    return {new_a, new_b, new_c};\n}\n\nLine generate_candidate_line() {\n    if (clusters.size() < 2) {\n        Point p1 = {(long long)rnd.next_int(20001) - 10000, (long long)rnd.next_int(20001) - 10000};\n        Point p2 = {(long long)rnd.next_int(20001) - 10000, (long long)rnd.next_int(20001) - 10000};\n        if (p1.x == p2.x && p1.y == p2.y) p2.x++;\n        return points_to_line(p1, p2);\n    }\n    if (rnd.next_double() < 0.5) {\n        return gen_candidate_p2p();\n    } else {\n        return gen_candidate_centroid();\n    }\n}\n\n// --- Clustering ---\nvoid perform_clustering() {\n    std::vector<int> target_sizes;\n    for (int d = 1; d <= 10; ++d) {\n        for (int i = 0; i < target_a[d]; ++i) {\n            target_sizes.push_back(d);\n        }\n    }\n    std::shuffle(target_sizes.begin(), target_sizes.end(), std::mt19937(rnd.next()));\n\n    std::vector<bool> assigned(N, false);\n    int assigned_count = 0;\n\n    for (int d : target_sizes) {\n        if (assigned_count + d > N) continue;\n\n        int seed_idx = -1;\n        int start_node = rnd.next_int(N);\n        for (int i = 0; i < N; ++i) {\n            int current_node = (start_node + i) % N;\n            if (!assigned[current_node]) {\n                seed_idx = current_node;\n                break;\n            }\n        }\n        if (seed_idx == -1) break;\n\n        std::vector<std::pair<long long, int>> dists;\n        for (int i = 0; i < N; ++i) {\n            if (!assigned[i]) {\n                long long dx = strawberries[seed_idx].x - strawberries[i].x;\n                long long dy = strawberries[seed_idx].y - strawberries[i].y;\n                dists.push_back({dx * dx + dy * dy, i});\n            }\n        }\n        \n        if (dists.size() > (size_t)d) {\n            std::nth_element(dists.begin(), dists.begin() + d, dists.end());\n        }\n\n        std::vector<int> new_cluster;\n        for (int i = 0; i < std::min((int)dists.size(), d); ++i) {\n            int strawberry_idx = dists[i].second;\n            new_cluster.push_back(strawberry_idx);\n            assigned[strawberry_idx] = true;\n        }\n        clusters.push_back(new_cluster);\n        assigned_count += d;\n    }\n}\n\n\n// --- Score Calculation ---\nint calculate_score_val(const std::vector<Line>& lines) {\n    if (lines.empty()) return 0;\n    \n    std::unordered_map<std::vector<int>, int, VectorHasher> piece_counts;\n    for (int i = 0; i < N; ++i) {\n        std::vector<int> signature;\n        signature.reserve(lines.size());\n        bool on_line = false;\n        for (const auto& line : lines) {\n            int side = get_side(line, strawberries[i]);\n            if (side == 0) {\n                on_line = true;\n                break;\n            }\n            signature.push_back(side);\n        }\n        if (!on_line) {\n            piece_counts[signature]++;\n        }\n    }\n\n    std::vector<int> b(11, 0);\n    for (const auto& pair : piece_counts) {\n        if (pair.second >= 1 && pair.second <= 10) {\n            b[pair.second]++;\n        }\n    }\n\n    int score = 0;\n    for (int d = 1; d <= 10; ++d) {\n        score += std::min(target_a[d], b[d]);\n    }\n    return score;\n}\n\nstd::unordered_map<std::vector<int>, std::vector<int>, VectorHasher> current_partition;\nstd::vector<int> current_b_dist;\n\nint get_score_from_b(const std::vector<int>& b) {\n    int score = 0;\n    for (int d = 1; d <= 10; ++d) {\n        score += std::min(target_a[d], b[d]);\n    }\n    return score;\n}\n\nint calculate_score_with_new_line(const Line& new_line) {\n    std::vector<int> next_b_dist = current_b_dist;\n    for (auto const& [sig, strawberry_indices] : current_partition) {\n        int old_count = strawberry_indices.size();\n        if (old_count >= 1 && old_count <= 10) {\n            next_b_dist[old_count]--;\n        }\n        \n        int count1 = 0, count2 = 0;\n        for (int idx : strawberry_indices) {\n            int side = get_side(new_line, strawberries[idx]);\n            if (side == 1) count1++;\n            else if (side == -1) count2++;\n        }\n\n        if (count1 >= 1 && count1 <= 10) next_b_dist[count1]++;\n        if (count2 >= 1 && count2 <= 10) next_b_dist[count2]++;\n    }\n    return get_score_from_b(next_b_dist);\n}\n\nvoid add_line_to_state(const Line& new_line) {\n    auto old_partition = current_partition;\n    current_partition.clear();\n    std::vector<int> next_b_dist(11, 0);\n\n    for (auto const& [sig, strawberry_indices] : old_partition) {\n        std::vector<int> group1, group2;\n        for (int idx : strawberry_indices) {\n            int side = get_side(new_line, strawberries[idx]);\n            if (side == 1) group1.push_back(idx);\n            else if (side == -1) group2.push_back(idx);\n        }\n        if (!group1.empty()) {\n            std::vector<int> new_sig = sig; new_sig.push_back(1);\n            current_partition[new_sig] = group1;\n            int new_count = group1.size();\n            if (new_count >= 1 && new_count <= 10) next_b_dist[new_count]++;\n        }\n        if (!group2.empty()) {\n            std::vector<int> new_sig = sig; new_sig.push_back(-1);\n            current_partition[new_sig] = group2;\n            int new_count = group2.size();\n            if (new_count >= 1 && new_count <= 10) next_b_dist[new_count]++;\n        }\n    }\n    current_b_dist = next_b_dist;\n}\n\n// --- Main ---\nvoid output_solution(const std::vector<Line>& lines) {\n    std::cout << lines.size() << std::endl;\n    for (const auto& l : lines) {\n        long long p1x, p1y, p2x, p2y;\n        if (std::abs(l.b) > 1e-9 && (std::abs(l.a / l.b) < 1)) {\n            p1x = -INF_COORD; p1y = std::round(- (l.c + l.a * p1x) / l.b);\n            p2x = INF_COORD; p2y = std::round(- (l.c + l.a * p2x) / l.b);\n        } else if (std::abs(l.a) > 1e-9) {\n            p1y = -INF_COORD; p1x = std::round(- (l.c + l.b * p1y) / l.a);\n            p2y = INF_COORD; p2x = std::round(- (l.c + l.b * p2y) / l.a);\n        } else { // Should not happen with valid lines\n            p1x = 0; p1y = 0; p2x = 1; p2y = 1;\n        }\n        std::cout << p1x << \" \" << p1y << \" \" << p2x << \" \" << p2y << std::endl;\n    }\n}\n\nvoid solve() {\n    std::cin >> N >> K;\n    target_a.resize(11);\n    for (int d = 1; d <= 10; ++d) std::cin >> target_a[d];\n    strawberries.resize(N);\n    for (int i = 0; i < N; ++i) std::cin >> strawberries[i].x >> strawberries[i].y;\n    \n    perform_clustering();\n    \n    // Fast Greedy Construction\n    std::vector<Line> current_lines;\n    current_b_dist.assign(11, 0);\n    std::vector<int> initial_indices(N);\n    std::iota(initial_indices.begin(), initial_indices.end(), 0);\n    current_partition[{}] = initial_indices;\n    if (N >= 1 && N <= 10) current_b_dist[N] = 1;\n    \n    double greedy_time_limit = 1.6;\n    const int T_SEARCH = 40;\n    for (int k = 0; k < K; ++k) {\n        if (get_time() > greedy_time_limit) break;\n        Line best_line = {};\n        int best_score = -1;\n        for (int i = 0; i < T_SEARCH; ++i) {\n            Line candidate_line = generate_candidate_line();\n            int score = calculate_score_with_new_line(candidate_line);\n            if (score > best_score) {\n                best_score = score;\n                best_line = candidate_line;\n            }\n        }\n        if (best_score != -1) {\n            current_lines.push_back(best_line);\n            add_line_to_state(best_line);\n        } else break;\n    }\n    \n    while (current_lines.size() < (size_t)K) {\n        current_lines.push_back(generate_candidate_line());\n    }\n\n    // Simulated Annealing\n    std::vector<LinePolar> polar_lines;\n    polar_lines.reserve(current_lines.size());\n    for(const auto& l : current_lines) polar_lines.push_back(to_polar(l));\n    \n    int current_score = calculate_score_val(current_lines);\n    std::vector<Line> best_lines = current_lines;\n    int best_score = current_score;\n\n    double T_start = 10.0, T_end = 0.01;\n    double time_start_sa = get_time(), time_end_sa = TIME_LIMIT;\n    const double P_REPLACE = 0.1;\n\n    while(true) {\n        double current_time = get_time();\n        if (current_time >= time_end_sa) break;\n\n        double progress = (current_time - time_start_sa) / (time_end_sa - time_start_sa + 1e-9);\n        double T = T_start * std::pow(T_end / T_start, progress);\n\n        if (polar_lines.empty()) break;\n        int line_idx = rnd.next_int(polar_lines.size());\n        \n        std::vector<Line> new_lines = current_lines;\n        \n        if (rnd.next_double() < P_REPLACE) {\n            new_lines[line_idx] = generate_candidate_line();\n        } else {\n            LinePolar new_polar = polar_lines[line_idx];\n            double move_range = (1.0 - progress) * 0.5;\n            new_polar.theta += (rnd.next_double() * 2 - 1) * PI * move_range;\n            new_polar.rho += (rnd.next_double() * 2 - 1) * 10000 * move_range;\n\n            if (new_polar.theta < 0) new_polar.theta += 2*PI;\n            new_polar.theta = fmod(new_polar.theta, 2*PI);\n            if (new_polar.theta >= PI) {\n                new_polar.theta -= PI; new_polar.rho *= -1;\n            }\n            new_lines[line_idx] = to_cartesian(new_polar);\n        }\n        \n        int new_score = calculate_score_val(new_lines);\n        double delta = new_score - current_score;\n\n        if (delta > 0 || std::exp(delta / T) > rnd.next_double()) {\n            current_score = new_score;\n            current_lines = new_lines;\n            polar_lines[line_idx] = to_polar(current_lines[line_idx]);\n            if (new_score > best_score) {\n                best_score = new_score;\n                best_lines = new_lines;\n            }\n        }\n    }\n    output_solution(best_lines);\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <tuple>\n#include <chrono>\n#include <map>\n#include <queue>\n#include <set>\n\nusing namespace std;\n\n// Timer\nauto start_time = chrono::steady_clock::now();\ndouble time_limit = 4.9;\n\nbool is_time_over() {\n    auto now = chrono::steady_clock::now();\n    double elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count() / 1000.0;\n    return elapsed > time_limit;\n}\n\nint N;\nlong long M_initial;\nlong long C;\n\nstruct Point {\n    int x, y;\n\n    bool operator==(const Point& other) const {\n        return x == other.x && y == other.y;\n    }\n    bool operator<(const Point& other) const {\n        if (x != other.x) return x < other.x;\n        return y < other.y;\n    }\n    Point operator+(const Point& other) const {\n        return {x + other.x, y + other.y};\n    }\n    Point operator-(const Point& other) const {\n        return {x - other.x, y - other.y};\n    }\n};\n\nlong long dot_product(const Point& a, const Point& b) {\n    return (long long)a.x * b.x + (long long)a.y * b.y;\n}\n\nlong long get_weight(const Point& p) {\n    long long dx = p.x - C;\n    long long dy = p.y - C;\n    return dx * dx + dy * dy + 1;\n}\n\nstruct Candidate {\n    long long weight;\n    Point p_new, p_adj1, p_corner, p_adj2;\n\n    bool operator>(const Candidate& other) const {\n        return weight < other.weight;\n    }\n};\n\nbool has_dot[62][62];\nvector<Point> dots;\nvector<tuple<Point, Point, Point, Point>> solution_moves;\npriority_queue<Candidate, vector<Candidate>, greater<Candidate>> pq;\n\nmap<int, set<pair<int, int>>> H_segs, V_segs, D1_segs, D2_segs;\n\nbool is_in_bounds(const Point& p) {\n    return p.x >= 0 && p.x < N && p.y >= 0 && p.y < N;\n}\n\nbool check_perimeter_clean(const Point& p_new, const Point& p_adj1, const Point& p_corner, const Point& p_adj2) {\n    auto check_segment = [&](const Point& a, const Point& b) {\n        int dx = b.x - a.x;\n        int dy = b.y - a.y;\n        int common_divisor = std::gcd(abs(dx), abs(dy));\n        if (common_divisor <= 1) return true;\n        int step_x = dx / common_divisor;\n        int step_y = dy / common_divisor;\n        for (int i = 1; i < common_divisor; ++i) {\n            Point p = {a.x + i * step_x, a.y + i * step_y};\n            if (has_dot[p.x][p.y]) return false;\n        }\n        return true;\n    };\n    \n    if (!check_segment(p_corner, p_adj1)) return false;\n    if (!check_segment(p_adj1, p_new)) return false;\n    if (!check_segment(p_new, p_adj2)) return false;\n    if (!check_segment(p_adj2, p_corner)) return false;\n    return true;\n}\n\nbool check_segment_overlap(map<int, set<pair<int, int>>>& seg_map, int line_idx, int c1, int c2) {\n    if (c1 == c2) return false;\n    int min_c = min(c1, c2);\n    int max_c = max(c1, c2);\n\n    if (seg_map.find(line_idx) == seg_map.end()) return false;\n\n    const auto& intervals = seg_map.at(line_idx);\n    auto it = intervals.lower_bound({min_c, 0});\n\n    if (it != intervals.begin()) {\n        auto prev_it = prev(it);\n        if (max(min_c, prev_it->first) < min(max_c, prev_it->second)) return true;\n    }\n    if (it != intervals.end()) {\n        if (max(min_c, it->first) < min(max_c, it->second)) return true;\n    }\n    return false;\n}\n\nvoid add_segment(map<int, set<pair<int, int>>>& seg_map, int line_idx, int c1, int c2) {\n    if (c1 == c2) return;\n    int min_c = min(c1, c2);\n    int max_c = max(c1, c2);\n    seg_map[line_idx].insert({min_c, max_c});\n}\n\nvoid find_and_push_candidates(const Point& p_adj1, const Point& p_corner, const Point& p_adj2) {\n    Point v1 = p_adj1 - p_corner;\n    Point v2 = p_adj2 - p_corner;\n    \n    if ((v1.x == 0 && v1.y == 0) || (v2.x == 0 && v2.y == 0)) return;\n\n    bool is_axis_aligned = (v1.x == 0 || v1.y == 0);\n    bool is_45_tilted = (abs(v1.x) == abs(v1.y));\n    if (!is_axis_aligned && !is_45_tilted) {\n        return;\n    }\n\n    Point p_new = p_adj1 + p_adj2 - p_corner;\n    if (is_in_bounds(p_new) && !has_dot[p_new.x][p_new.y]) {\n        if (check_perimeter_clean(p_new, p_adj1, p_corner, p_adj2)) {\n            pq.push({get_weight(p_new), p_new, p_adj1, p_corner, p_adj2});\n        }\n    }\n}\n\nvoid find_new_candidates(const Point& p_added) {\n    for (size_t i = 0; i < dots.size() - 1; ++i) {\n        for (size_t j = i + 1; j < dots.size() - 1; ++j) {\n            const Point& p_i = dots[i];\n            const Point& p_j = dots[j];\n            \n            if (dot_product(p_i - p_added, p_j - p_added) == 0) find_and_push_candidates(p_i, p_added, p_j);\n            if (dot_product(p_added - p_i, p_j - p_i) == 0) find_and_push_candidates(p_added, p_i, p_j);\n            if (dot_product(p_added - p_j, p_i - p_j) == 0) find_and_push_candidates(p_added, p_j, p_i);\n        }\n    }\n}\n\nvoid find_initial_candidates() {\n    for (size_t i = 0; i < dots.size(); ++i) {\n        for (size_t j = i + 1; j < dots.size(); ++j) {\n            for (size_t k = j + 1; k < dots.size(); ++k) {\n                Point p_i = dots[i], p_j = dots[j], p_k = dots[k];\n                if (dot_product(p_j - p_i, p_k - p_i) == 0) find_and_push_candidates(p_j, p_i, p_k);\n                if (dot_product(p_i - p_j, p_k - p_j) == 0) find_and_push_candidates(p_i, p_j, p_k);\n                if (dot_product(p_i - p_k, p_j - p_k) == 0) find_and_push_candidates(p_i, p_k, p_j);\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N >> M_initial;\n    C = (N - 1) / 2;\n\n    for (int i = 0; i < M_initial; ++i) {\n        int x, y;\n        cin >> x >> y;\n        dots.push_back({x, y});\n        has_dot[x][y] = true;\n    }\n\n    find_initial_candidates();\n\n    while (!pq.empty() && !is_time_over()) {\n        Candidate c = pq.top();\n        pq.pop();\n\n        if (has_dot[c.p_new.x][c.p_new.y]) continue;\n\n        Point p_new = c.p_new, p_corner = c.p_corner, p_adj1 = c.p_adj1, p_adj2 = c.p_adj2;\n        if (!check_perimeter_clean(p_new, p_adj1, p_corner, p_adj2)) continue;\n\n        auto check_s = [&](const Point& u, const Point& v) {\n            if (u.y == v.y) return !check_segment_overlap(H_segs, u.y, u.x, v.x);\n            if (u.x == v.x) return !check_segment_overlap(V_segs, u.x, u.y, v.y);\n            if (u.x + u.y == v.x + v.y) return !check_segment_overlap(D1_segs, u.x + u.y, u.x, v.x);\n            return !check_segment_overlap(D2_segs, u.x - u.y, u.x, v.x);\n        };\n\n        if (!check_s(p_corner, p_adj1)) continue;\n        if (!check_s(p_adj1, p_new)) continue;\n        if (!check_s(p_new, p_adj2)) continue;\n        if (!check_s(p_adj2, p_corner)) continue;\n        \n        auto add_s = [&](const Point& u, const Point& v){\n            if (u.y == v.y) add_segment(H_segs, u.y, u.x, v.x);\n            else if (u.x == v.x) add_segment(V_segs, u.x, u.y, v.y);\n            else if (u.x + u.y == v.x + v.y) add_segment(D1_segs, u.x + u.y, u.x, v.x);\n            else add_segment(D2_segs, u.x - u.y, u.x, v.x);\n        };\n\n        add_s(p_corner, p_adj1);\n        add_s(p_adj1, p_new);\n        add_s(p_new, p_adj2);\n        add_s(p_adj2, p_corner);\n\n        solution_moves.emplace_back(p_new, p_adj1, p_corner, p_adj2);\n        dots.push_back(p_new);\n        has_dot[p_new.x][p_new.y] = true;\n        \n        find_new_candidates(p_new);\n    }\n\n    cout << solution_moves.size() << endl;\n    for (const auto& move : solution_moves) {\n        cout << get<0>(move).x << \" \" << get<0>(move).y << \" \"\n             << get<1>(move).x << \" \" << get<1>(move).y << \" \"\n             << get<2>(move).x << \" \" << get<2>(move).y << \" \"\n             << get<3>(move).x << \" \" << get<3>(move).y << endl;\n    }\n\n    return 0;\n}","ahc015":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <algorithm>\n#include <map>\n#include <cmath>\n\nconst int GRID_SIZE = 10;\n\n// Represents the state of the 10x10 grid.\nstruct Grid {\n    std::vector<std::vector<int>> board;\n\n    Grid() : board(GRID_SIZE, std::vector<int>(GRID_SIZE, 0)) {}\n\n    // Places a candy of a given flavor at the p-th empty cell (1-indexed).\n    void place(int p, int flavor) {\n        int empty_count = 0;\n        for (int i = 0; i < GRID_SIZE; ++i) {\n            for (int j = 0; j < GRID_SIZE; ++j) {\n                if (board[i][j] == 0) {\n                    empty_count++;\n                    if (empty_count == p) {\n                        board[i][j] = flavor;\n                        return;\n                    }\n                }\n            }\n        }\n    }\n};\n\n// Simulates a tilt operation on the grid and returns the new grid state.\nGrid simulate_tilt(const Grid& current_grid, char dir) {\n    Grid next_grid; // Initializes to an empty board.\n    \n    if (dir == 'F') { // Move Up\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            int current_row = 0;\n            for (int i = 0; i < GRID_SIZE; ++i) {\n                if (current_grid.board[i][j] != 0) {\n                    next_grid.board[current_row++][j] = current_grid.board[i][j];\n                }\n            }\n        }\n    } else if (dir == 'B') { // Move Down\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            int current_row = GRID_SIZE - 1;\n            for (int i = GRID_SIZE - 1; i >= 0; --i) {\n                if (current_grid.board[i][j] != 0) {\n                    next_grid.board[current_row--][j] = current_grid.board[i][j];\n                }\n            }\n        }\n    } else if (dir == 'L') { // Move Left\n        for (int i = 0; i < GRID_SIZE; ++i) {\n            int current_col = 0;\n            for (int j = 0; j < GRID_SIZE; ++j) {\n                if (current_grid.board[i][j] != 0) {\n                    next_grid.board[i][current_col++] = current_grid.board[i][j];\n                }\n            }\n        }\n    } else if (dir == 'R') { // Move Right\n        for (int i = 0; i < GRID_SIZE; ++i) {\n            int current_col = GRID_SIZE - 1;\n            for (int j = GRID_SIZE - 1; j >= 0; --j) {\n                if (current_grid.board[i][j] != 0) {\n                    next_grid.board[i][current_col--] = current_grid.board[i][j];\n                }\n            }\n        }\n    }\n    return next_grid;\n}\n\n// Calculates the sum of squares of connected component sizes using BFS.\nlong long calculate_conn_score(const Grid& grid) {\n    long long total_score = 0;\n    std::vector<std::vector<bool>> visited(GRID_SIZE, std::vector<bool>(GRID_SIZE, false));\n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            if (grid.board[i][j] != 0 && !visited[i][j]) {\n                int flavor = grid.board[i][j];\n                long long component_size = 0;\n                std::vector<std::pair<int, int>> q;\n                q.push_back({i, j});\n                visited[i][j] = true;\n                \n                int head = 0;\n                while(head < q.size()){\n                    auto [r, c] = q[head++];\n                    component_size++;\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 < GRID_SIZE && nc >= 0 && nc < GRID_SIZE &&\n                            !visited[nr][nc] && grid.board[nr][nc] == flavor) {\n                            visited[nr][nc] = true;\n                            q.push_back({nr, nc});\n                        }\n                    }\n                }\n                total_score += component_size * component_size;\n            }\n        }\n    }\n    return total_score;\n}\n\n// Global map from flavor to its target side.\nstd::map<int, int> target_side_map; // 0: Top, 1: Left, 2: Right\n\n// Calculates the proximity score (negative sum of distances to target sides).\nlong long calculate_prox_score(const Grid& grid) {\n    long long total_dist = 0;\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            if (grid.board[i][j] != 0) {\n                int flavor = grid.board[i][j];\n                int target_side = target_side_map.at(flavor);\n                if (target_side == 0) { // Top\n                    total_dist += i;\n                } else if (target_side == 1) { // Left\n                    total_dist += j;\n                } else { // Right\n                    total_dist += (GRID_SIZE - 1 - j);\n                }\n            }\n        }\n    }\n    return -total_dist;\n}\n\n// Calculates a penalty for having candies of different flavors adjacent to each other.\nlong long calculate_adj_penalty_score(const Grid& grid) {\n    long long penalty = 0;\n    // Check right and down to avoid double counting\n    for (int r = 0; r < GRID_SIZE; ++r) {\n        for (int c = 0; c < GRID_SIZE; ++c) {\n            if (grid.board[r][c] == 0) continue;\n            int current_flavor = grid.board[r][c];\n            // Check right neighbor\n            if (c + 1 < GRID_SIZE && grid.board[r][c+1] != 0 && grid.board[r][c+1] != current_flavor) {\n                penalty--;\n            }\n            // Check down neighbor\n            if (r + 1 < GRID_SIZE && grid.board[r+1][c] != 0 && grid.board[r+1][c] != current_flavor) {\n                penalty--;\n            }\n        }\n    }\n    return penalty;\n}\n\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    std::vector<int> f(100);\n    std::map<int, int> flavor_counts;\n    for (int i = 0; i < 100; ++i) {\n        std::cin >> f[i];\n        flavor_counts[f[i]]++;\n    }\n    \n    std::vector<std::pair<int, int>> sorted_flavors;\n    for (int i = 1; i <= 3; ++i) {\n        sorted_flavors.push_back({flavor_counts.count(i) ? flavor_counts[i] : 0, i});\n    }\n    std::sort(sorted_flavors.rbegin(), sorted_flavors.rend());\n\n    // Assign targets to sides based on flavor frequency.\n    // 0: Top, 1: Left, 2: Right\n    std::vector<int> target_sides = {0, 1, 2};\n    for (size_t i = 0; i < 3; ++i) {\n        target_side_map[sorted_flavors[i].second] = target_sides[i];\n    }\n\n    Grid current_grid;\n\n    for (int t = 1; t <= 100; ++t) {\n        int p;\n        std::cin >> p;\n        current_grid.place(p, f[t - 1]);\n\n        if (t == 100) {\n            break;\n        }\n\n        char best_dir = 'F';\n        double best_score = -1e18;\n\n        const char dirs[] = {'F', 'B', 'L', 'R'};\n        for (char dir : dirs) {\n            Grid next_grid = simulate_tilt(current_grid, dir);\n            \n            long long conn_score = calculate_conn_score(next_grid);\n            long long prox_score = calculate_prox_score(next_grid);\n            long long adj_penalty_score = calculate_adj_penalty_score(next_grid);\n\n            double t_double = static_cast<double>(t);\n            double w_conn = t_double * t_double;\n            // The scaling factors for prox and adj scores are chosen heuristically\n            // to balance their magnitudes against the connectivity score.\n            double w_prox = 2.0 * (101.0 - t_double) * (101.0 - t_double);\n            double w_adj = 10.0 * t_double * t_double;\n            \n            double current_total_score = w_conn * conn_score + w_prox * prox_score + w_adj * adj_penalty_score;\n            \n            if (current_total_score > best_score) {\n                best_score = current_total_score;\n                best_dir = dir;\n            }\n        }\n        \n        std::cout << best_dir << std::endl;\n        current_grid = simulate_tilt(current_grid, best_dir);\n    }\n\n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <set>\n#include <chrono>\n\n// --- Globals ---\nint M;\ndouble EPS;\nint N;\nstd::vector<int> clique_sizes;\n\n// --- Graph representation and utilities ---\nstruct Graph {\n    int n_vertices;\n    std::vector<std::vector<int>> adj;\n    int n_edges;\n\n    Graph(int n) : n_vertices(n), adj(n), n_edges(0) {}\n\n    void add_edge(int u, int v) {\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n        n_edges++;\n    }\n\n    static Graph from_string(int n, const std::string& s) {\n        Graph g(n);\n        int k = 0;\n        for (int i = 0; i < n; ++i) {\n            for (int j = i + 1; j < n; ++j) {\n                if (s[k] == '1') {\n                    g.add_edge(i, j);\n                }\n                k++;\n            }\n        }\n        return g;\n    }\n};\n\n// --- Problem Logic ---\n\ndouble binary_entropy(double p) {\n    if (p <= 0.0 || p >= 1.0) {\n        return 0.0;\n    }\n    return -p * std::log2(p) - (1.0 - p) * std::log2(1.0 - p);\n}\n\nvoid determine_N() {\n    double alpha = 1.5 + 5.0 * EPS;\n    double capacity = std::max(0.01, 1.0 - binary_entropy(EPS));\n    double bits_needed = std::log2(M) * alpha;\n    double edges_needed = bits_needed / capacity;\n    double n_theory = (1.0 + std::sqrt(std::max(0.0, 1.0 + 8.0 * edges_needed))) / 2.0;\n    \n    N = static_cast<int>(std::ceil(n_theory));\n    // To have M distinct graphs of the chosen structure (cliques of size 0, 2, ..., M),\n    // we need N to be at least M.\n    N = std::max(N, M);\n    \n    N = std::min(100, std::max(4, N));\n}\n\n\nvoid generate_base_graphs() {\n    clique_sizes.resize(M);\n    if (M > 0) {\n        clique_sizes[0] = 0; // Empty graph\n    }\n    for (int i = 1; i < M; ++i) {\n        clique_sizes[i] = i + 1; // Cliques of size 2, 3, ..., M\n    }\n    \n    std::cout << N << std::endl;\n    for (int k = 0; k < M; ++k) {\n        int C = clique_sizes[k];\n        std::string s = \"\";\n        s.reserve(N * (N - 1) / 2);\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) {\n                if (i < C && j < C) {\n                    s += '1';\n                } else {\n                    s += '0';\n                }\n            }\n        }\n        std::cout << s << std::endl;\n    }\n}\n\n\nvoid solve() {\n    // Phase 1: Determine N and generate graphs\n    determine_N();\n    generate_base_graphs();\n    std::cout.flush();\n\n    // Precompute theoretical properties of base graphs\n    std::vector<long long> clique_edge_counts(N + 1);\n    for (int i = 0; i <= N; ++i) {\n        clique_edge_counts[i] = (long long)i * (i - 1) / 2;\n    }\n\n    // Phase 2: Process queries\n    for (int q = 0; q < 100; ++q) {\n        std::string H_str;\n        std::cin >> H_str;\n\n        Graph H = Graph::from_string(N, H_str);\n\n        // Heuristic for finding densest k-subgraph for all k using degeneracy order.\n        std::vector<int> degree(N);\n        for(int i = 0; i < N; ++i) degree[i] = H.adj[i].size();\n\n        std::vector<std::vector<int>> buckets(N);\n        for(int i = 0; i < N; ++i) buckets[degree[i]].push_back(i);\n\n        std::vector<int> pos(N);\n        for(int d = 0; d < N; ++d) {\n            for(size_t i = 0; i < buckets[d].size(); ++i) {\n                pos[buckets[d][i]] = i;\n            }\n        }\n\n        long long current_edges = H.n_edges;\n        std::vector<long long> edges_in_subgraph(N + 1, 0);\n        std::vector<bool> removed(N, false);\n        \n        int min_deg = 0;\n        for (int k = N; k > 0; --k) {\n            edges_in_subgraph[k] = current_edges;\n            \n            while(min_deg < N && buckets[min_deg].empty()) {\n                min_deg++;\n            }\n            if (min_deg == N) break;\n\n            int v = buckets[min_deg].back();\n            buckets[min_deg].pop_back();\n            removed[v] = true;\n\n            current_edges -= degree[v];\n\n            for (int u : H.adj[v]) {\n                if (!removed[u]) {\n                    int d_u = degree[u];\n                    int pos_u = pos[u];\n                    int last_v_in_bucket = buckets[d_u].back();\n                    \n                    buckets[d_u][pos_u] = last_v_in_bucket;\n                    pos[last_v_in_bucket] = pos_u;\n                    buckets[d_u].pop_back();\n\n                    degree[u]--;\n                    buckets[d_u-1].push_back(u);\n                    pos[u] = buckets[d_u-1].size() - 1;\n                }\n            }\n        }\n        \n        int best_idx = -1;\n        double min_flips = 1e18;\n\n        for (int i = 0; i < M; ++i) {\n            int C = clique_sizes[i];\n            if (C > N) continue;\n            \n            long long E_star = edges_in_subgraph[C];\n            long long E_clique = clique_edge_counts[C];\n\n            // Estimated flips = (edges missing from clique) + (edges outside clique)\n            double estimated_flips = (double)(E_clique - E_star) + (H.n_edges - E_star);\n\n            if (estimated_flips < min_flips) {\n                min_flips = estimated_flips;\n                best_idx = i;\n            }\n        }\n        \n        std::cout << best_idx << std::endl;\n        std::cout.flush();\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    std::cin >> M >> EPS;\n    solve();\n\n    return 0;\n}","ahc017":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <iomanip>\n#include <functional>\n#include <queue>\n\nusing namespace std;\n\nconst long long INF = 1e12;\n\nstruct Edge {\n    int id;\n    int u, v, w;\n};\n\nstruct Point {\n    int x, y;\n};\n\nauto start_time = chrono::high_resolution_clock::now();\n\ndouble get_time() {\n    auto now = chrono::high_resolution_clock::now();\n    return chrono::duration_cast<chrono::duration<double>>(now - start_time).count();\n}\n\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\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    vector<vector<int>> edge_indices_adj(N);\n    for (int i = 0; i < M; ++i) {\n        edges[i].id = i;\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\n        edges[i].u--; \n        edges[i].v--;\n        adj[edges[i].u].push_back({edges[i].v, edges[i].w});\n        adj[edges[i].v].push_back({edges[i].u, edges[i].w});\n        edge_indices_adj[edges[i].u].push_back(i);\n        edge_indices_adj[edges[i].v].push_back(i);\n    }\n\n    vector<Point> coords(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> coords[i].x >> coords[i].y;\n    }\n    \n    vector<long long> edge_path_counts(M, 0);\n    int SAMPLES = 100;\n    if (N > 800) SAMPLES = 60;\n    vector<int> sample_nodes(N);\n    iota(sample_nodes.begin(), sample_nodes.end(), 0);\n    shuffle(sample_nodes.begin(), sample_nodes.end(), rng);\n\n    for (int i = 0; i < SAMPLES; ++i) {\n        int start_node = sample_nodes[i];\n        \n        vector<long long> dist(N, INF);\n        vector<int> parent_edge(N, -1);\n        dist[start_node] = 0;\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n        pq.push({0, start_node});\n\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n\n            if (d > dist[u]) continue;\n\n            for (auto& edge_idx : edge_indices_adj[u]) {\n                int v = (edges[edge_idx].u == u) ? edges[edge_idx].v : edges[edge_idx].u;\n                int w = edges[edge_idx].w;\n                if (dist[u] + w < dist[v]) {\n                    dist[v] = dist[u] + w;\n                    parent_edge[v] = edge_idx;\n                    pq.push({dist[v], v});\n                }\n            }\n        }\n\n        vector<vector<int>> tree_adj(N);\n        for(int j=0; j<N; ++j) {\n            if (parent_edge[j] != -1) {\n                int u = (edges[parent_edge[j]].u == j) ? edges[parent_edge[j]].v : edges[parent_edge[j]].u;\n                tree_adj[u].push_back(j);\n            }\n        }\n        \n        vector<int> subtree_size(N, 0);\n        function<void(int)> dfs_size = [&](int u) {\n            subtree_size[u] = 1;\n            for(int v : tree_adj[u]) {\n                dfs_size(v);\n                subtree_size[u] += subtree_size[v];\n            }\n        };\n        dfs_size(start_node);\n        \n        for(int j=0; j<N; ++j) {\n            if(parent_edge[j] != -1) {\n                edge_path_counts[parent_edge[j]] += (long long)subtree_size[j] * (N - subtree_size[j]);\n            }\n        }\n    }\n    \n    vector<double> edge_importance(M);\n    for (int i = 0; i < M; ++i) {\n        edge_importance[i] = (double)edge_path_counts[i] * edges[i].w;\n    }\n\n    vector<vector<float>> interactions(M, vector<float>(M));\n    vector<pair<double, double>> midpoints(M);\n    for(int i=0; i<M; ++i) {\n        midpoints[i] = {\n            (coords[edges[i].u].x + coords[edges[i].v].x) / 2.0,\n            (coords[edges[i].u].y + coords[edges[i].v].y) / 2.0\n        };\n    }\n\n    for(int i=0; i<M; ++i) {\n        for(int j=i+1; j<M; ++j) {\n            double dx = midpoints[i].first - midpoints[j].first;\n            double dy = midpoints[i].second - midpoints[j].second;\n            double dist_sq = dx*dx + dy*dy;\n            float val = 1.0f / (dist_sq + 1.0f);\n            if (edges[i].u == edges[j].u || edges[i].u == edges[j].v ||\n                edges[i].v == edges[j].u || edges[i].v == edges[j].v) {\n                val *= 2.0f;\n            }\n            interactions[i][j] = interactions[j][i] = val;\n        }\n    }\n\n    vector<int> sorted_edges(M);\n    iota(sorted_edges.begin(), sorted_edges.end(), 0);\n    sort(sorted_edges.begin(), sorted_edges.end(), [&](int a, int b){\n        return edge_importance[a] > edge_importance[b];\n    });\n\n    vector<vector<int>> days(D);\n    vector<int> edge_to_day(M);\n    \n    for (int edge_idx : sorted_edges) {\n        int best_day = -1;\n        float min_cost_increase = 1e18;\n\n        for (int d = 0; d < D; ++d) {\n            if (days[d].size() >= K) continue;\n            \n            float cost_increase = 0;\n            for (int other_edge_idx : days[d]) {\n                cost_increase += interactions[edge_idx][other_edge_idx];\n            }\n\n            if (cost_increase < min_cost_increase) {\n                min_cost_increase = cost_increase;\n                best_day = d;\n            } else if (abs(cost_increase - min_cost_increase) < 1e-9) { // Tie-breaking\n                if (best_day == -1 || days[d].size() < days[best_day].size()) {\n                    best_day = d;\n                }\n            }\n        }\n        days[best_day].push_back(edge_idx);\n        edge_to_day[edge_idx] = best_day;\n    }\n\n    double T0 = 20, T = T0;\n    long long iter_count = 0;\n    \n    double time_limit = 5.8;\n\n    while (true) {\n        iter_count++;\n        if ((iter_count & 255) == 0) {\n            double elapsed = get_time();\n            if (elapsed > time_limit) break;\n            double progress = elapsed / time_limit;\n            T = T0 * (1.0 - progress);\n        }\n\n        int move_type = uniform_int_distribution<>(0, 1)(rng);\n        \n        if (move_type == 0 && M > 0) { // Single edge move\n            int e_idx = uniform_int_distribution<>(0, M - 1)(rng);\n            int d1 = edge_to_day[e_idx];\n            int d2 = uniform_int_distribution<>(0, D - 1)(rng);\n\n            if (d1 == d2 || days[d2].size() >= K) continue;\n            \n            float cost_d1_old = 0;\n            for(int other_e : days[d1]) if(other_e != e_idx) cost_d1_old += interactions[e_idx][other_e];\n            \n            float cost_d2_new = 0;\n            for(int other_e : days[d2]) cost_d2_new += interactions[e_idx][other_e];\n            \n            double delta = cost_d2_new - cost_d1_old;\n\n            if (delta < 0 || (T > 1e-9 && uniform_real_distribution<>(0.0, 1.0)(rng) < exp(-delta / T))) {\n                auto& d1_edges = days[d1];\n                d1_edges.erase(remove(d1_edges.begin(), d1_edges.end(), e_idx), d1_edges.end());\n                days[d2].push_back(e_idx);\n                edge_to_day[e_idx] = d2;\n            }\n        } else if (M > 1) { // Swap move\n            int e1_idx = uniform_int_distribution<>(0, M - 1)(rng);\n            int d1 = edge_to_day[e1_idx];\n            \n            int d2;\n            do {\n                d2 = uniform_int_distribution<>(0, D - 1)(rng);\n            } while (d1 == d2 || days[d2].empty());\n            \n            int e2_idx = days[d2][uniform_int_distribution<>(0, (int)days[d2].size() - 1)(rng)];\n\n            float cost1_in_d1 = 0, cost2_in_d2 = 0, cost1_in_d2 = 0, cost2_in_d1 = 0;\n\n            for(int e_other : days[d1]) {\n                if (e_other == e1_idx) continue;\n                cost1_in_d1 += interactions[e1_idx][e_other];\n                cost2_in_d1 += interactions[e2_idx][e_other];\n            }\n            for(int e_other : days[d2]) {\n                if (e_other == e2_idx) continue;\n                cost2_in_d2 += interactions[e2_idx][e_other];\n                cost1_in_d2 += interactions[e1_idx][e_other];\n            }\n            \n            double delta = (cost2_in_d1 + cost1_in_d2) - (cost1_in_d1 + cost2_in_d2);\n\n            if (delta < 0 || (T > 1e-9 && uniform_real_distribution<>(0.0, 1.0)(rng) < exp(-delta / T))) {\n                auto& d1_edges = days[d1];\n                auto& d2_edges = days[d2];\n                \n                d1_edges.erase(remove(d1_edges.begin(), d1_edges.end(), e1_idx), d1_edges.end());\n                d2_edges.erase(remove(d2_edges.begin(), d2_edges.end(), e2_idx), d2_edges.end());\n                \n                d1_edges.push_back(e2_idx);\n                d2_edges.push_back(e1_idx);\n                \n                edge_to_day[e1_idx] = d2;\n                edge_to_day[e2_idx] = d1;\n            }\n        }\n    }\n\n    vector<int> result(M);\n    for (int i = 0; i < M; ++i) {\n        result[edges[i].id] = edge_to_day[i] + 1;\n    }\n\n    for (int i = 0; i < M; ++i) {\n        cout << result[i] << (i == M - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n\n    return 0;\n}","ahc019":"#include <iostream>\n#include <vector>\n#include <string>\n#include <tuple>\n#include <numeric>\n#include <algorithm>\n#include <set>\n#include <map>\n#include <chrono>\n\nusing namespace std;\n\nint D;\n\nstruct Point3D {\n    int x, y, z;\n    bool operator<(const Point3D& other) const {\n        if (x != other.x) return x < other.x;\n        if (y != other.y) return y < other.y;\n        return z < other.z;\n    }\n    bool operator==(const Point3D& other) const {\n        return x == other.x && y == other.y && z == other.z;\n    }\n};\n\nPoint3D operator+(const Point3D& a, const Point3D& b) {\n    return {a.x + b.x, a.y + b.y, a.z + b.z};\n}\n\nPoint3D operator-(const Point3D& a, const Point3D& b) {\n    return {a.x - b.x, a.y - b.y, a.z - b.z};\n}\n\nusing Shape = vector<Point3D>;\n\n// All 24 rotations of a cube\nconst vector<vector<int>> ROTS = {\n    {1,0,0,0,1,0,0,0,1}, {1,0,0,0,0,-1,0,1,0}, {1,0,0,0,-1,0,0,0,-1}, {1,0,0,0,0,1,0,-1,0},\n    {-1,0,0,0,-1,0,0,0,1}, {-1,0,0,0,0,1,0,1,0}, {-1,0,0,0,1,0,0,0,-1}, {-1,0,0,0,0,-1,0,-1,0},\n    {0,1,0,1,0,0,0,0,-1}, {0,1,0,0,0,1,1,0,0}, {0,1,0,-1,0,0,0,0,1}, {0,1,0,0,0,-1,-1,0,0},\n    {0,-1,0,-1,0,0,0,0,-1}, {0,-1,0,0,0,-1,1,0,0}, {0,-1,0,1,0,0,0,0,1}, {0,-1,0,0,0,1,-1,0,0},\n    {0,0,1,0,1,0,-1,0,0}, {0,0,1,1,0,0,0,1,0}, {0,0,1,0,-1,0,1,0,0}, {0,0,1,-1,0,0,0,-1,0},\n    {0,0,-1,0,-1,0,-1,0,0}, {0,0,-1,-1,0,0,0,1,0}, {0,0,-1,0,1,0,1,0,0}, {0,0,-1,1,0,0,0,-1,0}\n};\n\nPoint3D rotate(const Point3D& p, const vector<int>& R) {\n    return {\n        R[0]*p.x + R[1]*p.y + R[2]*p.z,\n        R[3]*p.x + R[4]*p.y + R[5]*p.z,\n        R[6]*p.x + R[7]*p.y + R[8]*p.z\n    };\n}\n\nShape normalize_shape(Shape s) {\n    if (s.empty()) return {};\n    Point3D min_p = s[0];\n    for (size_t i = 1; i < s.size(); ++i) {\n        min_p.x = min(min_p.x, s[i].x);\n        min_p.y = min(min_p.y, s[i].y);\n        min_p.z = min(min_p.z, s[i].z);\n    }\n    for (auto& p : s) {\n        p = p - min_p;\n    }\n    sort(s.begin(), s.end());\n    return s;\n}\n\nShape get_canonical_shape(const Shape& s) {\n    if (s.empty()) return {};\n    Shape canonical = normalize_shape(s);\n    for (const auto& R : ROTS) {\n        Shape rotated_s;\n        for (const auto& p : s) {\n            rotated_s.push_back(rotate(p, R));\n        }\n        Shape normalized_rotated = normalize_shape(rotated_s);\n        if (normalized_rotated < canonical) {\n            canonical = normalized_rotated;\n        }\n    }\n    return canonical;\n}\n\nstruct ProtoBlock {\n    Shape points;\n    int id = 0;\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\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    auto is_valid_coord = [&](int x, int y, int z) {\n        return x >= 0 && x < D && y >= 0 && y < D && z >= 0 && z < D;\n    };\n\n    vector<vector<vector<bool>>> C1(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    vector<vector<vector<bool>>> C2(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    vector<vector<vector<bool>>> C_common(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    \n    for (int x = 0; x < D; ++x) for (int y = 0; y < D; ++y) for (int z = 0; z < D; ++z) {\n        if (f1[z][x] == '1' && r1[z][y] == '1') C1[x][y][z] = true;\n        if (f2[z][x] == '1' && r2[z][y] == '1') C2[x][y][z] = true;\n        if (C1[x][y][z] && C2[x][y][z]) C_common[x][y][z] = true;\n    }\n\n    vector<ProtoBlock> common_blocks;\n    vector<vector<vector<bool>>> visited_common = C_common;\n    for (int x = 0; x < D; ++x) for (int y = 0; y < D; ++y) for (int z = 0; z < D; ++z) {\n        if (visited_common[x][y][z]) {\n            Shape current_block_points;\n            vector<Point3D> q;\n            q.push_back({x, y, z});\n            visited_common[x][y][z] = false;\n            size_t head = 0;\n            while(head < q.size()){\n                Point3D curr = q[head++];\n                current_block_points.push_back(curr);\n                int dx[] = {-1, 1, 0, 0, 0, 0};\n                int dy[] = {0, 0, -1, 1, 0, 0};\n                int dz[] = {0, 0, 0, 0, -1, 1};\n                for (int i = 0; i < 6; ++i) {\n                    Point3D next = {curr.x + dx[i], curr.y + dy[i], curr.z + dz[i]};\n                    if (is_valid_coord(next.x, next.y, next.z) && visited_common[next.x][next.y][next.z]) {\n                        visited_common[next.x][next.y][next.z] = false;\n                        q.push_back(next);\n                    }\n                }\n            }\n            common_blocks.push_back({current_block_points, 0});\n        }\n    }\n\n    vector<bool> f1_req_met(D*D, false), r1_req_met(D*D, false);\n    for (const auto& block : common_blocks) {\n        for (const auto& p : block.points) {\n            f1_req_met[p.z * D + p.x] = true;\n            r1_req_met[p.z * D + p.y] = true;\n        }\n    }\n\n    vector<ProtoBlock> filler1_blocks;\n    {\n        vector<Point3D> c1_only_cells;\n        for (int x=0; x<D; ++x) for (int y=0; y<D; ++y) for (int z=0; z<D; ++z) {\n             if (C1[x][y][z] && !C_common[x][y][z]) c1_only_cells.push_back({x,y,z});\n        }\n        vector<Point3D> filler1_cells;\n        while(true) {\n            int best_score = 0; int best_idx = -1;\n            for(size_t i=0; i<c1_only_cells.size(); ++i){\n                const auto& p = c1_only_cells[i];\n                int score = (f1[p.z][p.x]=='1' && !f1_req_met[p.z*D+p.x]) + (r1[p.z][p.y]=='1' && !r1_req_met[p.z*D+p.y]);\n                if(score > best_score) { best_score = score; best_idx = i; }\n            }\n            if (best_score == 0) break;\n            Point3D p = c1_only_cells[best_idx];\n            filler1_cells.push_back(p);\n            f1_req_met[p.z*D+p.x] = true; r1_req_met[p.z*D+p.y] = true;\n            swap(c1_only_cells[best_idx], c1_only_cells.back()); c1_only_cells.pop_back();\n        }\n        vector<vector<vector<bool>>> filler1_grid(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n        for(const auto& p : filler1_cells) filler1_grid[p.x][p.y][p.z] = true;\n        for(const auto& p_start : filler1_cells) {\n            if (filler1_grid[p_start.x][p_start.y][p_start.z]) {\n                Shape current_block_points; vector<Point3D> q; q.push_back(p_start);\n                filler1_grid[p_start.x][p_start.y][p_start.z] = false;\n                size_t head = 0;\n                while(head < q.size()){\n                    Point3D curr = q[head++]; current_block_points.push_back(curr);\n                    int dx[]={-1,1,0,0,0,0}, dy[]={0,0,-1,1,0,0}, dz[]={0,0,0,0,-1,1};\n                    for (int i=0; i<6; ++i) {\n                        Point3D next = {curr.x+dx[i], curr.y+dy[i], curr.z+dz[i]};\n                        if (is_valid_coord(next.x, next.y, next.z) && filler1_grid[next.x][next.y][next.z]) {\n                            filler1_grid[next.x][next.y][next.z] = false; q.push_back(next);\n                        }\n                    }\n                }\n                filler1_blocks.push_back({current_block_points, 0});\n            }\n        }\n    }\n    \n    vector<pair<int, ProtoBlock>> placed_common_blocks;\n    for(size_t i=0; i<common_blocks.size(); ++i) {\n        placed_common_blocks.push_back({(int)i, common_blocks[i]});\n    }\n    vector<ProtoBlock> filler2_blocks;\n    {\n        vector<vector<vector<bool>>> occupied2(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n        vector<bool> f2_req_met(D*D, false), r2_req_met(D*D, false);\n\n        sort(placed_common_blocks.begin(), placed_common_blocks.end(), [](const auto& a, const auto& b){\n            return a.second.points.size() > b.second.points.size();\n        });\n\n        for (auto& [idx, block] : placed_common_blocks) {\n            Shape s_rel = normalize_shape(block.points);\n            int best_block_score = -1; Shape best_block_placed_shape;\n            for (const auto& R : ROTS) {\n                Shape s_rot; for(const auto& p : s_rel) s_rot.push_back(rotate(p, R));\n                Point3D min_p = s_rot[0];\n                for(size_t i=1; i<s_rot.size(); ++i) { min_p.x=min(min_p.x,s_rot[i].x); min_p.y=min(min_p.y,s_rot[i].y); min_p.z=min(min_p.z,s_rot[i].z); }\n                for (int x=0; x<D; ++x) for(int y=0; y<D; ++y) for(int z=0; z<D; ++z) {\n                    Point3D trans = {x - min_p.x, y - min_p.y, z - min_p.z};\n                    bool possible = true; Shape placed_shape;\n                    set<pair<int,int>> f_covered, r_covered;\n                    for (const auto& p_rot : s_rot) {\n                        Point3D p_final = p_rot + trans;\n                        if (!is_valid_coord(p_final.x, p_final.y, p_final.z) || !C2[p_final.x][p_final.y][p_final.z] || occupied2[p_final.x][p_final.y][p_final.z]) {\n                            possible = false; break;\n                        }\n                        placed_shape.push_back(p_final);\n                        if (f2[p_final.z][p_final.x]=='1' && !f2_req_met[p_final.z*D+p_final.x]) f_covered.insert({p_final.z, p_final.x});\n                        if (r2[p_final.z][p_final.y]=='1' && !r2_req_met[p_final.z*D+p_final.y]) r_covered.insert({p_final.z, p_final.y});\n                    }\n                    if (possible) {\n                        int current_score = f_covered.size() + r_covered.size();\n                        if (current_score > best_block_score) {\n                            best_block_score = current_score; best_block_placed_shape = placed_shape;\n                        }\n                    }\n                }\n            }\n            if(best_block_score > -1){\n                block.points = best_block_placed_shape;\n                for (const auto& p : block.points) {\n                    occupied2[p.x][p.y][p.z] = true;\n                    f2_req_met[p.z*D+p.x] = true; r2_req_met[p.z*D+p.y] = true;\n                }\n            } else { block.points.clear(); }\n        }\n        \n        vector<Point3D> c2_rem_cells;\n        for (int x=0; x<D; ++x) for (int y=0; y<D; ++y) for (int z=0; z<D; ++z) {\n             if (C2[x][y][z] && !occupied2[x][y][z]) c2_rem_cells.push_back({x,y,z});\n        }\n        vector<Point3D> filler2_cells;\n        while(true) {\n            int best_score=0; int best_idx=-1;\n            for(size_t i=0; i<c2_rem_cells.size(); ++i){\n                const auto& p = c2_rem_cells[i];\n                int score = (f2[p.z][p.x]=='1' && !f2_req_met[p.z*D+p.x]) + (r2[p.z][p.y]=='1' && !r2_req_met[p.z*D+p.y]);\n                if(score > best_score) { best_score = score; best_idx = i; }\n            }\n            if(best_score == 0) break;\n            Point3D p = c2_rem_cells[best_idx];\n            filler2_cells.push_back(p);\n            f2_req_met[p.z*D+p.x] = true; r2_req_met[p.z*D+p.y] = true;\n            swap(c2_rem_cells[best_idx], c2_rem_cells.back()); c2_rem_cells.pop_back();\n        }\n        \n        vector<vector<vector<bool>>> filler2_grid(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n        for(const auto& p : filler2_cells) filler2_grid[p.x][p.y][p.z] = true;\n        for(const auto& p_start : filler2_cells) {\n            if (filler2_grid[p_start.x][p_start.y][p_start.z]) {\n                Shape current_block_points; vector<Point3D> q; q.push_back(p_start);\n                filler2_grid[p_start.x][p_start.y][p_start.z] = false;\n                size_t head = 0;\n                while(head < q.size()){\n                    Point3D curr = q[head++]; current_block_points.push_back(curr);\n                    int dx[]={-1,1,0,0,0,0}, dy[]={0,0,-1,1,0,0}, dz[]={0,0,0,0,-1,1};\n                    for (int i=0; i<6; ++i) {\n                        Point3D next = {curr.x+dx[i], curr.y+dy[i], curr.z+dz[i]};\n                        if (is_valid_coord(next.x, next.y, next.z) && filler2_grid[next.x][next.y][next.z]) {\n                            filler2_grid[next.x][next.y][next.z] = false; q.push_back(next);\n                        }\n                    }\n                }\n                filler2_blocks.push_back({current_block_points, 0});\n            }\n        }\n    }\n    \n    int next_id = 1;\n    for (auto& block : common_blocks) {\n        if (!block.points.empty()) {\n            block.id = next_id++;\n        }\n    }\n\n    map<Shape, vector<ProtoBlock*>> f1_by_canon, f2_by_canon;\n    set<Shape> all_filler_canons;\n\n    for (auto& block : filler1_blocks) {\n        if (block.points.empty()) continue;\n        Shape canon = get_canonical_shape(normalize_shape(block.points));\n        f1_by_canon[canon].push_back(&block);\n        all_filler_canons.insert(canon);\n    }\n    for (auto& block : filler2_blocks) {\n        if (block.points.empty()) continue;\n        Shape canon = get_canonical_shape(normalize_shape(block.points));\n        f2_by_canon[canon].push_back(&block);\n        all_filler_canons.insert(canon);\n    }\n\n    for (const auto& canon : all_filler_canons) {\n        auto it1 = f1_by_canon.find(canon);\n        auto it2 = f2_by_canon.find(canon);\n        vector<ProtoBlock*> v1 = (it1 == f1_by_canon.end()) ? vector<ProtoBlock*>() : it1->second;\n        vector<ProtoBlock*> v2 = (it2 == f2_by_canon.end()) ? vector<ProtoBlock*>() : it2->second;\n        \n        size_t matches = min(v1.size(), v2.size());\n        for (size_t i = 0; i < matches; ++i) {\n            int id = next_id++;\n            v1[i]->id = id;\n            v2[i]->id = id;\n        }\n        for (size_t i = matches; i < v1.size(); ++i) {\n            v1[i]->id = next_id++;\n        }\n        for (size_t i = matches; i < v2.size(); ++i) {\n            v2[i]->id = next_id++;\n        }\n    }\n\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    for (const auto& block : common_blocks) for (const auto& p : block.points) b1[p.x][p.y][p.z] = block.id;\n    for (const auto& block : filler1_blocks) for (const auto& p : block.points) b1[p.x][p.y][p.z] = block.id;\n\n    for (const auto& [idx, block] : placed_common_blocks) {\n        if (!block.points.empty()) {\n            int id = common_blocks[idx].id;\n            for (const auto& p : block.points) b2[p.x][p.y][p.z] = id;\n        }\n    }\n    for (const auto& block : filler2_blocks) for (const auto& p : block.points) b2[p.x][p.y][p.z] = block.id;\n    \n    cout << next_id - 1 << endl;\n    for (int x=0; x<D; ++x) for (int y=0; y<D; ++y) for (int z=0; z<D; ++z) cout << b1[x][y][z] << (x==D-1 && y==D-1 && z==D-1 ? \"\" : \" \"); cout << endl;\n    for (int x=0; x<D; ++x) for (int y=0; y<D; ++y) for (int z=0; z<D; ++z) cout << b2[x][y][z] << (x==D-1 && y==D-1 && z==D-1 ? \"\" : \" \"); cout << endl;\n\n    return 0;\n}","ahc020":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <queue>\n\nusing namespace std;\n\nconst long long INF = 1e18;\n\nstruct Point {\n    long long x, y;\n};\n\nstruct Edge {\n    int u, v;\n    long long w;\n    int id;\n};\n\nstruct GraphEdge {\n    int to;\n    long long weight;\n    int id;\n};\n\nlong long distSq(const Point& p1, const Point& p2) {\n    return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y);\n}\n\n// Global timer\nchrono::steady_clock::time_point start_time;\n\nbool is_time_up(double time_limit) {\n    auto now = chrono::steady_clock::now();\n    double elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n    return elapsed > time_limit;\n}\n\n// --- Precomputed data ---\nint N, M, K;\nvector<Point> stations;\nvector<Point> residents;\nvector<Edge> edges;\nvector<vector<GraphEdge>> adj;\nvector<vector<long long>> dist_G;\nvector<vector<int>> parent_G;\nvector<vector<pair<long long, int>>> dists_to_resident;\n\n// --- Randomness ---\nmt19937 rng;\n\nlong long calculate_connection_cost(const vector<int>& V_list) {\n    if (V_list.empty()) return 0;\n    if (V_list.size() == 1) return 0;\n\n    long long cost = 0;\n    vector<long long> min_cost(N + 1, INF);\n    vector<bool> in_mst(N + 1, false);\n\n    min_cost[V_list[0]] = 0;\n    \n    for (size_t i = 0; i < V_list.size(); ++i) {\n        int u = -1;\n        for (int station_id : V_list) {\n            if (!in_mst[station_id] && (u == -1 || min_cost[station_id] < min_cost[u])) {\n                u = station_id;\n            }\n        }\n\n        if (u == -1) break;\n        if (min_cost[u] == INF) return INF; // Should not happen in a connected graph\n        in_mst[u] = true;\n        cost += min_cost[u];\n\n        for (int v : V_list) {\n            if (!in_mst[v]) {\n                min_cost[v] = min(min_cost[v], dist_G[u - 1][v - 1]);\n            }\n        }\n    }\n    return cost;\n}\n\nbool check_coverage(const vector<bool>& active) {\n    for (int k = 0; k < K; ++k) {\n        bool covered = false;\n        for (const auto& p : dists_to_resident[k]) {\n            if (active[p.second]) {\n                covered = true;\n                break;\n            }\n        }\n        if (!covered) return false;\n    }\n    return true;\n}\n\nlong long calculate_total_cost(const vector<bool>& active) {\n    vector<int> V_list;\n    for (int i = 1; i <= N; ++i) {\n        if (active[i]) V_list.push_back(i);\n    }\n    if (V_list.empty() || !active[1]) {\n        return INF;\n    }\n\n    long long connection_cost = calculate_connection_cost(V_list);\n\n    long long power_cost = 0;\n    vector<long long> required_power_sq(N + 1, 0);\n\n    for (int k = 0; k < K; ++k) {\n        for (const auto& p : dists_to_resident[k]) {\n            int station_id = p.second;\n            if (active[station_id]) {\n                required_power_sq[station_id] = max(required_power_sq[station_id], p.first);\n                break;\n            }\n        }\n    }\n\n    for (int i = 1; i <= N; ++i) {\n        power_cost += required_power_sq[i];\n    }\n    \n    return connection_cost + power_cost;\n}\n\nvoid solve() {\n    start_time = chrono::steady_clock::now();\n    \n    cin >> N >> M >> K;\n    stations.resize(N);\n    for (int i = 0; i < N; ++i) cin >> stations[i].x >> stations[i].y;\n    edges.resize(M);\n    adj.resize(N + 1);\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\n        edges[i].id = i + 1;\n        adj[edges[i].u].push_back({edges[i].v, edges[i].w, edges[i].id});\n        adj[edges[i].v].push_back({edges[i].u, edges[i].w, edges[i].id});\n    }\n    residents.resize(K);\n    for (int i = 0; i < K; ++i) cin >> residents[i].x >> residents[i].y;\n\n    // Precomputation\n    dist_G.assign(N, vector<long long>(N, INF));\n    parent_G.assign(N, vector<int>(N, -1));\n\n    for (int i = 0; i < N; ++i) {\n        dist_G[i][i] = 0;\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n        pq.push({0, i + 1});\n\n        vector<long long> d(N + 1, INF);\n        vector<int> p(N + 1, -1);\n        d[i + 1] = 0;\n\n        while (!pq.empty()) {\n            auto [cost, u] = pq.top();\n            pq.pop();\n\n            if (cost > d[u]) continue;\n\n            for (const auto& edge : adj[u]) {\n                int v = edge.to;\n                if (d[u] + edge.weight < d[v]) {\n                    d[v] = d[u] + edge.weight;\n                    p[v] = u;\n                    pq.push({d[v], v});\n                }\n            }\n        }\n        for (int j = 0; j < N; ++j) {\n            dist_G[i][j] = d[j + 1];\n            parent_G[i][j] = p[j + 1];\n        }\n    }\n    \n    dists_to_resident.resize(K);\n    for (int k = 0; k < K; ++k) {\n        for (int i = 0; i < N; ++i) {\n            dists_to_resident[k].push_back({distSq(residents[k], stations[i]), i + 1});\n        }\n        sort(dists_to_resident[k].begin(), dists_to_resident[k].end());\n    }\n\n    // Initial Solution\n    vector<bool> current_V(N + 1, false);\n    current_V[1] = true;\n\n    while (true) {\n        int first_uncovered = -1;\n        for (int k = 0; k < K; ++k) {\n            bool is_k_covered = false;\n            for (const auto& p : dists_to_resident[k]) {\n                if (current_V[p.second]) {\n                    is_k_covered = true;\n                    break;\n                }\n            }\n            if (!is_k_covered) {\n                first_uncovered = k;\n                break;\n            }\n        }\n\n        if (first_uncovered == -1) break;\n\n        current_V[dists_to_resident[first_uncovered][0].second] = true;\n    }\n\n    vector<bool> best_V = current_V;\n    long long current_cost = calculate_total_cost(current_V);\n    long long best_cost = current_cost;\n\n    // Simulated Annealing\n    double time_limit = 1950;\n    double T_start = best_cost / 10.0;\n    double T_end = 1.0;\n    \n    uniform_int_distribution<> dist_N(1, N);\n    uniform_real_distribution<> dist_real(0.0, 1.0);\n\n    while (!is_time_up(time_limit)) {\n        double elapsed = chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count();\n        double progress = elapsed / time_limit;\n        if (progress > 1.0) progress = 1.0;\n        double T = T_start * pow(T_end / T_start, progress);\n\n        vector<bool> next_V = current_V;\n        \n        double p = dist_real(rng);\n        if (p < 0.45) { // ADD\n            int u = dist_N(rng);\n            int attempts = 0;\n            while (next_V[u] && attempts < 2*N) {\n                u = dist_N(rng);\n                attempts++;\n            }\n            if (!next_V[u]) next_V[u] = true; else continue;\n        } else if (p < 0.9) { // REMOVE\n            int v = dist_N(rng);\n            int attempts = 0;\n            while ((v == 1 || !next_V[v]) && attempts < 2*N) {\n                v = dist_N(rng);\n                attempts++;\n            }\n            if (v != 1 && next_V[v]) next_V[v] = false; else continue;\n            \n            if (!check_coverage(next_V)) continue;\n        } else { // SWAP\n            int u = dist_N(rng);\n            int attempts_u = 0;\n            while(next_V[u] && attempts_u < 2*N) {\n                 u = dist_N(rng);\n                 attempts_u++;\n            }\n            if(next_V[u]) continue;\n\n            int v = dist_N(rng);\n            int attempts_v = 0;\n            while((v==1 || !next_V[v]) && attempts_v < 2*N) {\n                v = dist_N(rng);\n                attempts_v++;\n            }\n            if(v==1 || !next_V[v]) continue;\n            \n            next_V[u] = true;\n            next_V[v] = false;\n            if (!check_coverage(next_V)) continue;\n        }\n        \n        long long next_cost = calculate_total_cost(next_V);\n        if(next_cost == INF) continue;\n\n        long long delta = next_cost - current_cost;\n        if (delta < 0 || dist_real(rng) < exp(-(double)delta / T)) {\n            current_V = next_V;\n            current_cost = next_cost;\n            if (current_cost < best_cost) {\n                best_cost = current_cost;\n                best_V = current_V;\n            }\n        }\n    }\n\n    // Output\n    vector<long long> P(N + 1, 0);\n    vector<long long> required_power_sq(N + 1, 0);\n    for (int k = 0; k < K; ++k) {\n        for (const auto& p : dists_to_resident[k]) {\n            int station_id = p.second;\n            if (best_V[station_id]) {\n                required_power_sq[station_id] = max(required_power_sq[station_id], p.first);\n                break;\n            }\n        }\n    }\n    for (int i = 1; i <= N; ++i) {\n        if (best_V[i]) {\n            P[i] = min(5000LL, (long long)round(sqrt((long double)required_power_sq[i])));\n        }\n    }\n\n    vector<bool> B(M + 1, false);\n    vector<int> V_list;\n    for (int i = 1; i <= N; ++i) if (best_V[i]) V_list.push_back(i);\n\n    if (V_list.size() > 1) {\n        vector<long long> min_cost(N + 1, INF);\n        vector<int> edge_from(N + 1, -1);\n        vector<bool> in_mst(N + 1, false);\n        min_cost[V_list[0]] = 0;\n\n        for (size_t i = 0; i < V_list.size(); ++i) {\n            int u = -1;\n            for (int station_id : V_list) {\n                if (!in_mst[station_id] && (u == -1 || min_cost[station_id] < min_cost[u])) {\n                    u = station_id;\n                }\n            }\n\n            if (u == -1) break;\n            in_mst[u] = true;\n            if (edge_from[u] != -1) {\n                int v = edge_from[u];\n                int target = v - 1;\n                int curr = u - 1;\n                while (curr != target) {\n                    int prev = parent_G[target][curr] - 1;\n                    if(prev < 0) break;\n                    \n                    bool edge_found = false;\n                    for (const auto& edge : adj[curr + 1]) {\n                        if (edge.to == prev + 1) {\n                            B[edge.id] = true;\n                            edge_found = true;\n                            break;\n                        }\n                    }\n                    if(!edge_found) { // for undirected graph\n                        for (const auto& edge : adj[prev + 1]) {\n                            if (edge.to == curr + 1) {\n                                B[edge.id] = true;\n                                break;\n                            }\n                        }\n                    }\n                    curr = prev;\n                }\n            }\n\n            for (int v : V_list) {\n                if (!in_mst[v] && dist_G[u - 1][v - 1] < min_cost[v]) {\n                    min_cost[v] = dist_G[u - 1][v - 1];\n                    edge_from[v] = u;\n                }\n            }\n        }\n    }\n\n\n    for (int i = 1; i <= N; ++i) cout << P[i] << (i == N ? \"\" : \" \");\n    cout << endl;\n    for (int i = 1; i <= M; ++i) cout << B[i] << (i == M ? \"\" : \" \");\n    cout << endl;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    unsigned int seed = 0;\n    try {\n        seed = chrono::high_resolution_clock::now().time_since_epoch().count();\n    } catch(const exception& e) {\n        // fallback\n    }\n    rng.seed(seed);\n    solve();\n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <tuple>\n\nconst int N = 30;\n\nstd::vector<std::vector<int>> b;\nstd::vector<std::tuple<int, int, int, int>> ops;\n\n// A helper function to perform a swap and record it.\n// It stops recording if the operation limit is reached.\nvoid do_swap(int r1, int c1, int r2, int c2) {\n    if (ops.size() >= 10000) return;\n    std::swap(b[r1][c1], b[r2][c2]);\n    ops.emplace_back(r1, c1, r2, c2);\n}\n\n// Function to check if the pyramid satisfies the condition (E=0).\nint count_errors() {\n    int errors = 0;\n    for (int r = 0; r < N - 1; ++r) {\n        for (int c = 0; c <= r; ++c) {\n            if (b[r][c] > b[r + 1][c]) {\n                errors++;\n            }\n            if (b[r][c] > b[r + 1][c + 1]) {\n                errors++;\n            }\n        }\n    }\n    return errors;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    b.resize(N);\n    for (int i = 0; i < N; ++i) {\n        b[i].resize(i + 1);\n        for (int j = 0; j <= i; ++j) {\n            std::cin >> b[i][j];\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        if (ops.size() >= 10000) break;\n        \n        // Top-down pass: push large numbers down.\n        if (i % 2 == 0) { // Alternate column iteration direction\n            for (int r = 0; r < N - 1; ++r) {\n                for (int c = 0; c <= r; ++c) {\n                    if (ops.size() >= 10000) break;\n                    int val_p = b[r][c];\n                    int val_c1 = b[r + 1][c];\n                    int val_c2 = b[r + 1][c + 1];\n\n                    if (val_p > val_c1 && val_p > val_c2) {\n                        if (val_c1 < val_c2) do_swap(r, c, r + 1, c);\n                        else do_swap(r, c, r + 1, c + 1);\n                    } else if (val_p > val_c1) {\n                        do_swap(r, c, r + 1, c);\n                    } else if (val_p > val_c2) {\n                        do_swap(r, c, r + 1, c + 1);\n                    }\n                }\n                if (ops.size() >= 10000) break;\n            }\n        } else {\n             for (int r = 0; r < N - 1; ++r) {\n                for (int c = r; c >= 0; --c) {\n                    if (ops.size() >= 10000) break;\n                    int val_p = b[r][c];\n                    int val_c1 = b[r + 1][c];\n                    int val_c2 = b[r + 1][c + 1];\n\n                    if (val_p > val_c1 && val_p > val_c2) {\n                        if (val_c1 < val_c2) do_swap(r, c, r + 1, c);\n                        else do_swap(r, c, r + 1, c + 1);\n                    } else if (val_p > val_c1) {\n                        do_swap(r, c, r + 1, c);\n                    } else if (val_p > val_c2) {\n                        do_swap(r, c, r + 1, c + 1);\n                    }\n                }\n                if (ops.size() >= 10000) break;\n            }\n        }\n\n        if (ops.size() >= 10000) break;\n\n        // Bottom-up pass: pull small numbers up.\n        if (i % 2 == 0) { // Alternate column iteration direction\n            for (int r = N - 1; r >= 1; --r) {\n                for (int c = 0; c <= r; ++c) {\n                    if (ops.size() >= 10000) break;\n                    int val_c = b[r][c];\n                    bool has_p1 = (c > 0);\n                    bool has_p2 = (c < r);\n\n                    if (has_p1 && !has_p2) { // Right edge child\n                        if (val_c < b[r - 1][c - 1]) {\n                            do_swap(r, c, r - 1, c - 1);\n                        }\n                    } else if (!has_p1 && has_p2) { // Left edge child\n                        if (val_c < b[r - 1][c]) {\n                            do_swap(r, c, r - 1, c);\n                        }\n                    } else if (has_p1 && has_p2) { // Middle child\n                        int val_p1 = b[r - 1][c - 1];\n                        int val_p2 = b[r - 1][c];\n                        if (val_c < val_p1 || val_c < val_p2) {\n                            if (val_p1 > val_p2) {\n                                if (val_c < val_p1) do_swap(r, c, r - 1, c - 1);\n                            } else {\n                                if (val_c < val_p2) do_swap(r, c, r - 1, c);\n                            }\n                        }\n                    }\n                }\n                if (ops.size() >= 10000) break;\n            }\n        } else {\n            for (int r = N - 1; r >= 1; --r) {\n                for (int c = r; c >= 0; --c) {\n                    if (ops.size() >= 10000) break;\n                    int val_c = b[r][c];\n                    bool has_p1 = (c > 0);\n                    bool has_p2 = (c < r);\n\n                    if (has_p1 && !has_p2) { // Right edge child\n                        if (val_c < b[r - 1][c - 1]) {\n                            do_swap(r, c, r - 1, c - 1);\n                        }\n                    } else if (!has_p1 && has_p2) { // Left edge child\n                        if (val_c < b[r - 1][c]) {\n                            do_swap(r, c, r - 1, c);\n                        }\n                    } else if (has_p1 && has_p2) { // Middle child\n                        int val_p1 = b[r - 1][c - 1];\n                        int val_p2 = b[r - 1][c];\n                        if (val_c < val_p1 || val_c < val_p2) {\n                            if (val_p1 > val_p2) {\n                                if (val_c < val_p1) do_swap(r, c, r - 1, c - 1);\n                            } else {\n                                if (val_c < val_p2) do_swap(r, c, r - 1, c);\n                            }\n                        }\n                    }\n                }\n                if (ops.size() >= 10000) break;\n            }\n        }\n        \n        // Check for early termination if sorted.\n        if (count_errors() == 0) {\n            break;\n        }\n    }\n\n    std::cout << ops.size() << \"\\n\";\n    for (const auto& op : ops) {\n        std::cout << std::get<0>(op) << \" \" << std::get<1>(op) << \" \" << std::get<2>(op) << \" \" << std::get<3>(op) << \"\\n\";\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n#include <map>\n#include <tuple>\n#include <set>\n\nusing namespace std;\n\n// Constants\nconst int D_CONST = 9;\nconst int ENTRANCE_R = 0;\nconst int ENTRANCE_C = (D_CONST - 1) / 2;\nconst int DR[] = {-1, 1, 0, 0};\nconst int DC[] = {0, 0, -1, 1};\n\n// Global state\nint D_input, N;\nint C; // Number of containers\nvector<vector<int>> grid;\n\n// Precomputed data\nstruct SquareInfo {\n    int r, c;\n    int dist;\n    int block_count;\n\n    bool operator<(const SquareInfo& other) const {\n        if (block_count != other.block_count) return block_count > other.block_count;\n        if (dist != other.dist) return dist > other.dist;\n        if (r != other.r) return r > other.r;\n        if (abs(c - ENTRANCE_C) != abs(other.c - ENTRANCE_C)) return abs(c - ENTRANCE_C) > abs(other.c - ENTRANCE_C);\n        return c > other.c;\n    }\n};\nvector<SquareInfo> P;\nvector<bool> p_occupied;\nmap<int, pair<int, int>> container_locs;\n\n// Utility functions\nbool is_valid(int r, int c) {\n    return r >= 0 && r < D_CONST && c >= 0 && c < D_CONST;\n}\n\n// BFS on a grid where -1 is a wall.\nvector<vector<int>> bfs_on_static_grid(const vector<vector<int>>& static_grid) {\n    vector<vector<int>> dist(D_CONST, vector<int>(D_CONST, -1));\n    queue<pair<int, int>> q;\n\n    if (static_grid[ENTRANCE_R][ENTRANCE_C] == -1) return dist;\n\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();\n        q.pop();\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + DR[i];\n            int nc = c + DC[i];\n            if (is_valid(nr, nc) && dist[nr][nc] == -1 && static_grid[nr][nc] != -1) {\n                dist[nr][nc] = dist[r][c] + 1;\n                q.push({nr, nc});\n            }\n        }\n    }\n    return dist;\n}\n\n// Phase 1: Pre-computation\nvoid precompute() {\n    C = D_CONST * D_CONST - 1 - N;\n\n    grid.assign(D_CONST, vector<int>(D_CONST, -3)); // -3: empty\n    grid[ENTRANCE_R][ENTRANCE_C] = -2; // -2: entrance\n    \n    for (int i = 0; i < N; ++i) {\n        int r, c;\n        cin >> r >> c;\n        grid[r][c] = -1; // -1: obstacle\n    }\n\n    vector<pair<int, int>> placeable_squares;\n    for (int i = 0; i < D_CONST; ++i) {\n        for (int j = 0; j < D_CONST; ++j) {\n            if (grid[i][j] == -3) {\n                placeable_squares.push_back({i, j});\n            }\n        }\n    }\n\n    auto initial_dist_grid = bfs_on_static_grid(grid);\n\n    for (const auto& s : placeable_squares) {\n        SquareInfo info;\n        info.r = s.first;\n        info.c = s.second;\n        info.dist = initial_dist_grid[s.first][s.second];\n\n        vector<vector<int>> temp_grid = grid;\n        temp_grid[s.first][s.second] = -1;\n        \n        auto dist_after_block = bfs_on_static_grid(temp_grid);\n        \n        int reachable_count = 0;\n        for (const auto& other_s : placeable_squares) {\n            if (s != other_s) {\n                if (dist_after_block[other_s.first][other_s.second] != -1) {\n                    reachable_count++;\n                }\n            }\n        }\n        info.block_count = (placeable_squares.size() - 1) - reachable_count;\n        P.push_back(info);\n    }\n    \n    sort(P.begin(), P.end());\n}\n\n// Phase 2: Placement\nvoid solve_placement() {\n    p_occupied.assign(C, false);\n    \n    for (int d = 0; d < C; ++d) {\n        int t_d;\n        cin >> t_d;\n\n        vector<vector<bool>> visited(D_CONST, vector<bool>(D_CONST, false));\n        queue<pair<int, int>> q;\n\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();\n            q.pop();\n\n            for(int i = 0; i < 4; ++i){\n                int nr = r + DR[i];\n                int nc = c + DC[i];\n                if(is_valid(nr, nc) && !visited[nr][nc]) {\n                    if(grid[nr][nc] == -3 || grid[nr][nc] == -2) {\n                        visited[nr][nc] = true;\n                        q.push({nr, nc});\n                    }\n                }\n            }\n        }\n\n        int target_rank = (C - 1) - t_d;\n        int best_k = -1;\n\n        for (int delta = 0; delta < C; ++delta) {\n            int k1 = target_rank - delta;\n            if (k1 >= 0 && k1 < C && !p_occupied[k1]) {\n                if (visited[P[k1].r][P[k1].c]) {\n                    best_k = k1;\n                    break;\n                }\n            }\n            if (delta > 0) {\n                int k2 = target_rank + delta;\n                if (k2 >= 0 && k2 < C && !p_occupied[k2]) {\n                    if (visited[P[k2].r][P[k2].c]) {\n                        best_k = k2;\n                        break;\n                    }\n                }\n            }\n        }\n        \n        p_occupied[best_k] = true;\n        int r_out = P[best_k].r;\n        int c_out = P[best_k].c;\n        grid[r_out][c_out] = t_d;\n        container_locs[t_d] = {r_out, c_out};\n\n        cout << r_out << \" \" << c_out << endl;\n    }\n}\n\n// Phase 3: Retrieval\nvoid solve_retrieval() {\n    for (int k = 0; k < C; ++k) {\n        set<int> accessible_containers;\n        queue<pair<int, int>> q;\n        vector<vector<bool>> visited_empty(D_CONST, vector<bool>(D_CONST, false));\n\n        q.push({ENTRANCE_R, ENTRANCE_C});\n        visited_empty[ENTRANCE_R][ENTRANCE_C] = true;\n\n        while(!q.empty()){\n            auto [r, c] = q.front();\n            q.pop();\n\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + DR[i];\n                int nc = c + DC[i];\n                if (!is_valid(nr, nc)) continue;\n                \n                if (grid[nr][nc] >= 0) {\n                    accessible_containers.insert(grid[nr][nc]);\n                } else if (grid[nr][nc] == -3 && !visited_empty[nr][nc]) {\n                    visited_empty[nr][nc] = true;\n                    q.push({nr, nc});\n                }\n            }\n        }\n\n        int min_t = *accessible_containers.begin();\n\n        auto [qr, qc] = container_locs[min_t];\n        cout << qr << \" \" << qc << endl;\n        grid[qr][qc] = -3;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> D_input >> N;\n    \n    precompute();\n    solve_placement();\n    solve_retrieval();\n\n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <set>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <queue>\n#include <tuple>\n\n// Constants\nconstexpr int N = 50;\nconstexpr int M = 100;\n\n// Randomness\nstruct Xoroshiro128 {\n    uint64_t s[2];\n\n    Xoroshiro128() {\n        std::random_device rd;\n        s[0] = ((uint64_t)rd() << 32) | rd();\n        s[1] = ((uint64_t)rd() << 32) | rd();\n    }\n\n    static inline uint64_t rotl(const uint64_t x, int k) {\n        return (x << k) | (x >> (64 - k));\n    }\n\n    uint64_t next() {\n        const uint64_t s0 = s[0];\n        uint64_t s1 = s[1];\n        const uint64_t result = s0 + s1;\n\n        s1 ^= s0;\n        s[0] = rotl(s0, 24) ^ s1 ^ (s1 << 16);\n        s[1] = rotl(s1, 37);\n\n        return result;\n    }\n\n    double next_double() {\n        return (double)(next() >> 11) * (1.0 / (1LL << 53));\n    }\n};\n\nXoroshiro128 rng;\n\n// Timer\nclass Timer {\npublic:\n    Timer() : start_time(std::chrono::high_resolution_clock::now()) {}\n\n    double get_elapsed_sec() {\n        auto now = std::chrono::high_resolution_clock::now();\n        return std::chrono::duration_cast<std::chrono::duration<double>>(now - start_time).count();\n    }\nprivate:\n    std::chrono::time_point<std::chrono::high_resolution_clock> start_time;\n};\n\n// Data structures\nstruct Point {\n    int r, c;\n};\n\nstruct Vec2d {\n    double x, y;\n};\n\n// Globals for problem data\nstd::vector<std::vector<bool>> adj;\nstd::vector<std::vector<int>> initial_grid;\n\nvoid read_input() {\n    int n_dummy, m_dummy;\n    std::cin >> n_dummy >> m_dummy;\n    initial_grid.assign(N, std::vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            std::cin >> initial_grid[i][j];\n        }\n    }\n}\n\nvoid build_adj() {\n    adj.assign(M + 1, std::vector<bool>(M + 1, false));\n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            if (r == 0 || r == N - 1 || c == 0 || c == N - 1) {\n                adj[initial_grid[r][c]][0] = adj[0][initial_grid[r][c]] = true;\n            }\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + dr[i];\n                int nc = c + dc[i];\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                    int c1 = initial_grid[r][c];\n                    int c2 = initial_grid[nr][nc];\n                    if (c1 != c2) {\n                        adj[c1][c2] = adj[c2][c1] = true;\n                    }\n                }\n            }\n        }\n    }\n}\n\nstruct Solution {\n    std::vector<std::vector<int>> grid;\n    int score;\n\n    Solution() : grid(N, std::vector<int>(N, 0)), score(0) {}\n\n    void calculate_score() {\n        int empty_count = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (grid[i][j] == 0) {\n                    empty_count++;\n                }\n            }\n        }\n        score = empty_count + 1;\n    }\n\n    void print() {\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                std::cout << grid[i][j] << (j == N - 1 ? \"\" : \" \");\n            }\n            std::cout << std::endl;\n        }\n    }\n};\n\nclass Solver {\npublic:\n    Solver(const Timer& timer) : timer(timer) {}\n\n    Solution solve() {\n        Solution best_solution;\n        best_solution.score = -1;\n\n        while(timer.get_elapsed_sec() < 1.95) {\n            Solution current_solution = generate_solution();\n            if (current_solution.score > best_solution.score) {\n                best_solution = current_solution;\n            }\n        }\n        return best_solution;\n    }\n\nprivate:\n    const Timer& timer;\n    std::vector<std::vector<int>> grid;\n    std::vector<Point> seed_pos;\n\n    Solution generate_solution() {\n        std::vector<Vec2d> positions = force_directed_layout();\n        grid.assign(N, std::vector<int>(N, 0));\n        seed_pos.assign(M + 1, {-1, -1});\n        place_seeds(positions);\n        connect_regions();\n        \n        Solution sol;\n        sol.grid = grid;\n        sol.calculate_score();\n        return sol;\n    }\n\n    std::vector<Vec2d> force_directed_layout() {\n        std::vector<Vec2d> pos(M + 1);\n        for (int i = 1; i <= M; ++i) {\n            pos[i] = {rng.next_double() * N, rng.next_double() * N};\n        }\n\n        double temp = N / 4.0;\n        const int iterations = 150;\n        const double k_attr = 0.1, k_rep = 150.0;\n        const double border_rep = 200.0;\n\n        for (int iter = 0; iter < iterations; ++iter) {\n            if (timer.get_elapsed_sec() > 1.95) break;\n\n            std::vector<Vec2d> forces(M + 1, {0.0, 0.0});\n            for (int i = 1; i <= M; ++i) {\n                for (int j = i + 1; j <= M; ++j) {\n                    Vec2d diff = {pos[j].x - pos[i].x, pos[j].y - pos[i].y};\n                    double dist_sq = diff.x * diff.x + diff.y * diff.y + 1e-6;\n                    double dist = std::sqrt(dist_sq);\n                    \n                    if (adj[i][j]) {\n                        double f = k_attr * (dist - N/10.0);\n                        forces[i].x += f * diff.x / dist;\n                        forces[i].y += f * diff.y / dist;\n                        forces[j].x -= f * diff.x / dist;\n                        forces[j].y -= f * diff.y / dist;\n                    } else {\n                        double f = k_rep / dist_sq;\n                        forces[i].x -= f * diff.x / dist;\n                        forces[i].y -= f * diff.y / dist;\n                        forces[j].x += f * diff.x / dist;\n                        forces[j].y += f * diff.y / dist;\n                    }\n                }\n            }\n\n            for (int i = 1; i <= M; ++i) {\n                 if (!adj[i][0]) {\n                    forces[i].x += border_rep / (pos[i].x * pos[i].x + 1e-6);\n                    forces[i].y += border_rep / (pos[i].y * pos[i].y + 1e-6);\n                    forces[i].x -= border_rep / ((N-1 - pos[i].x) * (N-1 - pos[i].x) + 1e-6);\n                    forces[i].y -= border_rep / ((N-1 - pos[i].y) * (N-1 - pos[i].y) + 1e-6);\n                }\n            }\n\n            for (int i = 1; i <= M; ++i) {\n                double force_mag = std::sqrt(forces[i].x * forces[i].x + forces[i].y * forces[i].y) + 1e-6;\n                pos[i].x += temp * forces[i].x / force_mag;\n                pos[i].y += temp * forces[i].y / force_mag;\n                pos[i].x = std::max(1.0, std::min((double)N - 2, pos[i].x));\n                pos[i].y = std::max(1.0, std::min((double)N - 2, pos[i].y));\n            }\n            temp *= 0.98;\n        }\n        return pos;\n    }\n\n    void place_seeds(const std::vector<Vec2d>& pos) {\n        std::vector<int> p(M);\n        std::iota(p.begin(), p.end(), 1);\n        auto mt = std::mt19937(rng.next());\n        std::shuffle(p.begin(), p.end(), mt);\n\n        for (int color : p) {\n            int target_r = std::round(pos[color].y);\n            int target_c = std::round(pos[color].x);\n\n            int best_r = -1, best_c = -1;\n            for (int d = 0; d < N; ++d) {\n                for(int i = -d; i <= d; ++i) {\n                    int j = d - std::abs(i);\n                    int r_offsets[] = {i, i};\n                    int c_offsets[] = {j, -j};\n                    for (int k = 0; k < 2; ++k) {\n                        int r = target_r + r_offsets[k];\n                        int c = target_c + c_offsets[k];\n                        if (r < 0 || r >= N || c < 0 || c >= N) continue;\n                        if (is_valid_placement(color, r, c)) {\n                            best_r = r; best_c = c; goto found_pos;\n                        }\n                    }\n                }\n            }\n            found_pos:;\n            if (best_r != -1) {\n                grid[best_r][best_c] = color;\n                seed_pos[color] = {best_r, best_c};\n            }\n        }\n    }\n\n    bool is_valid_placement(int color, int r, int c) {\n        if (grid[r][c] != 0) return false;\n        if (!adj[color][0] && (r == 0 || r == N - 1 || c == 0 || c == N - 1)) return false;\n        \n        int dr[] = {-1, 1, 0, 0};\n        int dc[] = {0, 0, -1, 1};\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i], nc = c + dc[i];\n            if (nr >= 0 && nr < N && nc >= 0 && nc < N && grid[nr][nc] != 0) {\n                if (!adj[color][grid[nr][nc]]) return false;\n            }\n        }\n        return true;\n    }\n\n    void connect_regions() {\n        std::vector<std::pair<int, int>> reqs;\n        for (int i = 1; i <= M; ++i) for (int j = i + 1; j <= M; ++j) if (adj[i][j]) reqs.push_back({i, j});\n        auto mt = std::mt19937(rng.next());\n        std::shuffle(reqs.begin(), reqs.end(), mt);\n        \n        std::vector<std::vector<bool>> satisfied_adj(M + 1, std::vector<bool>(M + 1, false));\n\n        for (const auto& p : reqs) {\n            if (timer.get_elapsed_sec() > 1.95) break;\n            \n            bool is_adj = false;\n            int c1 = p.first, c2 = p.second;\n            if(seed_pos[c1].r == -1 || seed_pos[c2].r == -1) continue;\n            for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) {\n                if(grid[r][c]==c1) {\n                    int dr[]={-1,1,0,0}, dc[]={0,0,-1,1};\n                    for(int i=0;i<4;++i) {\n                        int nr=r+dr[i], nc=c+dc[i];\n                        if(nr>=0 && nr<N && nc>=0 && nc<N && grid[nr][nc]==c2) { is_adj=true; goto end_check; }\n                    }\n                }\n            }\n            end_check:;\n\n            if (!is_adj) connect_pair(p.first, p.second);\n        }\n        \n        for (int i = 1; i <= M; ++i) {\n            if (timer.get_elapsed_sec() > 1.95) break;\n            if (adj[i][0]) {\n                 bool is_adj_to_0 = false;\n                 for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) {\n                    if (grid[r][c] == i && (r==0 || r==N-1 || c==0 || c==N-1)) {\n                        is_adj_to_0 = true; break;\n                    }\n                 }\n                 if(!is_adj_to_0) connect_to_border(i);\n            }\n        }\n    }\n\n    void connect_pair(int c1, int c2) {\n        using State = std::tuple<int, int, int>;\n        std::priority_queue<State, std::vector<State>, std::greater<State>> pq;\n        std::vector<std::vector<int>> dist(N, std::vector<int>(N, 1e9));\n        std::vector<std::vector<Point>> parent(N, std::vector<Point>(N, {-1, -1}));\n\n        for (int r = 0; r < N; ++r) for (int c = 0; c < N; ++c) {\n            if (grid[r][c] == c1) { pq.emplace(0, r, c); dist[r][c] = 0; }\n        }\n\n        const int PENALTY = N*N;\n        int dr[] = {-1, 1, 0, 0}; int dc[] = {0, 0, -1, 1};\n        Point end_pos = {-1, -1};\n\n        while (!pq.empty()) {\n            auto [d, r, c] = pq.top(); pq.pop();\n            if (d > dist[r][c]) continue;\n\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + dr[i], nc = c + dc[i];\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N && grid[nr][nc] == c2) {\n                    end_pos = {r, c}; goto path_found;\n                }\n            }\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + dr[i], nc = c + dc[i];\n                if (nr < 0 || nr >= N || nc < 0 || nc >= N || (grid[nr][nc] != 0 && grid[nr][nc] != c1)) continue;\n                int cost = 1, penalty = 0;\n                for (int j = 0; j < 4; ++j) {\n                    int nnr = nr + dr[j], nnc = nc + dc[j];\n                    if (nnr < 0 || nnr >= N || nnc < 0 || nnc >= N) continue;\n                    int neighbor_color = grid[nnr][nnc];\n                    if (neighbor_color != 0 && neighbor_color != c1 && !adj[c1][neighbor_color]) penalty += PENALTY;\n                }\n                if (dist[nr][nc] > d + cost + penalty) {\n                    dist[nr][nc] = d + cost + penalty; parent[nr][nc] = {r, c}; pq.emplace(dist[nr][nc], nr, nc);\n                }\n            }\n        }\n    path_found:\n        if (end_pos.r != -1) {\n            Point curr = end_pos;\n            while (grid[curr.r][curr.c] == 0) {\n                grid[curr.r][curr.c] = c1; curr = parent[curr.r][curr.c];\n            }\n        }\n    }\n\n    void connect_to_border(int c1) {\n        if (seed_pos[c1].r == -1) return;\n        using State = std::tuple<int, int, int>;\n        std::priority_queue<State, std::vector<State>, std::greater<State>> pq;\n        std::vector<std::vector<int>> dist(N, std::vector<int>(N, 1e9));\n        std::vector<std::vector<Point>> parent(N, std::vector<Point>(N, {-1, -1}));\n\n        for (int r = 0; r < N; ++r) for (int c = 0; c < N; ++c) {\n            if (grid[r][c] == c1) { pq.emplace(0, r, c); dist[r][c] = 0; }\n        }\n        \n        const int PENALTY = N*N;\n        int dr[] = {-1, 1, 0, 0}; int dc[] = {0, 0, -1, 1};\n        Point end_pos = {-1, -1};\n\n        while (!pq.empty()) {\n            auto [d, r, c] = pq.top(); pq.pop();\n            if (d > dist[r][c]) continue;\n            if (r == 0 || r == N - 1 || c == 0 || c == N - 1) { end_pos = {r, c}; break; }\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + dr[i], nc = c + dc[i];\n                if (nr < 0 || nr >= N || nc < 0 || nc >= N || (grid[nr][nc] != 0 && grid[nr][nc] != c1)) continue;\n                int cost = 1, penalty = 0;\n                for (int j = 0; j < 4; ++j) {\n                    int nnr = nr + dr[j], nnc = nc + dc[j];\n                    if (nnr < 0 || nnr >= N || nnc < 0 || nnc >= N) continue;\n                    int neighbor_color = grid[nnr][nnc];\n                    if (neighbor_color != 0 && neighbor_color != c1 && !adj[c1][neighbor_color]) penalty += PENALTY;\n                }\n                if (!adj[c1][0] && (nr==0 || nr==N-1 || nc==0 || nc==N-1)) penalty += PENALTY;\n                if (dist[nr][nc] > d + cost + penalty) {\n                    dist[nr][nc] = d + cost + penalty; parent[nr][nc] = {r, c}; pq.emplace(dist[nr][nc], nr, nc);\n                }\n            }\n        }\n        if (end_pos.r != -1) {\n            Point curr = end_pos;\n            while (grid[curr.r][curr.c] == 0) {\n                grid[curr.r][curr.c] = c1; curr = parent[curr.r][curr.c];\n            }\n        }\n    }\n};\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    Timer timer;\n\n    read_input();\n    build_adj();\n\n    Solver solver(timer);\n    Solution best_solution = solver.solve();\n    \n    best_solution.print();\n\n    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n\n// --- Utilities ---\nstruct Timer {\n    std::chrono::high_resolution_clock::time_point start_time;\n    Timer() {\n        start_time = std::chrono::high_resolution_clock::now();\n    }\n    long long get_elapsed_ms() const {\n        auto now = std::chrono::high_resolution_clock::now();\n        return std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time).count();\n    }\n};\n\nstd::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// --- Problem specific globals ---\nint N, D, Q;\nconst int NUM_PARTICLES = 2000;\nstd::vector<std::vector<long long>> particles;\ndouble W_CAP;\n\n// --- Query interaction ---\nchar query(const std::vector<int>& L, const std::vector<int>& R) {\n    std::cout << L.size() << \" \" << R.size();\n    for (int x : L) std::cout << \" \" << x;\n    for (int x : R) std::cout << \" \" << x;\n    std::cout << std::endl;\n    char res;\n    std::cin >> res;\n    return res;\n}\n\n// --- Particle management ---\nvoid generate_particles() {\n    particles.clear();\n    std::uniform_real_distribution<double> unif(0.0, 1.0);\n    const double lambda = 1e-5;\n\n    for (int i = 0; i < NUM_PARTICLES; ++i) {\n        std::vector<long long> weights(N);\n        for (int j = 0; j < N; ++j) {\n            double w_prime;\n            do {\n                double u = std::max(1e-9, unif(rng)); // Avoid log(0)\n                w_prime = -log(u) / lambda;\n            } while (w_prime > W_CAP);\n            weights[j] = std::max(1LL, (long long)round(w_prime));\n        }\n        particles.push_back(weights);\n    }\n}\n\nvoid filter_particles(const std::vector<int>& L, const std::vector<int>& R, char result) {\n    std::vector<std::vector<long long>> next_particles;\n    next_particles.reserve(particles.size());\n    for (const auto& p : particles) {\n        long long sum_L = 0, sum_R = 0;\n        for (int i : L) sum_L += p[i];\n        for (int i : R) sum_R += p[i];\n        \n        bool consistent = false;\n        if (result == '<' && sum_L < sum_R) consistent = true;\n        else if (result == '>' && sum_L > sum_R) consistent = true;\n        else if (result == '=' && sum_L == sum_R) consistent = true;\n        \n        if (consistent) {\n            next_particles.push_back(p);\n        }\n    }\n    if (!next_particles.empty()) {\n        particles = std::move(next_particles);\n    }\n}\n\nstd::vector<double> get_estimated_weights() {\n    std::vector<double> avg_weights(N, 0.0);\n    if (particles.empty()) {\n        for(int i=0; i<N; ++i) avg_weights[i] = 1.0;\n        return avg_weights;\n    }\n    for (int i = 0; i < N; ++i) {\n        long long total = 0;\n        for (const auto& p : particles) {\n            total += p[i];\n        }\n        avg_weights[i] = (double)total / particles.size();\n    }\n    return avg_weights;\n}\n\n// --- Main logic ---\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    Timer timer;\n\n    std::cin >> N >> D >> Q;\n    W_CAP = 1e5 * N / D;\n\n    generate_particles();\n\n    int queries_made = 0;\n\n    int num_sort_queries = std::min((int)(Q * 0.5), N * (N - 1) / 2);\n    if (N > 80 && Q > 20 * N) num_sort_queries = std::min((int)(Q * 0.3), N * (N - 1) / 2);\n\n    std::vector<std::pair<int, int>> pairs;\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            pairs.push_back({i, j});\n        }\n    }\n    std::shuffle(pairs.begin(), pairs.end(), rng);\n\n    for (int i = 0; i < num_sort_queries && i < pairs.size() && queries_made < Q; ++i) {\n        auto [u, v] = pairs[i];\n        char res = query({u}, {v});\n        filter_particles({u}, {v}, res);\n        queries_made++;\n    }\n\n    int k_cycle = 0;\n    while (queries_made < Q) {\n        auto estimated_weights = get_estimated_weights();\n        std::vector<int> p(N);\n        std::iota(p.begin(), p.end(), 0);\n        std::sort(p.begin(), p.end(), [&](int i, int j) {\n            return estimated_weights[i] < estimated_weights[j];\n        });\n\n        std::vector<double> prefix_sum_w(N, 0.0);\n        prefix_sum_w[0] = estimated_weights[p[0]];\n        for (int i = 1; i < N; ++i) {\n            prefix_sum_w[i] = prefix_sum_w[i-1] + estimated_weights[p[i]];\n        }\n        \n        int k_idx = (N - 1) - (k_cycle % (N - 1));\n        if (k_idx <= 0) k_idx = 1;\n        int item_k = p[k_idx];\n\n        auto it = std::upper_bound(prefix_sum_w.begin(), prefix_sum_w.begin() + k_idx, estimated_weights[item_k]);\n        int j_idx = std::distance(prefix_sum_w.begin(), it);\n        if (j_idx > 0 && j_idx < k_idx) {\n            if (std::abs(prefix_sum_w[j_idx] - estimated_weights[item_k]) > std::abs(prefix_sum_w[j_idx-1] - estimated_weights[item_k])) {\n                j_idx--;\n            }\n        }\n        j_idx = std::max(0, std::min(k_idx - 1, j_idx));\n        \n        std::vector<int> L = {item_k};\n        std::vector<int> R;\n        for (int i = 0; i <= j_idx; ++i) {\n            R.push_back(p[i]);\n        }\n\n        char res = query(L, R);\n        filter_particles(L, R, res);\n        queries_made++;\n        k_cycle++;\n    }\n\n    auto final_weights = get_estimated_weights();\n    std::vector<long long> scaled_weights(N);\n    double scale_factor = 1000.0;\n    for(int i=0; i<N; ++i) {\n        scaled_weights[i] = round(final_weights[i] * scale_factor);\n    }\n\n    std::vector<int> p(N);\n    std::iota(p.begin(), p.end(), 0);\n    std::sort(p.begin(), p.end(), [&](int i, int j) {\n        return scaled_weights[i] > scaled_weights[j];\n    });\n\n    std::vector<int> assignment(N);\n    using int128 = __int128_t;\n    std::vector<int128> set_sums(D, 0);\n    \n    for (int item_idx : p) {\n        int best_set = 0;\n        if (D > 0) {\n            for (int j = 1; j < D; ++j) {\n                if (set_sums[j] < set_sums[best_set]) {\n                    best_set = j;\n                }\n            }\n        }\n        assignment[item_idx] = best_set;\n        if(D > 0) set_sums[best_set] += scaled_weights[item_idx];\n    }\n    \n    std::vector<int128> current_set_sums = set_sums;\n    std::vector<int> current_assignment = assignment;\n    \n    int128 current_score = 0;\n    for(auto s : current_set_sums) current_score += s*s;\n\n    auto best_assignment = current_assignment;\n    int128 best_score = current_score;\n\n    long double start_temp = 0.0;\n    if (N > 0 && D > 1) {\n        for(int i=0; i<100; ++i) {\n            int item_idx = rng() % N;\n            int d1 = current_assignment[item_idx];\n            int d2 = (d1 + 1 + (rng() % (D-1))) % D;\n            int128 w = scaled_weights[item_idx];\n            int128 s1 = current_set_sums[d1];\n            int128 s2 = current_set_sums[d2];\n            start_temp += std::abs((long double)(2 * w * (s2 - s1 + w)));\n        }\n        start_temp /= 100;\n        if (start_temp < 1e-9) start_temp = 1.0;\n    }\n\n\n    long double end_temp = 1e-9;\n    \n    long long time_limit = 1950;\n    \n    while(D > 1 && timer.get_elapsed_ms() < time_limit) {\n        \n        long double temp = start_temp * pow(end_temp / start_temp, (long double)timer.get_elapsed_ms() / time_limit);\n        \n        if (rng() % 2 == 0) { // Move\n            int item_idx = rng() % N;\n            int d1 = current_assignment[item_idx];\n            int d2 = (d1 + 1 + (rng() % (D-1))) % D;\n\n            int128 w = scaled_weights[item_idx];\n            int128 s1 = current_set_sums[d1];\n            int128 s2 = current_set_sums[d2];\n\n            int128 new_score = current_score - s1*s1 - s2*s2 + (s1 - w)*(s1 - w) + (s2 + w)*(s2 + w);\n            \n            if (new_score < current_score || std::uniform_real_distribution<long double>(0,1)(rng) < expl((long double)(current_score - new_score) / temp)) {\n                current_assignment[item_idx] = d2;\n                current_set_sums[d1] -= w;\n                current_set_sums[d2] += w;\n                current_score = new_score;\n\n                if (current_score < best_score) {\n                    best_score = current_score;\n                    best_assignment = current_assignment;\n                }\n            }\n        } else { // Swap\n            int item1_idx = rng() % N;\n            int item2_idx;\n            do { item2_idx = rng() % N; } while (item1_idx == item2_idx);\n\n            int d1 = current_assignment[item1_idx];\n            int d2 = current_assignment[item2_idx];\n\n            if (d1 == d2) continue;\n\n            int128 w1 = scaled_weights[item1_idx];\n            int128 w2 = scaled_weights[item2_idx];\n            int128 s1 = current_set_sums[d1];\n            int128 s2 = current_set_sums[d2];\n\n            int128 new_score = current_score - s1*s1 - s2*s2 + (s1 - w1 + w2)*(s1 - w1 + w2) + (s2 - w2 + w1)*(s2 - w2 + w1);\n\n            if (new_score < current_score || std::uniform_real_distribution<long double>(0,1)(rng) < expl((long double)(current_score - new_score) / temp)) {\n                std::swap(current_assignment[item1_idx], current_assignment[item2_idx]);\n                current_set_sums[d1] = s1 - w1 + w2;\n                current_set_sums[d2] = s2 - w2 + w1;\n                current_score = new_score;\n\n                if (current_score < best_score) {\n                    best_score = current_score;\n                    best_assignment = current_assignment;\n                }\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        std::cout << best_assignment[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    std::cout << std::endl;\n\n    return 0;\n}","ahc026":"#include <iostream>\n#include <vector>\n#include <deque>\n#include <array>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n\nusing namespace std;\n\nconst int N = 200;\nconst int M = 10;\nint BEAM_WIDTH = 50; // Tunable parameter\n\nstruct State {\n    array<deque<int>, M> stacks;\n    array<pair<int, int>, N + 1> box_pos; // {stack_idx, height_from_bottom}\n    long long cost = 0;\n    double score = 0.0;\n    vector<pair<int, int>> history;\n\n    State() {\n        for(int i=0; i<=N; ++i) box_pos[i] = {-1, -1};\n    }\n    \n    double calculate_heuristic(int v_start) const {\n        double h = 0;\n        for (int v = v_start; v <= N; ++v) {\n            if (box_pos[v].first != -1) { // if not carried out\n                int stack_idx = box_pos[v].first;\n                int height = box_pos[v].second;\n                int boxes_on_top = stacks[stack_idx].size() - height - 1;\n                if (boxes_on_top > 0) {\n                    h += boxes_on_top + 1;\n                }\n            }\n        }\n        return h;\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    auto start_time = chrono::high_resolution_clock::now();\n\n    int n_in, m_in;\n    cin >> n_in >> m_in;\n\n    State initial_state;\n    for (int i = 0; i < M; ++i) {\n        initial_state.stacks[i].resize(N / M);\n        for (int j = 0; j < N / M; ++j) {\n            int b;\n            cin >> b;\n            initial_state.stacks[i][j] = b;\n            initial_state.box_pos[b] = {i, j};\n        }\n    }\n\n    vector<State> beam;\n    beam.push_back(initial_state);\n\n    for (int v_to_carry = 1; v_to_carry <= N; ++v_to_carry) {\n        auto current_time = chrono::high_resolution_clock::now();\n        double elapsed_ms = chrono::duration<double, milli>(current_time - start_time).count();\n        if (elapsed_ms > 1900) {\n            BEAM_WIDTH = 1;\n        } else if (elapsed_ms > 1800) {\n            BEAM_WIDTH = min(BEAM_WIDTH, 5);\n        } else if (elapsed_ms > 1500) {\n            BEAM_WIDTH = min(BEAM_WIDTH, 15);\n        }\n\n        vector<State> candidates;\n        candidates.reserve(beam.size() * M);\n        \n        for (const auto& s : beam) {\n            int stack_idx = s.box_pos[v_to_carry].first;\n            int height = s.box_pos[v_to_carry].second;\n            \n            if (s.stacks[stack_idx].size() - 1 == height) { // is on top\n                State next_s = s;\n                int box_v = next_s.stacks[stack_idx].back();\n                next_s.stacks[stack_idx].pop_back();\n                next_s.box_pos[box_v] = {-1, -1};\n                next_s.history.push_back({box_v, 0});\n                next_s.score = next_s.cost + next_s.calculate_heuristic(v_to_carry + 1);\n                candidates.push_back(move(next_s));\n            } else { // not on top, must move\n                int move_v = s.stacks[stack_idx][height + 1];\n                \n                int empty_stack_idx = -1;\n                for (int i = 0; i < M; ++i) {\n                    if (i != stack_idx && s.stacks[i].empty()) {\n                        empty_stack_idx = i;\n                        break;\n                    }\n                }\n                \n                vector<int> dest_options;\n                if (empty_stack_idx != -1) {\n                    dest_options.push_back(empty_stack_idx);\n                } else {\n                    for (int i = 0; i < M; ++i) {\n                        if (i != stack_idx) {\n                            dest_options.push_back(i);\n                        }\n                    }\n                }\n\n                for (int dest_idx : dest_options) {\n                    State next_s = s;\n                    \n                    auto& src_stack = next_s.stacks[stack_idx];\n                    vector<int> moved_boxes;\n                    moved_boxes.assign(src_stack.begin() + height + 1, src_stack.end());\n                    src_stack.resize(height + 1);\n                    \n                    int num_moved = moved_boxes.size();\n                    next_s.cost += num_moved + 1;\n                    next_s.history.push_back({move_v, dest_idx + 1});\n                    \n                    auto& dest_stack = next_s.stacks[dest_idx];\n                    int old_dest_size = dest_stack.size();\n                    dest_stack.insert(dest_stack.end(), moved_boxes.begin(), moved_boxes.end());\n\n                    for (size_t i = 0; i < moved_boxes.size(); ++i) {\n                        int box_id = moved_boxes[i];\n                        next_s.box_pos[box_id] = {dest_idx, (int)(old_dest_size + i)};\n                    }\n                    \n                    // Now carry out v_to_carry\n                    int box_v = next_s.stacks[stack_idx].back();\n                    next_s.stacks[stack_idx].pop_back();\n                    next_s.box_pos[box_v] = {-1, -1};\n                    next_s.history.push_back({box_v, 0});\n\n                    next_s.score = next_s.cost + next_s.calculate_heuristic(v_to_carry + 1);\n                    candidates.push_back(move(next_s));\n                }\n            }\n        }\n\n        sort(candidates.begin(), candidates.end(), [](const auto& a, const auto& b) {\n            return a.score < b.score;\n        });\n\n        beam.clear();\n        for (size_t i = 0; i < min((size_t)candidates.size(), (size_t)BEAM_WIDTH); ++i) {\n            beam.push_back(move(candidates[i]));\n        }\n    }\n    \n    const State* best_state = &beam[0];\n    for(size_t i = 1; i < beam.size(); ++i) {\n        if(beam[i].cost < best_state->cost) {\n            best_state = &beam[i];\n        }\n    }\n\n    for (const auto& op : best_state->history) {\n        cout << op.first << \" \" << op.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc027":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <functional>\n#include <list>\n#include <set>\n#include <chrono>\n#include <map>\n\n// Timer\nauto start_time = std::chrono::high_resolution_clock::now();\n\nstruct Pos {\n    short r, c;\n    bool operator<(const Pos& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n    bool operator==(const Pos& other) const {\n        return r == other.r && c == other.c;\n    }\n};\n\nint N;\nstd::vector<std::string> h_walls, v_walls;\nstd::vector<std::vector<int>> d;\nstd::vector<std::vector<std::vector<Pos>>> adj;\nstd::vector<std::vector<long long>> k;\nstd::vector<std::vector<double>> g;\n\n// Randomness\nstd::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\nvoid build_adj() {\n    adj.assign(N, std::vector<std::vector<Pos>>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (i > 0 && h_walls[i - 1][j] == '0') adj[i][j].push_back({(short)(i - 1), (short)j});\n            if (i < N - 1 && h_walls[i][j] == '0') adj[i][j].push_back({(short)(i + 1), (short)j});\n            if (j > 0 && v_walls[i][j - 1] == '0') adj[i][j].push_back({(short)i, (short)(j - 1)});\n            if (j < N - 1 && v_walls[i][j] == '0') adj[i][j].push_back({(short)i, (short)(j + 1)});\n        }\n    }\n}\n\n// Generate initial path via randomized DFS\nstd::list<Pos> tour;\nstd::vector<std::vector<bool>> visited;\n\nvoid generate_initial_path_dfs(Pos p) {\n    visited[p.r][p.c] = true;\n    tour.push_back(p);\n    \n    std::vector<Pos> neighbors = adj[p.r][p.c];\n    std::shuffle(neighbors.begin(), neighbors.end(), rng);\n    \n    for (const auto& next_p : neighbors) {\n        if (!visited[next_p.r][next_p.c]) {\n            generate_initial_path_dfs(next_p);\n            tour.push_back(p);\n        }\n    }\n}\n\nstd::string pos_to_moves(const std::list<Pos>& pos_path) {\n    std::string moves;\n    moves.reserve(pos_path.size());\n    auto it = pos_path.begin();\n    Pos current = *it;\n    ++it;\n    while (it != pos_path.end()) {\n        Pos next = *it;\n        if (next.r == current.r - 1) moves.push_back('U');\n        else if (next.r == current.r + 1) moves.push_back('D');\n        else if (next.c == current.c - 1) moves.push_back('L');\n        else moves.push_back('R');\n        current = next;\n        ++it;\n    }\n    return moves;\n}\n\ndouble calculate_g(const Pos& p) {\n    if (k[p.r][p.c] == 0) return 1e18; // Should not happen after initial path\n    return (double)d[p.r][p.c] / (k[p.r][p.c] * (k[p.r][p.c] + 1.0));\n}\n\nstruct PQ_Elem {\n    double score;\n    Pos p;\n    bool operator<(const PQ_Elem& other) const {\n        if (std::abs(score - other.score) > 1e-9) return score < other.score;\n        return p < other.p;\n    }\n};\n\nvoid solve() {\n    build_adj();\n    \n    visited.assign(N, std::vector<bool>(N, false));\n    generate_initial_path_dfs({0,0});\n    \n    k.assign(N, std::vector<long long>(N, 0));\n    std::vector<std::vector<std::list<Pos>::iterator>> pos_iters(N, std::vector<std::list<Pos>::iterator>(N));\n\n    for(auto it = tour.begin(); it != tour.end(); ++it) {\n        k[it->r][it->c]++;\n        pos_iters[it->r][it->c] = it;\n    }\n\n    g.assign(N, std::vector<double>(N));\n    std::vector<std::vector<Pos>> best_neighbor(N, std::vector<Pos>(N));\n    std::set<PQ_Elem> pq;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            g[i][j] = calculate_g({(short)i, (short)j});\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            Pos p = {(short)i, (short)j};\n            double max_g = -1.0;\n            Pos bn = {-1, -1};\n            for (const auto& neighbor : adj[i][j]) {\n                if (g[neighbor.r][neighbor.c] > max_g) {\n                    max_g = g[neighbor.r][neighbor.c];\n                    bn = neighbor;\n                }\n            }\n            best_neighbor[i][j] = bn;\n            if (bn.r != -1) {\n                pq.insert({g[i][j] + max_g, p});\n            }\n        }\n    }\n\n    int MAX_L = 100000;\n    \n    while (tour.size() + 2 <= MAX_L) {\n        auto now = std::chrono::high_resolution_clock::now();\n        if (std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time).count() > 1980) {\n            break;\n        }\n\n        if (pq.empty()) break;\n        \n        PQ_Elem top = *pq.rbegin();\n        Pos u = top.p;\n        Pos v = best_neighbor[u.r][u.c];\n\n        if(v.r == -1) {\n            pq.erase(std::prev(pq.end()));\n            continue;\n        }\n        \n        auto it_u_orig = pos_iters[u.r][u.c];\n        auto it_after_u = std::next(it_u_orig);\n        auto it_new_u = tour.insert(it_after_u, u);\n        auto it_v = tour.insert(it_new_u, v);\n        \n        pos_iters[u.r][u.c] = it_new_u;\n        pos_iters[v.r][v.c] = it_v;\n\n        k[u.r][u.c]++;\n        k[v.r][v.c]++;\n\n        std::set<Pos> to_update_pq;\n        to_update_pq.insert(u);\n        to_update_pq.insert(v);\n        for(const auto& neighbor: adj[u.r][u.c]) to_update_pq.insert(neighbor);\n        for(const auto& neighbor: adj[v.r][v.c]) to_update_pq.insert(neighbor);\n        \n        for (const auto& p : to_update_pq) {\n            Pos bn = best_neighbor[p.r][p.c];\n            if (bn.r != -1) {\n                pq.erase({g[p.r][p.c] + g[bn.r][bn.c], p});\n            }\n        }\n        \n        g[u.r][u.c] = calculate_g(u);\n        g[v.r][v.c] = calculate_g(v);\n\n        for (const auto& p : to_update_pq) {\n            double max_g = -1.0;\n            Pos bn = {-1, -1};\n            if (!adj[p.r][p.c].empty()){\n                for (const auto& neighbor : adj[p.r][p.c]) {\n                    if (g[neighbor.r][neighbor.c] > max_g) {\n                        max_g = g[neighbor.r][neighbor.c];\n                        bn = neighbor;\n                    }\n                }\n                best_neighbor[p.r][p.c] = bn;\n                if (bn.r != -1) {\n                    pq.insert({g[p.r][p.c] + max_g, p});\n                }\n            }\n        }\n    }\n\n    std::string moves = pos_to_moves(tour);\n    std::cout << moves << std::endl;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    std::cin >> N;\n    h_walls.resize(N - 1);\n    v_walls.resize(N);\n    d.assign(N, std::vector<int>(N));\n    for (int i = 0; i < N - 1; ++i) std::cin >> h_walls[i];\n    for (int i = 0; i < N; ++i) std::cin >> v_walls[i];\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            std::cin >> d[i][j];\n        }\n    }\n    \n    solve();\n    \n    return 0;\n}","ahc028":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <random>\n\nusing namespace std;\n\n// Constants from problem statement\nconst int N_GRID = 15;\nconst int M_TARGETS = 200;\n\n// Global variables for problem input\nint start_r, start_c;\nvector<string> grid(N_GRID);\nvector<string> targets(M_TARGETS);\n\n// Precomputed data structures\nvector<pair<int, int>> char_positions[26];\nint overlaps[M_TARGETS][M_TARGETS];\ndouble avg_transition_cost[26][26];\ndouble weights[M_TARGETS][M_TARGETS];\n\n// Random number generator for SA\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// --- Utility Functions ---\n\nint manhattan_distance(int r1, int c1, int r2, int c2) {\n    return abs(r1 - r2) + abs(c1 - c2);\n}\n\n// --- Precomputation Functions ---\n\nvoid read_input() {\n    int n_in, m_in;\n    cin >> n_in >> m_in;\n    cin >> start_r >> start_c;\n    for (int i = 0; i < N_GRID; ++i) cin >> grid[i];\n    for (int i = 0; i < M_TARGETS; ++i) cin >> targets[i];\n}\n\nvoid precompute_char_positions() {\n    for (int i = 0; i < N_GRID; ++i) {\n        for (int j = 0; j < N_GRID; ++j) {\n            char_positions[grid[i][j] - 'A'].push_back({i, j});\n        }\n    }\n}\n\nvoid precompute_overlaps() {\n    for (int i = 0; i < M_TARGETS; ++i) {\n        for (int j = 0; j < M_TARGETS; ++j) {\n            if (i == j) continue;\n            for (int k = 4; k >= 1; --k) {\n                if (targets[i].substr(5 - k) == targets[j].substr(0, k)) {\n                    overlaps[i][j] = k;\n                    break;\n                }\n            }\n        }\n    }\n}\n\nvoid precompute_avg_transition_cost() {\n    for (int i = 0; i < 26; ++i) {\n        for (int j = 0; j < 26; ++j) {\n            if (char_positions[i].empty() || char_positions[j].empty()) continue;\n            double total_min_dist = 0;\n            for (const auto& p1 : char_positions[i]) {\n                int min_dist = 1e9;\n                for (const auto& p2 : char_positions[j]) {\n                    min_dist = min(min_dist, manhattan_distance(p1.first, p1.second, p2.first, p2.second));\n                }\n                total_min_dist += min_dist;\n            }\n            avg_transition_cost[i][j] = total_min_dist / char_positions[i].size() + 1.0;\n        }\n    }\n}\n\nvoid precompute_weights() {\n    for (int i = 0; i < M_TARGETS; ++i) {\n        for (int j = 0; j < M_TARGETS; ++j) {\n            if (i == j) continue;\n            int ov = overlaps[i][j];\n            const string& t_j = targets[j];\n            const string& t_i = targets[i];\n            \n            double cost_est = 0;\n            if (5 - ov > 0) {\n                cost_est += avg_transition_cost[t_i.back() - 'A'][t_j[ov] - 'A'];\n                for (int k = ov; k < 4; ++k) {\n                    cost_est += avg_transition_cost[t_j[k] - 'A'][t_j[k+1] - 'A'];\n                }\n            }\n            weights[i][j] = (5.0 - ov) + cost_est;\n        }\n    }\n}\n\n// --- Core Logic ---\n\nlong long calculate_path_cost(const vector<int>& path, vector<pair<int, int>>& move_sequence) {\n    move_sequence.clear();\n    string S;\n    S.reserve(5 * M_TARGETS);\n    S += targets[path[0]];\n    for (size_t i = 1; i < path.size(); ++i) {\n        int u = path[i-1];\n        int v = path[i];\n        int ov = overlaps[u][v];\n        S += targets[v].substr(ov);\n    }\n\n    if (S.length() > 5000) return 1e18; \n\n    long long total_cost = 0;\n    int cur_r = start_r;\n    int cur_c = start_c;\n\n    for (char ch : S) {\n        int char_idx = ch - 'A';\n        int best_r = -1, best_c = -1;\n        int min_dist = 1e9;\n\n        for (const auto& pos : char_positions[char_idx]) {\n            int d = manhattan_distance(cur_r, cur_c, pos.first, pos.second);\n            if (d < min_dist) {\n                min_dist = d;\n                best_r = pos.first;\n                best_c = pos.second;\n            }\n        }\n        total_cost += min_dist + 1;\n        cur_r = best_r;\n        cur_c = best_c;\n        move_sequence.push_back({cur_r, cur_c});\n    }\n    return total_cost;\n}\n\nlong long calculate_path_cost(const vector<int>& path) {\n    vector<pair<int, int>> dummy;\n    return calculate_path_cost(path, dummy);\n}\n\ndouble calculate_approx_cost(const vector<int>& path) {\n    double cost = 0;\n    for (size_t i = 0; i < path.size() - 1; ++i) {\n        cost += weights[path[i]][path[i+1]];\n    }\n    return cost;\n}\n\nvector<int> get_initial_solution() {\n    vector<int> best_path;\n    double min_weight_sum = 1e18;\n\n    vector<int> start_nodes_to_try;\n    vector<int> p(M_TARGETS);\n    iota(p.begin(), p.end(), 0);\n    shuffle(p.begin(), p.end(), rng);\n    for(int i = 0; i < min(M_TARGETS, 10); ++i) start_nodes_to_try.push_back(p[i]);\n    \n    for (int start_node : start_nodes_to_try) {\n        vector<int> path;\n        path.reserve(M_TARGETS);\n        path.push_back(start_node);\n        vector<bool> visited(M_TARGETS, false);\n        visited[start_node] = true;\n        int current_node = start_node;\n        double current_weight_sum = 0;\n\n        for (int i = 0; i < M_TARGETS - 1; ++i) {\n            int next_node = -1;\n            double min_weight = 1e18;\n            for (int j = 0; j < M_TARGETS; ++j) {\n                if (!visited[j]) {\n                    if (weights[current_node][j] < min_weight) {\n                        min_weight = weights[current_node][j];\n                        next_node = j;\n                    }\n                }\n            }\n            visited[next_node] = true;\n            path.push_back(next_node);\n            current_weight_sum += min_weight;\n            current_node = next_node;\n        }\n        \n        if (current_weight_sum < min_weight_sum) {\n            min_weight_sum = current_weight_sum;\n            best_path = path;\n        }\n    }\n    return best_path;\n}\n\nvoid solve() {\n    auto time_start = chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_MS = 1950.0;\n    const double FAST_SA_TIME_MS = 1700.0;\n\n    vector<int> current_path = get_initial_solution();\n    vector<int> best_path_overall = current_path;\n    long long best_cost_overall = calculate_path_cost(best_path_overall);\n\n    // --- Fast SA Stage ---\n    {\n        double start_temp = 50.0, end_temp = 0.1;\n        vector<int> best_path_fast = current_path;\n        double current_approx_cost = calculate_approx_cost(current_path);\n        double best_approx_cost = current_approx_cost;\n        int iter_count = 0;\n\n        while (true) {\n            iter_count++;\n            if (iter_count % 100 == 0) {\n                if (chrono::duration<double, milli>(chrono::high_resolution_clock::now() - time_start).count() > FAST_SA_TIME_MS) break;\n            }\n\n            vector<int> new_path = current_path;\n            int i = uniform_int_distribution<int>(0, M_TARGETS - 1)(rng);\n            int j = uniform_int_distribution<int>(0, M_TARGETS - 1)(rng);\n            if (i == j) continue;\n            \n            int move_type = uniform_int_distribution<int>(0, 2)(rng);\n            if (move_type == 0) { // Reverse\n                if (i > j) swap(i, j);\n                reverse(new_path.begin() + i, new_path.begin() + j + 1);\n            } else if (move_type == 1) { // Swap\n                swap(new_path[i], new_path[j]);\n            } else { // Move\n                int element = new_path[i];\n                new_path.erase(new_path.begin() + i);\n                new_path.insert(new_path.begin() + j, element);\n            }\n\n            double new_approx_cost = calculate_approx_cost(new_path);\n            double elapsed_frac = chrono::duration<double, milli>(chrono::high_resolution_clock::now() - time_start).count() / FAST_SA_TIME_MS;\n            double temp = start_temp * pow(end_temp / start_temp, elapsed_frac);\n            \n            if (new_approx_cost < current_approx_cost || uniform_real_distribution<double>(0.0, 1.0)(rng) < exp((current_approx_cost - new_approx_cost) / temp)) {\n                current_path = new_path;\n                current_approx_cost = new_approx_cost;\n            }\n\n            if (current_approx_cost < best_approx_cost) {\n                best_approx_cost = current_approx_cost;\n                best_path_fast = current_path;\n            }\n        }\n        long long fast_sa_best_full_cost = calculate_path_cost(best_path_fast);\n        if (fast_sa_best_full_cost < best_cost_overall) {\n            best_cost_overall = fast_sa_best_full_cost;\n            best_path_overall = best_path_fast;\n        }\n    }\n\n    // --- Slow SA Stage ---\n    {\n        double start_temp = 30.0, end_temp = 0.01;\n        current_path = best_path_overall;\n        long long current_full_cost = best_cost_overall;\n        int iter_count = 0;\n        \n        while (true) {\n            iter_count++;\n             if (iter_count % 5 == 0) {\n                if (chrono::duration<double, milli>(chrono::high_resolution_clock::now() - time_start).count() > TIME_LIMIT_MS) break;\n            }\n\n            vector<int> new_path = current_path;\n            int i = uniform_int_distribution<int>(0, M_TARGETS - 1)(rng);\n            int j = uniform_int_distribution<int>(0, M_TARGETS - 1)(rng);\n            if (i == j) continue;\n            \n            int move_type = uniform_int_distribution<int>(0, 2)(rng);\n            if (move_type == 0) { // Reverse\n                if (i > j) swap(i, j);\n                reverse(new_path.begin() + i, new_path.begin() + j + 1);\n            } else if (move_type == 1) { // Swap\n                swap(new_path[i], new_path[j]);\n            } else { // Move\n                int element = new_path[i];\n                new_path.erase(new_path.begin() + i);\n                new_path.insert(new_path.begin() + j, element);\n            }\n\n            long long new_full_cost = calculate_path_cost(new_path);\n            \n            double elapsed_frac = (chrono::duration<double, milli>(chrono::high_resolution_clock::now() - time_start).count() - FAST_SA_TIME_MS) / (TIME_LIMIT_MS - FAST_SA_TIME_MS);\n            double temp = start_temp * pow(end_temp / start_temp, elapsed_frac);\n            \n            if (new_full_cost < current_full_cost || uniform_real_distribution<double>(0.0, 1.0)(rng) < exp((double)(current_full_cost - new_full_cost) / temp)) {\n                current_path = new_path;\n                current_full_cost = new_full_cost;\n            }\n\n            if (current_full_cost < best_cost_overall) {\n                best_cost_overall = current_full_cost;\n                best_path_overall = current_path;\n            }\n        }\n    }\n\n    vector<pair<int, int>> final_moves;\n    calculate_path_cost(best_path_overall, final_moves);\n    for (const auto& move : final_moves) {\n        cout << move.first << \" \" << move.second << \"\\n\";\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    read_input();\n    precompute_char_positions();\n    precompute_overlaps();\n    precompute_avg_transition_cost();\n    precompute_weights();\n    \n    solve();\n\n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <map>\n#include <iomanip>\n\n// Constants and Typedefs\nusing namespace std;\nusing Point = pair<int, int>;\n\n// Utilities\nstruct Timer {\n    chrono::high_resolution_clock::time_point start_time;\n    Timer() {\n        start_time = chrono::high_resolution_clock::now();\n    }\n    long long get_elapsed_ms() {\n        auto end_time = chrono::high_resolution_clock::now();\n        return chrono::duration_cast<chrono::milliseconds>(end_time - start_time).count();\n    }\n};\n\n// Global random engine\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// Problem specific structures\nstruct Polyomino {\n    int id;\n    int d;\n    vector<Point> coords;\n    int max_i = 0, max_j = 0;\n};\n\nstruct Problem {\n    int N, M;\n    double epsilon;\n    vector<Polyomino> fields;\n    vector<vector<Point>> valid_placements;\n    map<vector<Point>, vector<int>> identical_shapes;\n};\n\nstruct Particle {\n    vector<Point> placements;\n    vector<vector<int>> v_grid;\n\n    Particle(int M, int N) : placements(M), v_grid(N, vector<int>(N, 0)) {}\n\n    void compute_v_grid(const Problem& prob) {\n        for (auto& row : v_grid) fill(row.begin(), row.end(), 0);\n        for (int m = 0; m < prob.M; ++m) {\n            const auto& field = prob.fields[m];\n            const auto& p = placements[m];\n            for (const auto& rel_coord : field.coords) {\n                v_grid[p.first + rel_coord.first][p.second + rel_coord.second]++;\n            }\n        }\n    }\n};\n\n// Main solver\nclass Solver {\nprivate:\n    Problem prob;\n    int num_particles;\n    vector<Particle> particles;\n    vector<double> weights;\n    vector<vector<int>> known_v;\n    Timer timer;\n    int query_count = 0;\n    \npublic:\n    Solver(int N, int M, double epsilon, const vector<Polyomino>& fields, int K)\n        : prob{N, M, epsilon, fields}, num_particles(K), known_v(N, vector<int>(N, -1)) {\n        prob.valid_placements.resize(M);\n        for (int m = 0; m < M; ++m) {\n            auto& field = prob.fields[m];\n            field.max_i = 0;\n            field.max_j = 0;\n            for(const auto& p : field.coords) {\n                field.max_i = max(field.max_i, p.first);\n                field.max_j = max(field.max_j, p.second);\n            }\n            for (int i = 0; i < N - field.max_i; ++i) {\n                for (int j = 0; j < N - field.max_j; ++j) {\n                    prob.valid_placements[m].push_back({i, j});\n                }\n            }\n        }\n        \n        for (int m = 0; m < M; ++m) {\n            vector<Point> sorted_coords = fields[m].coords;\n            sort(sorted_coords.begin(), sorted_coords.end());\n            prob.identical_shapes[sorted_coords].push_back(m);\n        }\n    }\n\n    void solve() {\n        initialize_particles();\n\n        perform_initial_queries();\n\n        while (timer.get_elapsed_ms() < 2800 && query_count < 2 * prob.N * prob.N) {\n            auto p_grid = calculate_p_grid();\n            vector<Point> uncertain_cells;\n            Point most_uncertain_cell = {-1, -1};\n            double min_dist_to_half = 1.0;\n\n            for (int i = 0; i < prob.N; ++i) {\n                for (int j = 0; j < prob.N; ++j) {\n                    if (known_v[i][j] == -1) {\n                         if (p_grid[i][j] > 0.05 && p_grid[i][j] < 0.95) {\n                            uncertain_cells.push_back({i, j});\n                            if (abs(p_grid[i][j] - 0.5) < min_dist_to_half) {\n                                min_dist_to_half = abs(p_grid[i][j] - 0.5);\n                                most_uncertain_cell = {i, j};\n                            }\n                        }\n                    }\n                }\n            }\n            \n            if (most_uncertain_cell.first == -1) {\n                break; // Converged\n            }\n\n            if (uncertain_cells.size() < prob.N) { // Phase 3: Verification\n                query_drill(most_uncertain_cell.first, most_uncertain_cell.second);\n            } else { // Phase 2: Refinement\n                int block_size = 3;\n                vector<Point> query_set;\n                for (int di = -block_size / 2; di <= block_size / 2; ++di) {\n                    for (int dj = -block_size / 2; dj <= block_size / 2; ++dj) {\n                        int ni = most_uncertain_cell.first + di;\n                        int nj = most_uncertain_cell.second + dj;\n                        if (ni >= 0 && ni < prob.N && nj >= 0 && nj < prob.N && known_v[ni][nj] == -1) {\n                           query_set.push_back({ni, nj});\n                        }\n                    }\n                }\n                if (query_set.size() >= 2) {\n                    query_divine(query_set);\n                } else {\n                    query_drill(most_uncertain_cell.first, most_uncertain_cell.second);\n                }\n            }\n\n            if (timer.get_elapsed_ms() > 2800) break;\n\n            resample_and_mutate();\n        }\n\n        make_final_guess();\n    }\n\nprivate:\n    void initialize_particles() {\n        particles.clear();\n        for (int i = 0; i < num_particles; ++i) {\n            particles.emplace_back(prob.M, prob.N);\n            for (int m = 0; m < prob.M; ++m) {\n                uniform_int_distribution<> dist(0, prob.valid_placements[m].size() - 1);\n                particles.back().placements[m] = prob.valid_placements[m][dist(rng)];\n            }\n        }\n        for (auto& p : particles) p.compute_v_grid(prob);\n        weights.assign(num_particles, 1.0 / num_particles);\n    }\n    \n    void perform_initial_queries() {\n        vector<Point> all_cells, half_i, half_j, checker;\n        for (int i = 0; i < prob.N; ++i) {\n            for (int j = 0; j < prob.N; ++j) {\n                all_cells.push_back({i, j});\n                if (i < prob.N / 2) half_i.push_back({i, j});\n                if (j < prob.N / 2) half_j.push_back({i, j});\n                if ((i + j) % 2 == 0) checker.push_back({i, j});\n            }\n        }\n        \n        vector<vector<Point>> initial_queries = {all_cells, half_i, half_j, checker};\n        for(const auto& q_set : initial_queries){\n            if (timer.get_elapsed_ms() > 2800) break;\n            if (q_set.size() >= 2) {\n                query_divine(q_set);\n                resample_and_mutate();\n            }\n        }\n    }\n\n    void query_drill(int r, int c) {\n        if (known_v[r][c] != -1) return;\n        query_count++;\n        cout << \"q 1 \" << r << \" \" << c << endl;\n        int v;\n        cin >> v;\n        known_v[r][c] = v;\n        for (int i = 0; i < num_particles; ++i) {\n            if (particles[i].v_grid[r][c] != v) {\n                weights[i] = 0;\n            }\n        }\n    }\n\n    void query_divine(const vector<Point>& S) {\n        if (S.empty()) return;\n        if (S.size() == 1) {\n            query_drill(S[0].first, S[0].second);\n            return;\n        }\n\n        query_count++;\n        cout << \"q \" << S.size();\n        for (const auto& p : S) {\n            cout << \" \" << p.first << \" \" << p.second;\n        }\n        cout << endl;\n        \n        int O;\n        cin >> O;\n        \n        int k = S.size();\n        double var = k * prob.epsilon * (1.0 - prob.epsilon);\n        double stddev = sqrt(var);\n\n        for (int i = 0; i < num_particles; ++i) {\n            if (weights[i] == 0) continue;\n            int vS = 0;\n            for (const auto& p : S) {\n                vS += particles[i].v_grid[p.first][p.second];\n            }\n            double mu = k * prob.epsilon + vS * (1.0 - 2.0 * prob.epsilon);\n            \n            double prob_density;\n            if (stddev > 1e-9) {\n                prob_density = (1.0 / (stddev * sqrt(2 * M_PI))) * exp(-0.5 * pow((O - mu) / stddev, 2));\n            } else {\n                prob_density = (abs(O - mu) < 0.5) ? 1.0 : 1e-9;\n            }\n            weights[i] *= prob_density;\n        }\n    }\n\n    void resample_and_mutate() {\n        double total_weight = accumulate(weights.begin(), weights.end(), 0.0);\n        if (total_weight < 1e-20) {\n            initialize_particles();\n            return;\n        }\n        for (double& w : weights) {\n            w /= total_weight;\n        }\n\n        vector<Particle> new_particles;\n        new_particles.reserve(num_particles);\n        \n        discrete_distribution<int> dist(weights.begin(), weights.end());\n\n        int num_random_particles = num_particles * 0.05;\n        for (int i = 0; i < num_particles - num_random_particles; ++i) {\n            new_particles.push_back(particles[dist(rng)]);\n        }\n        for (int i = 0; i < num_random_particles; ++i) {\n            new_particles.emplace_back(prob.M, prob.N);\n            for (int m = 0; m < prob.M; ++m) {\n                uniform_int_distribution<> p_dist(0, prob.valid_placements[m].size() - 1);\n                new_particles.back().placements[m] = prob.valid_placements[m][p_dist(rng)];\n            }\n        }\n        \n        uniform_real_distribution<> r_dist(0.0, 1.0);\n        for(auto& p : new_particles) {\n            for(int m = 0; m < prob.M; ++m) {\n                if(r_dist(rng) < 0.1) {\n                    if (r_dist(rng) < 0.8 && prob.valid_placements[m].size() > 1) {\n                        const auto& current_pos = p.placements[m];\n                        vector<Point> neighbors;\n                        int dr[] = {-1,1,0,0}; int dc[] = {0,0,-1,1};\n                        for(int i=0; i<4; ++i) {\n                             Point neighbor = {current_pos.first + dr[i], current_pos.second + dc[i]};\n                             if (neighbor.first >= 0 && neighbor.first <= prob.N - 1 - prob.fields[m].max_i &&\n                                 neighbor.second >= 0 && neighbor.second <= prob.N - 1 - prob.fields[m].max_j) {\n                                neighbors.push_back(neighbor);\n                            }\n                        }\n                        if(!neighbors.empty()){\n                           uniform_int_distribution<> neighbor_dist(0, neighbors.size() - 1);\n                           p.placements[m] = neighbors[neighbor_dist(rng)];\n                        }\n                    } else {\n                        uniform_int_distribution<> p_dist(0, prob.valid_placements[m].size() - 1);\n                        p.placements[m] = prob.valid_placements[m][p_dist(rng)];\n                    }\n                }\n            }\n            for(const auto& [shape_coords, indices] : prob.identical_shapes) {\n                if (indices.size() > 1 && r_dist(rng) < 0.1) {\n                    uniform_int_distribution<int> idx_dist(0, indices.size() - 1);\n                    int m1_idx = idx_dist(rng);\n                    int m2_idx = idx_dist(rng);\n                    if (m1_idx == m2_idx) continue;\n                    swap(p.placements[indices[m1_idx]], p.placements[indices[m2_idx]]);\n                }\n            }\n        }\n\n        particles = new_particles;\n        for (auto& p : particles) p.compute_v_grid(prob);\n        weights.assign(num_particles, 1.0 / num_particles);\n    }\n    \n    vector<vector<double>> calculate_p_grid() {\n        vector<vector<double>> p_grid(prob.N, vector<double>(prob.N, 0.0));\n        for (const auto& p : particles) {\n            for (int i = 0; i < prob.N; ++i) {\n                for (int j = 0; j < prob.N; ++j) {\n                    if (p.v_grid[i][j] > 0) {\n                        p_grid[i][j] += 1.0;\n                    }\n                }\n            }\n        }\n        for (int i = 0; i < prob.N; ++i) {\n            for (int j = 0; j < prob.N; ++j) {\n                p_grid[i][j] /= num_particles;\n            }\n        }\n        return p_grid;\n    }\n\n    void make_final_guess() {\n        auto p_grid = calculate_p_grid();\n        \n        vector<Point> guess;\n        for (int i = 0; i < prob.N; ++i) {\n            for (int j = 0; j < prob.N; ++j) {\n                if (known_v[i][j] != -1) {\n                    if (known_v[i][j] > 0) {\n                        guess.push_back({i, j});\n                    }\n                } else {\n                    if (p_grid[i][j] > 0.5) {\n                        guess.push_back({i, j});\n                    }\n                }\n            }\n        }\n        \n        cout << \"a \" << guess.size();\n        for (const auto& p : guess) {\n            cout << \" \" << p.first << \" \" << p.second;\n        }\n        cout << endl;\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M;\n    double epsilon;\n    cin >> N >> M >> epsilon;\n\n    vector<Polyomino> fields(M);\n    for (int i = 0; i < M; ++i) {\n        fields[i].id = i;\n        cin >> fields[i].d;\n        fields[i].coords.resize(fields[i].d);\n        for (int j = 0; j < fields[i].d; ++j) {\n            cin >> fields[i].coords[j].first >> fields[i].coords[j].second;\n        }\n    }\n    \n    int K = 2000;\n    if (N <= 12) K = 1000;\n    if (M >= 15) K = 3000;\n\n    Solver solver(N, M, epsilon, fields, K);\n    solver.solve();\n\n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n#include <functional>\n\nusing namespace std;\n\n// Constants\nconstexpr int W = 1000;\nint D, N;\n\n// Structures\nstruct Rect {\n    int r0, c0, r1, c1;\n    long long area() const {\n        return (long long)(r1 - r0) * (c1 - c0);\n    }\n};\n\nstruct Node {\n    bool is_leaf;\n    int k_min, k_max; // range of reservation indices\n    Node *left = nullptr, *right = nullptr;\n    Node *parent = nullptr;\n\n    // For internal nodes\n    bool is_vertical_split;\n    int split_idx;\n\n    // For leaf nodes\n    int k;\n};\n\n// Globals\nvector<vector<long long>> a;\nvector<Node> tree_nodes;\nint node_idx_counter;\nvector<Rect> current_rects;\nvector<int> split_coords;\nvector<Node*> split_idx_to_node;\n\nvector<vector<bool>> h_prev_exists, v_prev_exists;\nvector<vector<int>> h_curr_count, v_curr_count;\n\n// Randomness\nuint64_t xor_shift() {\n    static uint64_t x = 88172645463325252ULL;\n    x ^= x << 13;\n    x ^= x >> 7;\n    x ^= x << 17;\n    return x;\n}\n\nint rand_int(int min_val, int max_val) {\n    if (min_val > max_val) return min_val;\n    return min_val + xor_shift() % (max_val - min_val + 1);\n}\n\ndouble rand_double() {\n    return (double)xor_shift() / UINT64_MAX;\n}\n\n// Tree building\nNode* build_tree(int k_min, int k_max, const Rect& region) {\n    Node* node = &tree_nodes[node_idx_counter++];\n    node->k_min = k_min;\n    node->k_max = k_max;\n\n    if (k_max - k_min == 1) {\n        node->is_leaf = true;\n        node->k = k_min;\n        return node;\n    }\n\n    node->is_leaf = false;\n    int k_mid = k_min + (k_max - k_min) / 2;\n    \n    node->is_vertical_split = (region.c1 - region.c0 >= region.r1 - region.r0);\n    \n    Rect left_region, right_region;\n    if (node->is_vertical_split) {\n        int c_split = region.c0 + (region.c1 - region.c0) / 2;\n        left_region = {region.r0, region.c0, region.r1, c_split};\n        right_region = {region.r0, c_split, region.r1, region.c1};\n    } else {\n        int r_split = region.r0 + (region.r1 - region.r0) / 2;\n        left_region = {region.r0, region.c0, r_split, region.c1};\n        right_region = {r_split, region.c0, region.r1, region.c1};\n    }\n    \n    node->left = build_tree(k_min, k_mid, left_region);\n    node->left->parent = node;\n    node->right = build_tree(k_mid, k_max, right_region);\n    node->right->parent = node;\n    return node;\n}\n\nvoid assign_split_indices(Node* node, int& split_idx_counter) {\n    if (node->is_leaf) return;\n    node->split_idx = split_idx_counter++;\n    split_idx_to_node[node->split_idx] = node;\n    assign_split_indices(node->left, split_idx_counter);\n    assign_split_indices(node->right, split_idx_counter);\n}\n\n\n// Layout and cost calculations\nvoid get_rects_from_coords(Node* node, const Rect& region, const vector<int>& coords, vector<Rect>& rects_out) {\n    if (node->is_leaf) {\n        rects_out[node->k] = region;\n        return;\n    }\n\n    int coord = coords[node->split_idx];\n    Rect left_region, right_region;\n\n    if (node->is_vertical_split) {\n        left_region = {region.r0, region.c0, region.r1, coord};\n        right_region = {region.r0, coord, region.r1, region.c1};\n    } else {\n        left_region = {region.r0, region.c0, coord, region.c1};\n        right_region = {coord, region.c0, region.r1, region.c1};\n    }\n    get_rects_from_coords(node->left, left_region, coords, rects_out);\n    get_rects_from_coords(node->right, right_region, coords, rects_out);\n}\n\nvoid get_ideal_coords(Node* node, const Rect& region, int d, vector<int>& coords) {\n    if (node->is_leaf) return;\n    \n    long long total_area_left = 0;\n    for (int k = node->left->k_min; k < node->left->k_max; ++k) total_area_left += a[d][k];\n    \n    long long total_area_right = 0;\n    for (int k = node->right->k_min; k < node->right->k_max; ++k) total_area_right += a[d][k];\n\n    long long total_area_node = total_area_left + total_area_right;\n    if (total_area_node == 0) total_area_node = 1;\n\n    int coord;\n    Rect left_region, right_region;\n    if (node->is_vertical_split) {\n        coord = region.c0 + round((double)(region.c1 - region.c0) * total_area_left / total_area_node);\n        coord = clamp(coord, region.c0 + 1, region.c1 - 1);\n        left_region = {region.r0, region.c0, region.r1, coord};\n        right_region = {region.r0, coord, region.r1, region.c1};\n    } else {\n        coord = region.r0 + round((double)(region.r1 - region.r0) * total_area_left / total_area_node);\n        coord = clamp(coord, region.r0 + 1, region.r1 - 1);\n        left_region = {region.r0, region.c0, coord, region.c1};\n        right_region = {coord, region.c0, region.r1, region.c1};\n    }\n    coords[node->split_idx] = coord;\n    get_ideal_coords(node->left, left_region, d, coords);\n    get_ideal_coords(node->right, right_region, d, coords);\n}\n\nlong long calculate_area_cost(int d, const vector<Rect>& rects) {\n    long long cost = 0;\n    for (int k = 0; k < N; ++k) {\n        cost += 100 * max(0LL, a[d][k] - rects[k].area());\n    }\n    return cost;\n}\n\nvoid populate_partition_counts(const vector<Rect>& rects) {\n    for (int i=1; i<W; ++i) fill(h_curr_count[i].begin(), h_curr_count[i].end(), 0);\n    for (int i=0; i<W; ++i) fill(v_curr_count[i].begin(), v_curr_count[i].end(), 0);\n    \n    for (int k = 0; k < N; ++k) {\n        const auto& r = rects[k];\n        if (r.r0 > 0) for (int c = r.c0; c < r.c1; ++c) h_curr_count[r.r0][c]++;\n        if (r.r1 < W) for (int c = r.c0; c < r.c1; ++c) h_curr_count[r.r1][c]++;\n        if (r.c0 > 0) for (int i = r.r0; i < r.r1; ++i) v_curr_count[i][r.c0]++;\n        if (r.c1 < W) for (int i = r.r0; i < r.r1; ++i) v_curr_count[i][r.c1]++;\n    }\n}\n\nlong long calculate_partition_change_cost_full() {\n    long long cost = 0;\n    for (int i = 1; i < W; ++i) {\n        for (int j = 0; j < W; ++j) {\n            cost += (h_prev_exists[i][j] != (h_curr_count[i][j] > 0));\n        }\n    }\n    for (int i = 0; i < W; ++i) {\n        for (int j = 1; j < W; ++j) {\n            cost += (v_prev_exists[i][j] != (v_curr_count[i][j] > 0));\n        }\n    }\n    return cost;\n}\n\nvoid update_prev_partitions() {\n    for (int i = 1; i < W; ++i) {\n        for (int j = 0; j < W; ++j) {\n            h_prev_exists[i][j] = (h_curr_count[i][j] > 0);\n        }\n    }\n    for (int i = 0; i < W; ++i) {\n        for (int j = 1; j < W; ++j) {\n            v_prev_exists[i][j] = (v_curr_count[i][j] > 0);\n        }\n    }\n}\n\n// Main logic\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int W_in;\n    cin >> W_in >> D >> N; \n    a.resize(D, vector<long long>(N));\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            cin >> a[d][k];\n        }\n    }\n\n    tree_nodes.resize(2 * N);\n    node_idx_counter = 0;\n    split_idx_to_node.resize(N - 1);\n    Node* root = build_tree(0, N, {0, 0, W, W});\n    int split_idx_counter = 0;\n    assign_split_indices(root, split_idx_counter);\n\n    current_rects.resize(N);\n    split_coords.resize(N - 1);\n    \n    h_prev_exists.resize(W + 1, vector<bool>(W + 1, false));\n    v_prev_exists.resize(W + 1, vector<bool>(W + 1, false));\n    h_curr_count.resize(W + 1, vector<int>(W + 1, 0));\n    v_curr_count.resize(W + 1, vector<int>(W + 1, 0));\n\n    // Day 0\n    get_ideal_coords(root, {0, 0, W, W}, 0, split_coords);\n    get_rects_from_coords(root, {0, 0, W, W}, split_coords, current_rects);\n    populate_partition_counts(current_rects);\n    update_prev_partitions();\n\n    vector<vector<Rect>> solution(D, vector<Rect>(N));\n    solution[0] = current_rects;\n\n    auto global_start_time = chrono::high_resolution_clock::now();\n\n    // Day 1 to D-1\n    for (int d = 1; d < D; ++d) {\n        get_rects_from_coords(root, {0, 0, W, W}, split_coords, current_rects);\n        populate_partition_counts(current_rects);\n        \n        long long current_area_cost = calculate_area_cost(d, current_rects);\n        long long partition_change_cost = calculate_partition_change_cost_full();\n        long long current_total_cost = current_area_cost + partition_change_cost;\n        \n        vector<int> best_coords = split_coords;\n        long long best_total_cost = current_total_cost;\n        \n        auto day_start_time = chrono::high_resolution_clock::now();\n        double time_limit_per_day = (2950.0 - chrono::duration_cast<chrono::milliseconds>(day_start_time - global_start_time).count()) / (D - d);\n\n        double temp = 5000;\n        int iter = 0;\n        while (true) {\n            iter++;\n            if (iter % 128 == 0) {\n                 auto now = chrono::high_resolution_clock::now();\n                 double elapsed = chrono::duration_cast<chrono::milliseconds>(now - day_start_time).count();\n                 if (elapsed > time_limit_per_day) break;\n            }\n            temp *= 0.9999;\n\n            int split_to_change = rand_int(0, N - 2);\n            Node* target_node = split_idx_to_node[split_to_change];\n            \n            Rect split_region = {0, 0, W, W};\n            Node* temp_node = target_node;\n            while(temp_node->parent != nullptr) {\n                Node* p = temp_node->parent;\n                int p_coord = split_coords[p->split_idx];\n                if (p->is_vertical_split) {\n                    if (temp_node == p->left) split_region.c1 = min(split_region.c1, p_coord);\n                    else split_region.c0 = max(split_region.c0, p_coord);\n                } else {\n                    if (temp_node == p->left) split_region.r1 = min(split_region.r1, p_coord);\n                    else split_region.r0 = max(split_region.r0, p_coord);\n                }\n                temp_node = p;\n            }\n\n            int old_coord = split_coords[split_to_change];\n            int range_min, range_max;\n            if (target_node->is_vertical_split) {\n                range_min = split_region.c0 + 1; range_max = split_region.c1 - 1;\n            } else {\n                range_min = split_region.r0 + 1; range_max = split_region.r1 - 1;\n            }\n            if (range_min >= range_max) continue;\n\n            int move_range = max(1, (int)((range_max - range_min) * 0.1 * temp / 5000.0));\n            int new_coord = old_coord + rand_int(-move_range, move_range);\n            new_coord = clamp(new_coord, range_min, range_max);\n            \n            if (new_coord == old_coord) continue;\n\n            vector<Rect> new_subtree_rects(N);\n            vector<int> next_coords = split_coords;\n            next_coords[split_to_change] = new_coord;\n\n            std::function<void(Node*, Rect)> compute_subtree_rects = \n                [&](Node* node, Rect region) {\n                    if (node->is_leaf) {\n                        new_subtree_rects[node->k] = region;\n                        return;\n                    }\n                    int coord = next_coords[node->split_idx];\n                    Rect left_region, right_region;\n                    if (node->is_vertical_split) {\n                        left_region = {region.r0, region.c0, region.r1, coord};\n                        right_region = {region.r0, coord, region.r1, region.c1};\n                    } else {\n                        left_region = {region.r0, region.c0, coord, region.c1};\n                        right_region = {coord, region.c0, region.r1, region.c1};\n                    }\n                    compute_subtree_rects(node->left, left_region);\n                    compute_subtree_rects(node->right, right_region);\n            };\n            compute_subtree_rects(target_node, split_region);\n\n            long long area_cost_delta = 0;\n            for(int k=target_node->k_min; k<target_node->k_max; ++k) {\n                area_cost_delta -= 100 * max(0LL, a[d][k] - current_rects[k].area());\n                area_cost_delta += 100 * max(0LL, a[d][k] - new_subtree_rects[k].area());\n            }\n\n            long long partition_cost_delta = 0;\n            if (target_node->is_vertical_split) {\n                for (int i = split_region.r0; i < split_region.r1; ++i) {\n                    partition_cost_delta -= (v_prev_exists[i][old_coord] != (v_curr_count[i][old_coord] > 0));\n                    v_curr_count[i][old_coord]--;\n                    partition_cost_delta += (v_prev_exists[i][old_coord] != (v_curr_count[i][old_coord] > 0));\n                    partition_cost_delta -= (v_prev_exists[i][new_coord] != (v_curr_count[i][new_coord] > 0));\n                    v_curr_count[i][new_coord]++;\n                    partition_cost_delta += (v_prev_exists[i][new_coord] != (v_curr_count[i][new_coord] > 0));\n                }\n            } else {\n                for (int j = split_region.c0; j < split_region.c1; ++j) {\n                    partition_cost_delta -= (h_prev_exists[old_coord][j] != (h_curr_count[old_coord][j] > 0));\n                    h_curr_count[old_coord][j]--;\n                    partition_cost_delta += (h_prev_exists[old_coord][j] != (h_curr_count[old_coord][j] > 0));\n                    partition_cost_delta -= (h_prev_exists[new_coord][j] != (h_curr_count[new_coord][j] > 0));\n                    h_curr_count[new_coord][j]++;\n                    partition_cost_delta += (h_prev_exists[new_coord][j] != (h_curr_count[new_coord][j] > 0));\n                }\n            }\n\n            long long cost_delta = area_cost_delta + partition_cost_delta;\n\n            if (cost_delta < 0 || (temp > 1 && rand_double() < exp(-(double)cost_delta / temp))) {\n                current_total_cost += cost_delta;\n                split_coords[split_to_change] = new_coord;\n                for(int k=target_node->k_min; k<target_node->k_max; ++k) {\n                    current_rects[k] = new_subtree_rects[k];\n                }\n                \n                if (current_total_cost < best_total_cost) {\n                    best_total_cost = current_total_cost;\n                    best_coords = split_coords;\n                }\n            } else { // revert counts\n                if (target_node->is_vertical_split) {\n                    for (int i = split_region.r0; i < split_region.r1; ++i) {\n                        v_curr_count[i][old_coord]++; v_curr_count[i][new_coord]--;\n                    }\n                } else {\n                    for (int j = split_region.c0; j < split_region.c1; ++j) {\n                        h_curr_count[old_coord][j]++; h_curr_count[new_coord][j]--;\n                    }\n                }\n            }\n        }\n        \n        split_coords = best_coords;\n        get_rects_from_coords(root, {0, 0, W, W}, split_coords, current_rects);\n        solution[d] = current_rects;\n        populate_partition_counts(current_rects);\n        update_prev_partitions();\n    }\n\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            const auto& r = solution[d][k];\n            cout << r.r0 << \" \" << r.c0 << \" \" << r.r1 << \" \" << r.c1 << \"\\n\";\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <optional>\n#include <map>\n#include <cmath>\n#include <array>\n\n// --- Constants ---\nconstexpr int N = 9;\nconstexpr int M = 20;\nconstexpr int K = 81;\nconstexpr long long P = 998244353;\nconstexpr int MAX_POS_COORD = N - 3; // 0 to N-3 inclusive\n\n// --- Type Definitions ---\nusing Board = std::vector<std::vector<long long>>;\nusing Stamp = std::vector<std::vector<long long>>;\n\nstruct Operation {\n    int m, p, q;\n};\n\n// --- Global Variables ---\nstd::vector<Stamp> stamps(M, Stamp(3, std::vector<long long>(3)));\nBoard initial_board(N, std::vector<long long>(N));\n\n// --- Randomness ---\nstd::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// --- Timer ---\nstd::chrono::steady_clock::time_point start_time;\n\n// --- Utility Functions ---\nlong long current_time_ms() {\n    return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count();\n}\n\nlong long positive_modulo(long long i, long long n) {\n    return (i % n + n) % n;\n}\n\nBoard apply_operations(const std::vector<Operation>& ops) {\n    Board current_board = initial_board;\n    for (const auto& op : ops) {\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                current_board[op.p + i][op.q + j] += stamps[op.m][i][j];\n            }\n        }\n    }\n    return current_board;\n}\n\nlong long calculate_score(const Board& board) {\n    long long score = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            score += positive_modulo(board[i][j], P);\n        }\n    }\n    return score;\n}\n\n\n// --- Greedy Algorithm ---\nstd::vector<Operation> greedy_solution() {\n    std::vector<Operation> ops;\n    Board current_board = initial_board;\n    \n    for (int k = 0; k < K; ++k) {\n        long long best_delta_score = 0;\n        std::optional<Operation> best_op;\n        \n        for (int m = 0; m < M; ++m) {\n            for (int p = 0; p <= MAX_POS_COORD; ++p) {\n                for (int q = 0; q <= MAX_POS_COORD; ++q) {\n                    long long current_delta_score = 0;\n                    for (int i = 0; i < 3; ++i) {\n                        for (int j = 0; j < 3; ++j) {\n                            long long old_val = current_board[p + i][q + j];\n                            long long new_val = old_val + stamps[m][i][j];\n                            current_delta_score += (new_val % P) - (old_val % P);\n                        }\n                    }\n                    \n                    if (current_delta_score > best_delta_score) {\n                        best_delta_score = current_delta_score;\n                        best_op = {m, p, q};\n                    }\n                }\n            }\n        }\n        \n        if (best_op) {\n            ops.push_back(*best_op);\n            for (int i = 0; i < 3; ++i) {\n                for (int j = 0; j < 3; ++j) {\n                    current_board[best_op->p + i][best_op->q + j] += stamps[best_op->m][i][j];\n                }\n            }\n        } else {\n            break; \n        }\n    }\n    \n    return ops;\n}\n\n// --- Simulated Annealing ---\nvoid simulated_annealing(std::vector<Operation>& solution) {\n    long long time_limit = 1950;\n    \n    Board current_board = apply_operations(solution);\n    long long current_score = calculate_score(current_board);\n    \n    std::vector<Operation> best_solution = solution;\n    long long best_score = current_score;\n    \n    double start_temp = 5e9;\n    double end_temp = 10;\n    \n    std::array<long long, N * N> deltas{};\n    std::vector<int> dirty_keys;\n    dirty_keys.reserve(18);\n\n    while (true) {\n        long long elapsed_time = current_time_ms();\n        if (elapsed_time >= time_limit) {\n            break;\n        }\n        \n        double progress = static_cast<double>(elapsed_time) / time_limit;\n        double temp = start_temp * std::pow(end_temp / start_temp, progress);\n\n        int r = std::uniform_int_distribution<>(0, 99)(rng);\n        int move_type; // 0: change, 1: add, 2: remove\n        int op_count = solution.size();\n\n        if (op_count == K) {\n            if (r < 80) move_type = 0; else move_type = 2;\n        } else if (op_count == 0) {\n            move_type = 1;\n        } else {\n            if (r < 70) move_type = 0;\n            else if (r < 90) move_type = 1;\n            else move_type = 2;\n        }\n        \n        std::optional<Operation> old_op, new_op;\n        int op_idx = -1;\n        \n        if (move_type == 0) { // Change\n            op_idx = std::uniform_int_distribution<int>(0, solution.size() - 1)(rng);\n            old_op = solution[op_idx];\n            \n            int change_type_r = std::uniform_int_distribution<>(0, 99)(rng);\n            if (change_type_r < 45) { // change position\n                Operation candidate = *old_op;\n                do {\n                    candidate.p = std::uniform_int_distribution<int>(0, MAX_POS_COORD)(rng);\n                    candidate.q = std::uniform_int_distribution<int>(0, MAX_POS_COORD)(rng);\n                } while (candidate.p == old_op->p && candidate.q == old_op->q);\n                new_op = candidate;\n            } else if (change_type_r < 90) { // change stamp\n                Operation candidate = *old_op;\n                do {\n                    candidate.m = std::uniform_int_distribution<int>(0, M - 1)(rng);\n                } while (candidate.m == old_op->m);\n                new_op = candidate;\n            } else { // change both\n                new_op = {\n                    std::uniform_int_distribution<int>(0, M - 1)(rng),\n                    std::uniform_int_distribution<int>(0, MAX_POS_COORD)(rng),\n                    std::uniform_int_distribution<int>(0, MAX_POS_COORD)(rng)\n                };\n            }\n        } else if (move_type == 1) { // Add\n            new_op = {\n                std::uniform_int_distribution<int>(0, M - 1)(rng),\n                std::uniform_int_distribution<int>(0, MAX_POS_COORD)(rng),\n                std::uniform_int_distribution<int>(0, MAX_POS_COORD)(rng)\n            };\n        } else { // Remove\n            op_idx = std::uniform_int_distribution<int>(0, solution.size() - 1)(rng);\n            old_op = solution[op_idx];\n        }\n\n        if (old_op) {\n            for (int i = 0; i < 3; ++i) {\n                for (int j = 0; j < 3; ++j) {\n                    int key = (old_op->p + i) * N + old_op->q + j;\n                    if (deltas[key] == 0) dirty_keys.push_back(key);\n                    deltas[key] -= stamps[old_op->m][i][j];\n                }\n            }\n        }\n        if (new_op) {\n            for (int i = 0; i < 3; ++i) {\n                for (int j = 0; j < 3; ++j) {\n                    int key = (new_op->p + i) * N + new_op->q + j;\n                    if (deltas[key] == 0) dirty_keys.push_back(key);\n                    deltas[key] += stamps[new_op->m][i][j];\n                }\n            }\n        }\n        \n        long long delta_score = 0;\n        for (int key : dirty_keys) {\n            long long old_val = current_board[key / N][key % N];\n            long long new_val = old_val + deltas[key];\n            delta_score += positive_modulo(new_val, P) - positive_modulo(old_val, P);\n        }\n        \n        if (delta_score > 0 || std::uniform_real_distribution<>(0.0, 1.0)(rng) < std::exp(static_cast<double>(delta_score) / temp)) {\n            current_score += delta_score;\n            for (int key : dirty_keys) {\n                current_board[key / N][key % N] += deltas[key];\n            }\n            \n            if (move_type == 0) {\n                solution[op_idx] = *new_op;\n            } else if (move_type == 1) {\n                solution.push_back(*new_op);\n            } else {\n                solution.erase(solution.begin() + op_idx);\n            }\n            \n            if (current_score > best_score) {\n                best_score = current_score;\n                best_solution = solution;\n            }\n        }\n        \n        for (int key : dirty_keys) {\n            deltas[key] = 0;\n        }\n        dirty_keys.clear();\n    }\n    \n    solution = best_solution;\n}\n\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    start_time = std::chrono::steady_clock::now();\n    \n    int n_dummy, m_dummy, k_dummy;\n    std::cin >> n_dummy >> m_dummy >> k_dummy;\n    \n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            std::cin >> initial_board[i][j];\n        }\n    }\n    \n    for (int m = 0; m < M; ++m) {\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                std::cin >> stamps[m][i][j];\n            }\n        }\n    }\n    \n    auto solution = greedy_solution();\n    simulated_annealing(solution);\n    \n    std::cout << solution.size() << std::endl;\n    for (const auto& op : solution) {\n        std::cout << op.m << \" \" << op.p << \" \" << op.q << std::endl;\n    }\n    \n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <map>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nconst int N = 5;\nconst int MAX_TURNS = 10000;\n\nstruct Pos {\n    int r, c;\n    bool operator==(const Pos& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Pos& other) const {\n        return !(*this == other);\n    }\n    bool operator<(const Pos& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n};\n\nenum TaskType {\n    NONE,\n    MOVE_TO_PARK,\n    UNLOAD,\n    SORT,\n    DISPATCH\n};\n\nstruct Task {\n    TaskType type = NONE;\n    int container_id = -1;\n    Pos from;\n    Pos to;\n};\n\nstruct Crane {\n    int id;\n    Pos pos;\n    int payload = -1;\n    Task task;\n    bool bombed = false;\n};\n\nint grid[N][N];\nPos container_pos[N * N];\nCrane cranes[N];\nint arrival_idx[N];\nint dispatch_next[N];\nvector<string> history(N);\n\nvoid init() {\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            grid[i][j] = -1;\n        }\n    }\n    for (int i = 0; i < N * N; ++i) {\n        container_pos[i] = {-1, -1};\n    }\n    for (int i = 0; i < N; ++i) {\n        cranes[i].id = i;\n        cranes[i].pos = {i, 0};\n        arrival_idx[i] = 0;\n        dispatch_next[i] = N * i;\n    }\n}\n\nvoid apply_actions(const string& actions) {\n    for (int i = 0; i < N; ++i) {\n        history[i] += actions[i];\n    }\n    \n    // Update payload first\n    for (int i = 0; i < N; ++i) {\n        char act = actions[i];\n        if (act == 'P') {\n            cranes[i].payload = grid[cranes[i].pos.r][cranes[i].pos.c];\n            grid[cranes[i].pos.r][cranes[i].pos.c] = -1;\n        } else if (act == 'Q') {\n            grid[cranes[i].pos.r][cranes[i].pos.c] = cranes[i].payload;\n            container_pos[cranes[i].payload] = cranes[i].pos;\n            cranes[i].payload = -1;\n        } else if (act == 'B') {\n            cranes[i].bombed = true;\n        }\n    }\n\n    // Update positions\n    for (int i = 0; i < N; ++i) {\n        char act = actions[i];\n        if (act == 'U') cranes[i].pos.r--;\n        else if (act == 'D') cranes[i].pos.r++;\n        else if (act == 'L') cranes[i].pos.c--;\n        else if (act == 'R') cranes[i].pos.c++;\n    }\n}\n\nPos get_next_pos(Pos current, char action) {\n    if (action == 'U') return {current.r - 1, current.c};\n    if (action == 'D') return {current.r + 1, current.c};\n    if (action == 'L') return {current.r, current.c - 1};\n    if (action == 'R') return {current.r, current.c + 1};\n    return current;\n}\n\nchar get_move_action(Pos from, Pos to) {\n    if (from.r < to.r) return 'D';\n    if (from.r > to.r) return 'U';\n    if (from.c < to.c) return 'R';\n    if (from.c > to.c) return 'L';\n    return '.';\n}\n\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n_dummy;\n    cin >> n_dummy;\n    vector<vector<int>> A(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> A[i][j];\n        }\n    }\n\n    init();\n\n    int dispatched_count = 0;\n\n    for (int t = 0; t < MAX_TURNS; ++t) {\n        if (dispatched_count == N * N) break;\n\n        // 1. Containers arrive\n        for (int i = 0; i < N; ++i) {\n            if (arrival_idx[i] < N && grid[i][0] == -1) {\n                int new_container = A[i][arrival_idx[i]];\n                grid[i][0] = new_container;\n                container_pos[new_container] = {i, 0};\n                arrival_idx[i]++;\n            }\n        }\n\n        // 2. Crane actions\n        \n        // Task assignment\n        for (int i = 0; i < N; ++i) {\n            if (cranes[i].task.type != NONE && cranes[i].payload == -1 && container_pos[cranes[i].task.container_id].r == -1) {\n                 cranes[i].task.type = NONE;\n            }\n            if (cranes[i].task.type == NONE) {\n                if (i == 0) { // Large crane\n                    int c_to_dispatch = dispatch_next[0];\n                    if (c_to_dispatch < N && grid[0][N - 1] == -1 && container_pos[c_to_dispatch].r != -1) {\n                        Pos c_pos = container_pos[c_to_dispatch];\n                        if(c_pos.r == 0 && c_pos.c == 3) {\n                           cranes[i].task = {DISPATCH, c_to_dispatch, c_pos, {0, N - 1}};\n                        }\n                    }\n                    if (cranes[i].task.type == NONE) {\n                        for (int r = 0; r < N; ++r) {\n                            if (grid[r][0] != -1 && grid[r][1] == -1) {\n                                int c = grid[r][0];\n                                cranes[i].task = {UNLOAD, c, {r, 0}, {r, 1}};\n                                break;\n                            }\n                        }\n                    }\n                    if (cranes[i].task.type == NONE) {\n                        for (int r = 0; r < N; ++r) {\n                            if (grid[r][1] != -1) {\n                                int c = grid[r][1];\n                                int dest_r = c / N;\n                                if (grid[dest_r][3] == -1) {\n                                    cranes[i].task = {SORT, c, {r, 1}, {dest_r, 3}};\n                                    break;\n                                }\n                            }\n                        }\n                    }\n                } else { // Small cranes\n                    int c_to_dispatch = dispatch_next[i];\n                    if (c_to_dispatch < N * (i + 1) && grid[i][N - 1] == -1 && container_pos[c_to_dispatch].r != -1) {\n                        Pos c_pos = container_pos[c_to_dispatch];\n                        if (c_pos.r == i && c_pos.c == 3) {\n                           cranes[i].task = {DISPATCH, c_to_dispatch, c_pos, {i, N-1}};\n                        }\n                    }\n                    if (cranes[i].task.type == NONE) {\n                        if (cranes[i].pos != Pos{i, 2}) {\n                           cranes[i].task.type = MOVE_TO_PARK;\n                           cranes[i].task.to = {i,2};\n                        }\n                    }\n                }\n            }\n        }\n        \n        string actions(N, '.');\n        vector<Pos> next_pos(N);\n        for(int i=0; i<N; ++i) next_pos[i] = cranes[i].pos;\n        \n        for(int iter=0; iter<5; ++iter) { // Iteratively resolve conflicts\n            vector<Pos> current_next_pos(N);\n            for(int i=0; i<N; ++i) current_next_pos[i] = get_next_pos(cranes[i].pos, actions[i]);\n\n            string planned_actions = actions;\n\n            // --- Action planning for each crane, considering current state of others ---\n            for (int k = 0; k < N; ++k) {\n                if(cranes[k].bombed) { planned_actions[k] = '.'; continue;}\n\n                char best_action = '.';\n                Task& task = cranes[k].task;\n\n                if (t < 2 && k > 0) {\n                    best_action = 'R';\n                } else if (task.type != NONE) {\n                    if (cranes[k].payload != -1) {\n                        if (cranes[k].pos == task.to) {\n                            best_action = 'Q';\n                            task.type = NONE; \n                        } else {\n                            Pos target = task.to;\n                            if (k == 0 && cranes[k].pos.c != 1 && cranes[k].pos.c != target.c) {\n                                target = {cranes[k].pos.r, 1};\n                            } else if (k == 0 && cranes[k].pos.c == 1 && cranes[k].pos.r != target.r) {\n                                target = {target.r, 1};\n                            }\n                            best_action = get_move_action(cranes[k].pos, target);\n                        }\n                    } else {\n                        if (task.type == MOVE_TO_PARK) {\n                             if (cranes[k].pos == task.to) {\n                                task.type = NONE;\n                                best_action = '.';\n                             } else {\n                                best_action = get_move_action(cranes[k].pos, task.to);\n                             }\n                        } else if (cranes[k].pos == task.from) {\n                            if (grid[task.from.r][task.from.c] == task.container_id){\n                               best_action = 'P';\n                            } else {\n                               task.type = NONE;\n                            }\n                        } else {\n                            Pos target = task.from;\n                            if (k == 0 && cranes[k].pos.c != 1 && cranes[k].pos.c != target.c) {\n                                target = {cranes[k].pos.r, 1};\n                            } else if (k == 0 && cranes[k].pos.c == 1 && cranes[k].pos.r != target.r) {\n                                target = {target.r, 1};\n                            }\n                            best_action = get_move_action(cranes[k].pos, target);\n                        }\n                    }\n                }\n                planned_actions[k] = best_action;\n            }\n\n            // --- Conflict resolution with priorities ---\n            actions = planned_actions;\n            for(int i=0; i<N; ++i) next_pos[i] = get_next_pos(cranes[i].pos, actions[i]);\n            \n            // Evasion\n            Pos np0 = next_pos[0];\n            for (int j=1; j<N; ++j) {\n                if (np0 == cranes[j].pos && cranes[j].pos == next_pos[j]) { // Crane 0 wants to move into stationary Crane j\n                    // j must evade\n                    char original_action_j = actions[j];\n                    actions[j] = '.';\n                    Pos evade_targets[] = {{cranes[j].pos.r, 1}, {cranes[j].pos.r - 1, 2}, {cranes[j].pos.r + 1, 2}};\n                    for(const Pos& evade_pos : evade_targets) {\n                        if (evade_pos.r < 0 || evade_pos.r >= N || evade_pos.c < 0 || evade_pos.c >= N) continue;\n                        \n                        bool pos_ok = true;\n                        if (evade_pos == np0) pos_ok = false;\n                        for(int k=0; k<N; ++k) if(k!=j && evade_pos == cranes[k].pos) pos_ok = false;\n                        \n                        if(pos_ok) {\n                            actions[j] = get_move_action(cranes[j].pos, evade_pos);\n                            break;\n                        }\n                    }\n                    if (actions[j] == '.') { // could not evade\n                        actions[0] = '.'; // crane 0 waits\n                        actions[j] = original_action_j;\n                    }\n                }\n            }\n\n            for(int i=0; i<N; ++i) next_pos[i] = get_next_pos(cranes[i].pos, actions[i]);\n\n            // General collision\n            for (int i = 0; i < N; ++i) {\n                for (int j = i + 1; j < N; ++j) {\n                    if (next_pos[i] == next_pos[j] || (next_pos[i] == cranes[j].pos && next_pos[j] == cranes[i].pos)) {\n                        actions[j] = '.';\n                        next_pos[j] = cranes[j].pos;\n                    }\n                }\n            }\n\n            // Small crane payload constraints\n            for(int i=1; i<N; ++i) {\n                if (cranes[i].payload != -1) {\n                    Pos np = get_next_pos(cranes[i].pos, actions[i]);\n                    if (np.r < 0 || np.r >= N || np.c < 0 || np.c >= N) {\n                        actions[i] = '.';\n                        continue;\n                    }\n                    for(int c=0; c<N*N; ++c) {\n                        if (container_pos[c] == np) {\n                            actions[i] = '.';\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n\n        // Bomb cranes whose jobs are done\n        for(int i=1; i<N; ++i){\n            if(dispatch_next[i] >= N*(i+1) && cranes[i].payload == -1 && !cranes[i].bombed) {\n                actions[i] = 'B';\n            }\n        }\n        \n        apply_actions(actions);\n        \n        // 3. Containers are dispatched\n        for (int i = 0; i < N; ++i) {\n            if (grid[i][N - 1] != -1) {\n                int dispatched_container = grid[i][N - 1];\n                if (dispatched_container / N == i) {\n                    if (dispatch_next[i] == dispatched_container)\n                        dispatch_next[i]++;\n                }\n                grid[i][N - 1] = -1;\n                container_pos[dispatched_container] = {-1, -1};\n                dispatched_count++;\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << history[i] << endl;\n    }\n\n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <cmath>\n#include <map>\n#include <algorithm>\n#include <chrono>\n#include <random>\n\n#include <atcoder/mincostflow>\n\nusing namespace std;\n\n// --- Utilities ---\nstruct XorShift {\n    unsigned int x, y, z, w;\n    XorShift() : x(123456789), y(362436069), z(521288629), w(88675123) {}\n    unsigned int next() {\n        unsigned int t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));\n    }\n    int next_int(int upper) { return next() % upper; }\n    int next_int(int lower, int upper) { return lower + next() % (upper - lower + 1); }\n    double next_double() { return next() / 4294967295.0; }\n};\nXorShift rnd;\n\nauto start_time = chrono::steady_clock::now();\ndouble time_limit = 1.95;\n\nbool is_time_up() {\n    auto now = chrono::steady_clock::now();\n    double elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count() / 1000.0;\n    return elapsed > time_limit;\n}\n\n// --- Problem specific structures ---\nconst int N = 20;\n\nstruct Pos {\n    int r, c;\n};\n\nint manhattan_dist(const Pos& p1, const Pos& p2) {\n    return abs(p1.r - p2.r) + abs(p1.c - p2.c);\n}\n\nvector<Pos> sources, sinks;\nvector<int> source_supply, sink_demand;\n\nusing Plan = vector<vector<int>>;\n\n// --- Core Logic ---\n\nlong long calculate_tour_cost(Pos start_pos, int initial_load, const vector<pair<int, int>>& tour, vector<string>* ops = nullptr) {\n    long long cost = 0;\n    Pos current_pos = start_pos;\n    int truck_load = initial_load;\n\n    for (const auto& stop : tour) {\n        int t_idx = stop.first;\n        int amount = stop.second;\n        Pos t_pos = sinks[t_idx];\n        \n        int dist = manhattan_dist(current_pos, t_pos);\n        cost += (long long)dist * (100 + truck_load);\n\n        if (ops) {\n            int dr = t_pos.r - current_pos.r;\n            int dc = t_pos.c - current_pos.c;\n            if (dr > 0) for(int i=0; i<dr; ++i) ops->push_back(\"D\");\n            if (dr < 0) for(int i=0; i<-dr; ++i) ops->push_back(\"U\");\n            if (dc > 0) for(int i=0; i<dc; ++i) ops->push_back(\"R\");\n            if (dc < 0) for(int i=0; i<-dc; ++i) ops->push_back(\"L\");\n\n            ops->push_back(\"-\" + to_string(amount));\n        }\n\n        cost += amount;\n        truck_load -= amount;\n        current_pos = t_pos;\n    }\n    return cost;\n}\n\nvoid optimize_tour(Pos start_pos, vector<pair<int, int>>& tour) {\n    if (tour.size() <= 1) return;\n\n    auto get_tour_dist = [&](const vector<pair<int, int>>& current_tour) {\n        long long d = 0;\n        Pos current_pos = start_pos;\n        for (const auto& stop : current_tour) {\n            d += manhattan_dist(current_pos, sinks[stop.first]);\n            current_pos = sinks[stop.first];\n        }\n        return d;\n    };\n\n    for(int iter = 0; iter < 2 * tour.size() * tour.size() && iter < 200; ++iter) {\n        int i = rnd.next_int(tour.size());\n        int j = rnd.next_int(tour.size());\n        if (i == j) continue;\n        if (i > j) swap(i, j);\n\n        vector<pair<int, int>> next_tour = tour;\n        reverse(next_tour.begin() + i, next_tour.begin() + j + 1);\n\n        if (get_tour_dist(next_tour) < get_tour_dist(tour)) {\n            tour = next_tour;\n        }\n    }\n}\n\nlong long evaluate(const Plan& plan, vector<string>* ops = nullptr) {\n    if (ops) ops->clear();\n    long long total_cost = 0;\n    Pos current_pos = {0, 0};\n\n    map<int, vector<pair<int, int>>> deliveries_by_source;\n    for (size_t s_idx = 0; s_idx < sources.size(); ++s_idx) {\n        for (size_t t_idx = 0; t_idx < sinks.size(); ++t_idx) {\n            if (plan[s_idx][t_idx] > 0) {\n                deliveries_by_source[s_idx].push_back({(int)t_idx, plan[s_idx][t_idx]});\n            }\n        }\n    }\n\n    vector<int> active_sources_indices;\n    for (const auto& [s_idx, v] : deliveries_by_source) {\n        active_sources_indices.push_back(s_idx);\n    }\n    \n    while (!active_sources_indices.empty()) {\n        int best_s_idx = -1;\n        int min_dist = 1e9;\n        size_t best_vec_idx = -1;\n\n        for (size_t i = 0; i < active_sources_indices.size(); ++i) {\n            int s_idx = active_sources_indices[i];\n            int d = manhattan_dist(current_pos, sources[s_idx]);\n            if (d < min_dist) {\n                min_dist = d;\n                best_s_idx = s_idx;\n                best_vec_idx = i;\n            }\n        }\n        \n        Pos s_pos = sources[best_s_idx];\n        total_cost += (long long)manhattan_dist(current_pos, s_pos) * 100;\n        \n        if (ops) {\n            int dr = s_pos.r - current_pos.r;\n            int dc = s_pos.c - current_pos.c;\n            if (dr > 0) for(int i=0; i<dr; ++i) ops->push_back(\"D\");\n            if (dr < 0) for(int i=0; i<-dr; ++i) ops->push_back(\"U\");\n            if (dc > 0) for(int i=0; i<dc; ++i) ops->push_back(\"R\");\n            if (dc < 0) for(int i=0; i<-dc; ++i) ops->push_back(\"L\");\n        }\n        current_pos = s_pos;\n\n        int total_load_amount = 0;\n        vector<pair<int, int>> tour_stops; // {t_idx, amount}\n        for (const auto& delivery : deliveries_by_source[best_s_idx]) {\n            total_load_amount += delivery.second;\n            tour_stops.push_back(delivery);\n        }\n\n        total_cost += total_load_amount;\n        if (ops && total_load_amount > 0) {\n            ops->push_back(\"+\" + to_string(total_load_amount));\n        }\n        \n        Pos tour_start_pos = current_pos;\n        vector<pair<int, int>> tour;\n        while (!tour_stops.empty()) {\n            auto best_it = tour_stops.end();\n            int min_dist_t = 1e9;\n            for (auto it = tour_stops.begin(); it != tour_stops.end(); ++it) {\n                int t_idx = it->first;\n                int d = manhattan_dist(current_pos, sinks[t_idx]);\n                if (d < min_dist_t) {\n                    min_dist_t = d;\n                    best_it = it;\n                }\n            }\n            tour.push_back(*best_it);\n            current_pos = sinks[best_it->first];\n            tour_stops.erase(best_it);\n        }\n\n        optimize_tour(tour_start_pos, tour);\n\n        total_cost += calculate_tour_cost(tour_start_pos, total_load_amount, tour, ops);\n        if (!tour.empty()) {\n            current_pos = sinks[tour.back().first];\n        }\n\n        active_sources_indices.erase(active_sources_indices.begin() + best_vec_idx);\n    }\n    return total_cost;\n}\n\nvoid solve() {\n    vector<vector<int>> h(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> h[i][j];\n            if (h[i][j] > 0) {\n                sources.push_back({i, j});\n                source_supply.push_back(h[i][j]);\n            } else if (h[i][j] < 0) {\n                sinks.push_back({i, j});\n                sink_demand.push_back(-h[i][j]);\n            }\n        }\n    }\n    \n    if (sources.empty()) return;\n\n    int num_s = sources.size();\n    int num_t = sinks.size();\n    atcoder::mcf_graph<int, int> g(num_s + num_t + 2);\n    int S_node = num_s + num_t;\n    int T_node = S_node + 1;\n\n    long long total_supply_val = 0;\n    for (int i = 0; i < num_s; ++i) {\n        g.add_edge(S_node, i, source_supply[i], 0);\n        total_supply_val += source_supply[i];\n    }\n    for (int i = 0; i < num_t; ++i) {\n        g.add_edge(num_s + i, T_node, sink_demand[i], 0);\n    }\n    for (int i = 0; i < num_s; ++i) {\n        for (int j = 0; j < num_t; ++j) {\n            g.add_edge(i, num_s + j, 1e9, manhattan_dist(sources[i], sinks[j]));\n        }\n    }\n    \n    g.flow(S_node, T_node, total_supply_val);\n    \n    Plan current_plan(num_s, vector<int>(num_t, 0));\n    for (const auto& e : g.edges()) {\n        if (e.from >= 0 && e.from < num_s && e.to >= num_s && e.to < num_s + num_t) {\n            if (e.flow > 0) {\n                current_plan[e.from][e.to-num_s] = e.flow;\n            }\n        }\n    }\n\n    Plan best_plan = current_plan;\n    long long best_cost = evaluate(best_plan);\n    long long current_cost = best_cost;\n    \n    double start_temp = 5000, end_temp = 10;\n    \n    while (!is_time_up()) {\n        double elapsed_ratio = chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count() / 1000.0 / time_limit;\n        double temp = start_temp * pow(end_temp / start_temp, elapsed_ratio);\n\n        int s1 = rnd.next_int(num_s);\n        int s2 = rnd.next_int(num_s);\n        int t1 = rnd.next_int(num_t);\n        int t2 = rnd.next_int(num_t);\n\n        if (s1 == s2 || t1 == t2) continue;\n        \n        int amount1 = current_plan[s1][t1];\n        int amount2 = current_plan[s2][t2];\n        if (amount1 == 0 || amount2 == 0) continue;\n        \n        int d = rnd.next_int(1, min(amount1, amount2));\n        \n        Plan new_plan = current_plan;\n        new_plan[s1][t1] -= d;\n        new_plan[s2][t2] -= d;\n        new_plan[s1][t2] += d;\n        new_plan[s2][t1] += d;\n\n        long long new_cost = evaluate(new_plan);\n        \n        if (new_cost < current_cost || rnd.next_double() < exp((double)(current_cost - new_cost) / temp)) {\n            current_plan = new_plan;\n            current_cost = new_cost;\n            if (current_cost < best_cost) {\n                best_cost = current_cost;\n                best_plan = current_plan;\n            }\n        }\n    }\n    \n    vector<string> ops;\n    evaluate(best_plan, &ops);\n    for (const auto& op : ops) {\n        cout << op << '\\n';\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    int N_dummy;\n    cin >> N_dummy;\n    solve();\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n#include <random>\n#include <unordered_set>\n\n// --- Constants ---\nconstexpr int N = 6;\nconstexpr int M = 15;\nconstexpr int T = 10;\nconstexpr int SEED_COUNT = 2 * N * (N - 1); // 60\nconstexpr int GRID_SIZE = N * N;             // 36\nconstexpr long long TIME_LIMIT_MS = 190;\n\n// --- Type Definitions ---\nstruct Seed {\n    int id;\n    std::vector<int> x;\n    int total_value;\n};\n\n// --- Global State ---\nstd::vector<Seed> current_seeds;\nstd::mt19937 rng;\nauto turn_start_time = std::chrono::high_resolution_clock::now();\n\n// --- Helper Functions ---\nvoid read_seeds() {\n    current_seeds.assign(SEED_COUNT, Seed());\n    for (int i = 0; i < SEED_COUNT; ++i) {\n        current_seeds[i].id = i;\n        current_seeds[i].x.resize(M);\n        current_seeds[i].total_value = 0;\n        for (int j = 0; j < M; ++j) {\n            std::cin >> current_seeds[i].x[j];\n            current_seeds[i].total_value += current_seeds[i].x[j];\n        }\n    }\n}\n\n// --- Core Logic for a Single Turn ---\nvoid solve_turn() {\n    // 1. REFINED SEED SELECTION: \"Guaranteed Champions\" strategy\n    // This strategy ensures that for every criterion, the seed with the highest value (\"champion\")\n    // is included in the set of seeds to be planted. This maximizes the potential to create a\n    // \"super seed\" that combines the best traits from all available seeds.\n    \n    // Find the champion seed index for each criterion.\n    std::vector<int> champion_indices_all;\n    champion_indices_all.reserve(M);\n    for (int j = 0; j < M; ++j) {\n        int best_seed_idx = -1;\n        int max_val = -1;\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            if (current_seeds[i].x[j] > max_val) {\n                max_val = current_seeds[i].x[j];\n                best_seed_idx = i;\n            }\n        }\n        champion_indices_all.push_back(best_seed_idx);\n    }\n\n    // Get the unique set of champion indices.\n    std::sort(champion_indices_all.begin(), champion_indices_all.end());\n    champion_indices_all.erase(std::unique(champion_indices_all.begin(), champion_indices_all.end()), champion_indices_all.end());\n\n    std::vector<int> seeds_to_plant_indices = champion_indices_all;\n    std::vector<bool> is_selected(SEED_COUNT, false);\n    for (int idx : seeds_to_plant_indices) {\n        is_selected[idx] = true;\n    }\n\n    // Fill the remaining spots with seeds that have the highest total value.\n    if (seeds_to_plant_indices.size() < GRID_SIZE) {\n        std::vector<int> other_indices;\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            if (!is_selected[i]) {\n                other_indices.push_back(i);\n            }\n        }\n        // Sort remaining seeds by total value to pick the best ones.\n        std::sort(other_indices.begin(), other_indices.end(), [&](int a, int b) {\n            return current_seeds[a].total_value > current_seeds[b].total_value;\n        });\n        \n        int needed = GRID_SIZE - seeds_to_plant_indices.size();\n        seeds_to_plant_indices.insert(seeds_to_plant_indices.end(), other_indices.begin(), other_indices.begin() + needed);\n    }\n    // If more than 36 champions, truncate (very unlikely).\n    if (seeds_to_plant_indices.size() > GRID_SIZE) {\n        seeds_to_plant_indices.resize(GRID_SIZE);\n    }\n\n    // 2. PLACEMENT using SIMULATED ANNEALING\n    \n    // Pre-calculate desirability for all pairs of selected seeds to speed up SA.\n    // Desirability aims to maximize the potential of offspring by summing the max values for each criterion.\n    std::vector<std::vector<double>> desirability_cache(GRID_SIZE, std::vector<double>(GRID_SIZE));\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = i; j < GRID_SIZE; ++j) {\n            int seed_idx1 = seeds_to_plant_indices[i];\n            int seed_idx2 = seeds_to_plant_indices[j];\n            double d = 0;\n            for (int k = 0; k < M; ++k) {\n                d += std::max(current_seeds[seed_idx1].x[k], current_seeds[seed_idx2].x[k]);\n            }\n            desirability_cache[i][j] = desirability_cache[j][i] = d;\n        }\n    }\n\n    // Initialize with a random placement to avoid getting stuck in local optima near a sorted configuration.\n    std::vector<int> p_indices(GRID_SIZE);\n    std::iota(p_indices.begin(), p_indices.end(), 0);\n    std::shuffle(p_indices.begin(), p_indices.end(), rng);\n\n    std::vector<std::vector<int>> current_placement(N, std::vector<int>(N));\n    for(int i=0; i<GRID_SIZE; ++i) {\n        current_placement[i/N][i%N] = p_indices[i];\n    }\n    \n    auto calculate_total_desirability = [&](const auto& placement) {\n        double total_d = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (i + 1 < N) total_d += desirability_cache[placement[i][j]][placement[i + 1][j]];\n                if (j + 1 < N) total_d += desirability_cache[placement[i][j]][placement[i][j + 1]];\n            }\n        }\n        return total_d;\n    };\n    \n    double current_desirability = calculate_total_desirability(current_placement);\n    auto best_placement = current_placement;\n    double best_desirability = current_desirability;\n    \n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n\n    // Fast delta calculation for a swap move.\n    auto calculate_delta = [&](int r1, int c1, int r2, int c2) {\n        double delta = 0;\n        int s1_idx = current_placement[r1][c1];\n        int s2_idx = current_placement[r2][c2];\n\n        for (int k=0; k<4; ++k) {\n            int nr = r1 + dr[k], nc = c1 + dc[k];\n            if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n            if (nr == r2 && nc == c2) continue;\n            int neighbor_idx = current_placement[nr][nc];\n            delta += desirability_cache[s2_idx][neighbor_idx] - desirability_cache[s1_idx][neighbor_idx];\n        }\n        for (int k=0; k<4; ++k) {\n            int nr = r2 + dr[k], nc = c2 + dc[k];\n            if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n            if (nr == r1 && nc == c1) continue;\n            int neighbor_idx = current_placement[nr][nc];\n            delta += desirability_cache[s1_idx][neighbor_idx] - desirability_cache[s2_idx][neighbor_idx];\n        }\n        return delta;\n    };\n\n    // Auto-tune starting temperature based on the energy landscape.\n    double T_start = 2000.0, T_end = 0.1;\n    double avg_bad_delta = 0;\n    int bad_move_count = 0;\n    std::uniform_int_distribution<> dis_pos(0, GRID_SIZE - 1);\n    for (int i = 0; i < 200; ++i) {\n        int p1_idx = dis_pos(rng), p2_idx = dis_pos(rng);\n        if (p1_idx == p2_idx) continue;\n        double delta = calculate_delta(p1_idx / N, p1_idx % N, p2_idx / N, p2_idx % N);\n        if (delta < 0) {\n            avg_bad_delta += -delta;\n            bad_move_count++;\n        }\n    }\n    if (bad_move_count > 0) {\n        avg_bad_delta /= bad_move_count;\n        T_start = avg_bad_delta / log(2.0); // Set T so that a move with avg bad delta has ~50% chance\n    }\n\n    std::uniform_real_distribution<double> accept_dis(0.0, 1.0);\n    int iter_count = 0;\n    while (true) {\n        iter_count++;\n        if (iter_count % 1024 == 0) { // Check time periodically\n            auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - turn_start_time).count();\n            if (elapsed > TIME_LIMIT_MS) break;\n        }\n\n        double progress = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - turn_start_time).count() / (double)TIME_LIMIT_MS;\n        if (progress >= 1.0) break;\n        double temp = T_start * std::pow(T_end / T_start, progress);\n\n        int p1_idx = dis_pos(rng), p2_idx = dis_pos(rng);\n        if (p1_idx == p2_idx) continue;\n\n        int r1 = p1_idx / N, c1 = p1_idx % N;\n        int r2 = p2_idx / N, c2 = p2_idx % N;\n        \n        double delta_desirability = calculate_delta(r1, c1, r2, c2);\n        \n        if (delta_desirability > 0 || (temp > 1e-9 && accept_dis(rng) < std::exp(delta_desirability / temp))) {\n            std::swap(current_placement[r1][c1], current_placement[r2][c2]);\n            current_desirability += delta_desirability;\n            if (current_desirability > best_desirability) {\n                best_desirability = current_desirability;\n                best_placement = current_placement;\n            }\n        }\n    }\n\n    // 3. OUTPUT the best placement found.\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int placement_idx = best_placement[i][j];\n            int seed_idx = seeds_to_plant_indices[placement_idx];\n            std::cout << current_seeds[seed_idx].id << (j == N - 1 ? \"\" : \" \");\n        }\n        std::cout << std::endl;\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    rng.seed(std::chrono::steady_clock::now().time_since_epoch().count());\n    \n    int n_in, m_in, t_in;\n    std::cin >> n_in >> m_in >> t_in;\n\n    read_seeds();\n\n    for (int t = 0; t < T; ++t) {\n        turn_start_time = std::chrono::high_resolution_clock::now();\n        solve_turn();\n        if (t < T - 1) {\n            read_seeds();\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <set>\n#include <map>\n#include <tuple>\n#include <chrono>\n\n#include <atcoder/mincostflow>\n\nusing namespace std;\n\n// --- Utilities ---\nstruct Timer {\n    chrono::steady_clock::time_point start_time;\n    Timer() {\n        start_time = chrono::steady_clock::now();\n    }\n    double get_elapsed_time() {\n        auto end_time = chrono::steady_clock::now();\n        return chrono::duration_cast<chrono::duration<double>>(end_time - start_time).count();\n    }\n};\n\nstruct Point {\n    int r, c;\n    bool operator<(const Point& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n    bool operator==(const Point& other) const {\n        return r == other.r && c == other.c;\n    }\n};\n\nPoint operator+(const Point& a, const Point& b) { return {a.r + b.r, a.c + b.c}; }\nPoint operator-(const Point& a, const Point& b) { return {a.r - b.r, a.c - b.c}; }\nint manhattan(const Point& a, const Point& b) { return abs(a.r - b.r) + abs(a.c - b.c); }\n\nconst int dr[] = {-1, 0, 1, 0}; // U, R, D, L\nconst int dc[] = {0, 1, 0, -1};\nconst char move_chars[] = {'U', 'R', 'D', 'L'};\nconst Point REL_DIRS[] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; // 0:R, 1:D, 2:L, 3:U\n\nint N, M, V;\n\n// --- Arm Structure ---\nstruct Arm {\n    int v_count;\n    Point root_pos;\n    vector<int> parent;\n    vector<int> length;\n    vector<vector<int>> children;\n    vector<int> is_leaf;\n\n    vector<int> edge_dir;\n    vector<Point> abs_pos;\n    \n    vector<int> finger_indices;\n\n    Arm(int v, Point root, const vector<pair<int, int>>& edges) : v_count(v), root_pos(root) {\n        parent.assign(v, -1);\n        length.assign(v, 0);\n        children.assign(v, vector<int>());\n        edge_dir.assign(v, 0); // All edges point right initially\n        abs_pos.resize(v);\n        is_leaf.assign(v, 0);\n\n        for(int i = 1; i < v; ++i) {\n            parent[i] = edges[i-1].first;\n            length[i] = edges[i-1].second;\n            children[parent[i]].push_back(i);\n        }\n\n        for (int i = 0; i < v; ++i) {\n            if (children[i].empty()) {\n                is_leaf[i] = 1;\n                finger_indices.push_back(i);\n            }\n        }\n        update_abs_pos();\n    }\n\n    void update_abs_pos() {\n        abs_pos.resize(v_count);\n        abs_pos[0] = root_pos;\n        vector<int> q;\n        q.push_back(0);\n        int q_ptr = 0;\n        while(q_ptr < (int)q.size()){\n            int u = q[q_ptr++];\n            for(int v : children[u]){\n                Point rel = {REL_DIRS[edge_dir[v]].r * length[v], REL_DIRS[edge_dir[v]].c * length[v]};\n                abs_pos[v] = abs_pos[u] + rel;\n                q.push_back(v);\n            }\n        }\n    }\n    \n    void apply_command(const string& cmd) {\n        if (cmd[0] == 'U') root_pos.r--;\n        else if (cmd[0] == 'D') root_pos.r++;\n        else if (cmd[0] == 'L') root_pos.c--;\n        else if (cmd[0] == 'R') root_pos.c++;\n\n        for (int i = 1; i < v_count; ++i) {\n            if (cmd[i] == 'L') edge_dir[i] = (edge_dir[i] + 3) % 4;\n            else if (cmd[i] == 'R') edge_dir[i] = (edge_dir[i] + 1) % 4;\n        }\n        update_abs_pos();\n    }\n};\n\n// --- Game State ---\nstruct GameState {\n    Arm arm;\n    set<Point> sources_left;\n    set<Point> targets_to_fill;\n    map<int, Point> held_by_finger; // finger_idx -> original_source_pos\n    map<Point, Point> s_to_t_map;\n\n    GameState(Arm a, set<Point> s, set<Point> t, map<Point, Point> st_map)\n        : arm(a), sources_left(s), targets_to_fill(t), s_to_t_map(st_map) {}\n};\n\nstruct TargetConfig {\n    bool is_pickup;\n    Point root_pos;\n    vector<int> edge_dirs;\n    map<int, Point> finger_assignments;\n    double value = -1e18;\n};\n\n// --- Planning Functions ---\nTargetConfig find_best_config(const GameState& state, bool is_pickup) {\n    TargetConfig best_config;\n    best_config.is_pickup = is_pickup;\n\n    vector<int> available_fingers;\n    if (is_pickup) {\n        for (int f_idx : state.arm.finger_indices) {\n            if (state.held_by_finger.find(f_idx) == state.held_by_finger.end()) {\n                available_fingers.push_back(f_idx);\n            }\n        }\n        if (available_fingers.empty() || state.sources_left.empty()) return best_config;\n\n        for (const Point& p_anchor : state.sources_left) {\n            for (int f_anchor_idx : available_fingers) {\n                if (state.arm.parent[f_anchor_idx] != 0) continue;\n                for (int dir = 0; dir < 4; ++dir) {\n                    Point root_rel = {REL_DIRS[dir].r * state.arm.length[f_anchor_idx], REL_DIRS[dir].c * state.arm.length[f_anchor_idx]};\n                    Point cand_root_pos = p_anchor - root_rel;\n\n                    map<int, Point> assignments;\n                    vector<int> cand_dirs(state.arm.v_count);\n                    \n                    set<Point> remaining_sources = state.sources_left;\n                    vector<int> remaining_fingers;\n                    for(int f : available_fingers) remaining_fingers.push_back(f);\n                    \n                    int current_score = 0;\n\n                    for(int f_idx : remaining_fingers) {\n                        for(int f_dir = 0; f_dir < 4; ++f_dir) {\n                            Point f_rel = {REL_DIRS[f_dir].r * state.arm.length[f_idx], REL_DIRS[f_dir].c * state.arm.length[f_idx]};\n                            Point f_pos = cand_root_pos + f_rel;\n                            if (remaining_sources.count(f_pos)) {\n                                assignments[f_idx] = f_pos;\n                                cand_dirs[f_idx] = f_dir;\n                                remaining_sources.erase(f_pos);\n                                current_score++;\n                                break;\n                            }\n                        }\n                    }\n\n                    int dist_cost = manhattan(state.arm.root_pos, cand_root_pos);\n                    double value = current_score * 100.0 - dist_cost;\n\n                    if (value > best_config.value) {\n                        best_config.value = value;\n                        best_config.root_pos = cand_root_pos;\n                        best_config.edge_dirs = cand_dirs;\n                        best_config.finger_assignments = assignments;\n                    }\n                }\n            }\n        }\n    } else { // dropoff\n        map<int, Point> finger_to_dest;\n        for (const auto& [f_idx, s_pos] : state.held_by_finger) {\n            available_fingers.push_back(f_idx);\n            finger_to_dest[f_idx] = state.s_to_t_map.at(s_pos);\n        }\n        if (available_fingers.empty()) return best_config;\n        \n        for (int f_anchor_idx : available_fingers) {\n            const Point& p_anchor = finger_to_dest.at(f_anchor_idx);\n            if (state.arm.parent[f_anchor_idx] != 0) continue;\n\n            for (int dir = 0; dir < 4; ++dir) {\n                Point root_rel = {REL_DIRS[dir].r * state.arm.length[f_anchor_idx], REL_DIRS[dir].c * state.arm.length[f_anchor_idx]};\n                Point cand_root_pos = p_anchor - root_rel;\n\n                vector<int> cand_dirs(state.arm.v_count);\n                map<int, Point> assignments;\n                \n                int current_score = 0;\n                for(auto const& [f_idx, dest_pos] : finger_to_dest) {\n                    for (int f_dir = 0; f_dir < 4; ++f_dir) {\n                        Point f_rel = {REL_DIRS[f_dir].r * state.arm.length[f_idx], REL_DIRS[f_dir].c * state.arm.length[f_idx]};\n                        if (cand_root_pos + f_rel == dest_pos) {\n                            cand_dirs[f_idx] = f_dir;\n                            assignments[f_idx] = dest_pos;\n                            current_score++;\n                            break;\n                        }\n                    }\n                }\n\n                int dist_cost = manhattan(state.arm.root_pos, cand_root_pos);\n                double value = current_score * 100.0 - dist_cost;\n                if (value > best_config.value) {\n                    best_config.value = value;\n                    best_config.root_pos = cand_root_pos;\n                    best_config.edge_dirs = cand_dirs;\n                    best_config.finger_assignments = assignments;\n                }\n            }\n        }\n    }\n    return best_config;\n}\n\nstring get_next_command(const GameState& state, const TargetConfig& target) {\n    Arm current_arm = state.arm;\n    string command(2 * state.arm.v_count, '.');\n\n    if (current_arm.root_pos == target.root_pos && current_arm.edge_dir == target.edge_dirs) {\n        for (auto const& [f_idx, _] : target.finger_assignments) {\n            command[current_arm.v_count + f_idx] = 'P';\n        }\n        return command;\n    }\n\n    char best_move_c = '.';\n    int min_dist = manhattan(current_arm.root_pos, target.root_pos);\n    Point next_root_pos = current_arm.root_pos;\n    if (min_dist > 0) {\n        for (int i = 0; i < 4; ++i) { // U,R,D,L -> maps to dr/dc indices\n            Point new_pos = {current_arm.root_pos.r + DIRS[i].r, current_arm.root_pos.c + DIRS[i].c};\n            if (new_pos.r >= 0 && new_pos.r < N && new_pos.c >= 0 && new_pos.c < N) {\n                if (manhattan(new_pos, target.root_pos) < min_dist) {\n                    min_dist = manhattan(new_pos, target.root_pos);\n                    best_move_c = \"URDL\"[i];\n                    next_root_pos = new_pos;\n                }\n            }\n        }\n    }\n    command[0] = best_move_c;\n\n    for (int i = 1; i < current_arm.v_count; ++i) {\n        if (current_arm.parent[i] != 0) continue;\n        \n        Point finger_target_pos = target.root_pos;\n        Point finger_rel = {REL_DIRS[target.edge_dirs[i]].r * current_arm.length[i], REL_DIRS[target.edge_dirs[i]].c * current_arm.length[i]};\n        finger_target_pos = finger_target_pos + finger_rel;\n\n        char best_rot_c = '.';\n        int best_rot_dist = -1;\n\n        Point cur_rel = {REL_DIRS[current_arm.edge_dir[i]].r * current_arm.length[i], REL_DIRS[current_arm.edge_dir[i]].c * current_arm.length[i]};\n        best_rot_dist = manhattan(next_root_pos + cur_rel, finger_target_pos);\n        \n        int l_dir = (current_arm.edge_dir[i] + 3) % 4;\n        Point l_rel = {REL_DIRS[l_dir].r * current_arm.length[i], REL_DIRS[l_dir].c * current_arm.length[i]};\n        if (manhattan(next_root_pos + l_rel, finger_target_pos) < best_rot_dist) {\n            best_rot_dist = manhattan(next_root_pos + l_rel, finger_target_pos);\n            best_rot_c = 'L';\n        }\n\n        int r_dir = (current_arm.edge_dir[i] + 1) % 4;\n        Point r_rel = {REL_DIRS[r_dir].r * current_arm.length[i], REL_DIRS[r_dir].c * current_arm.length[i]};\n        if (manhattan(next_root_pos + r_rel, finger_target_pos) < best_rot_dist) {\n            best_rot_c = 'R';\n        }\n        command[i] = best_rot_c;\n    }\n    return command;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    Timer timer;\n    cin >> N >> M >> V;\n    set<Point> sources, targets;\n    for (int i = 0; i < N; ++i) {\n        string row; cin >> row;\n        for (int j = 0; j < N; ++j) if (row[j] == '1') sources.insert({i, j});\n    }\n    for (int i = 0; i < N; ++i) {\n        string row; cin >> row;\n        for (int j = 0; j < N; ++j) if (row[j] == '1') targets.insert({i, j});\n    }\n\n    // --- Arm Design ---\n    int v_to_use = V;\n    vector<pair<int, int>> edges;\n    int arm_L = max(1, (int)round(N / 8.0));\n    for (int i = 1; i < v_to_use; ++i) edges.push_back({0, arm_L});\n    \n    long long sum_r = 0, sum_c = 0; for(const auto& p : sources) { sum_r += p.r; sum_c += p.c; }\n    Point initial_root = {(int)(sum_r/M), (int)(sum_c/M)};\n    \n    cout << v_to_use << endl;\n    for (const auto& edge : edges) cout << edge.first << \" \" << edge.second << endl;\n    cout << initial_root.r << \" \" << initial_root.c << endl;\n\n    // --- Initial Planning (Matching) ---\n    map<Point, Point> s_to_t_map;\n    vector<Point> s_vec(sources.begin(), sources.end());\n    vector<Point> t_vec(targets.begin(), targets.end());\n    atcoder::mcf_graph<int, int> g(2 * M + 2);\n    int S_node = 2 * M, T_node = 2 * M + 1;\n    for (int i = 0; i < M; ++i) {\n        g.add_edge(S_node, i, 1, 0);\n        g.add_edge(M + i, T_node, 1, 0);\n        for (int j = 0; j < M; ++j) g.add_edge(i, M + j, 1, manhattan(s_vec[i], t_vec[j]));\n    }\n    g.flow(S_node, T_node, M);\n    for (auto e : g.edges()) {\n        if (e.from < M && e.to >= M && e.to < 2*M && e.flow > 0) s_to_t_map[s_vec[e.from]] = t_vec[e.to - M];\n    }\n\n    // --- Main Loop ---\n    Arm arm(v_to_use, initial_root, edges);\n    GameState state(arm, sources, targets, s_to_t_map);\n    \n    TargetConfig current_target;\n    int plan_life = 0;\n\n    int max_turns = 100000;\n    for (int turn = 0; turn < max_turns; ++turn) {\n        if (state.targets_to_fill.empty() || timer.get_elapsed_time() > 2.9) break;\n\n        if (plan_life <= 0) {\n            TargetConfig pickup_config = find_best_config(state, true);\n            TargetConfig dropoff_config = find_best_config(state, false);\n\n            if (pickup_config.value > -1e17 || dropoff_config.value > -1e17) {\n                 if (pickup_config.value >= dropoff_config.value) current_target = pickup_config;\n                 else current_target = dropoff_config;\n                 plan_life = manhattan(state.arm.root_pos, current_target.root_pos) + 5;\n            } else { // Fallback\n                string cmd(2 * V, '.'); cout << cmd << endl; state.arm.apply_command(cmd); continue;\n            }\n        }\n        \n        string command = get_next_command(state, current_target);\n        state.arm.apply_command(command);\n        \n        bool action_taken = false;\n        for (int i = 0; i < V; ++i) {\n            if (command[V + i] == 'P') {\n                action_taken = true;\n                if (current_target.is_pickup) {\n                    Point s_pos = state.arm.abs_pos[i];\n                    state.sources_left.erase(s_pos);\n                    state.held_by_finger[i] = s_pos;\n                } else {\n                    Point s_pos = state.held_by_finger.at(i);\n                    state.targets_to_fill.erase(state.s_to_t_map.at(s_pos));\n                    state.held_by_finger.erase(i);\n                }\n            }\n        }\n        if(action_taken) plan_life = 0; else plan_life--;\n\n        cout << command << endl;\n    }\n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n#include <random>\n#include <set>\n#include <map>\n#include <queue>\n\n// --- Utilities ---\nstruct Point {\n    int x, y;\n    bool operator<(const Point& other) const {\n        if (x != other.x) return x < other.x;\n        return y < other.y;\n    }\n     bool operator==(const Point& other) const {\n        return x == other.x && y == other.y;\n    }\n};\n\nlong long cross_product(Point a, Point b, Point c) {\n    return (long long)(b.x - a.x) * (c.y - a.y) - (long long)(b.y - a.y) * (c.x - a.x);\n}\n\n// Global timer\nstd::chrono::high_resolution_clock::time_point start_time;\n\n// --- Polygon Utilities ---\nstruct Polygon {\n    std::vector<Point> vertices;\n\n    bool is_inside(Point p) const {\n        if (vertices.empty()) return false;\n        int n = vertices.size();\n        bool inside = false;\n        for (int i = 0; i < n; ++i) {\n            const Point& p1 = vertices[i];\n            const Point& p2 = vertices[(i + 1) % n];\n\n            if (p1.y == p2.y && p.y == p1.y && p.x >= std::min(p1.x, p2.x) && p.x <= std::max(p1.x, p2.x)) {\n                return true;\n            }\n            if (p1.x == p2.x && p.x == p1.x && p.y >= std::min(p1.y, p2.y) && p.y <= std::max(p1.y, p2.y)) {\n                return true;\n            }\n\n            if ((p1.y > p.y) != (p2.y > p.y)) {\n                double intersect_x = (double)(p2.x - p1.x) * (p.y - p1.y) / (double)(p2.y - p1.y) + p1.x;\n                if (p.x < intersect_x) {\n                    inside = !inside;\n                }\n            }\n        }\n        return inside;\n    }\n\n    long long calculate_perimeter() const {\n        if (vertices.size() < 2) return 0;\n        long long p = 0;\n        for (size_t i = 0; i < vertices.size(); ++i) {\n            const auto& v1 = vertices[i];\n            const auto& v2 = vertices[(i + 1) % vertices.size()];\n            p += std::abs(v1.x - v2.x) + std::abs(v1.y - v2.y);\n        }\n        return p;\n    }\n};\n\n// --- Problem Data ---\nint N;\nstd::vector<Point> mackerels;\nstd::vector<Point> sardines;\n\n// --- Main Algorithm ---\n\nusing GridPoint = std::pair<int, int>;\n\nconst int DX[] = {0, 1, 0, -1};\nconst int DY[] = {1, 0, -1, 0};\n\nPolygon generate_polygon_from_cells(const std::set<GridPoint>& cells, int cell_size) {\n    if (cells.empty()) {\n        return Polygon{};\n    }\n\n    std::map<Point, std::vector<Point>> adj;\n    for (const auto& cell : cells) {\n        int gx = cell.first;\n        int gy = cell.second;\n        Point corners[] = {\n            {gx * cell_size, gy * cell_size},\n            {(gx + 1) * cell_size, gy * cell_size},\n            {(gx + 1) * cell_size, (gy + 1) * cell_size},\n            {gx * cell_size, (gy + 1) * cell_size}\n        };\n\n        for (int i = 0; i < 4; ++i) {\n            GridPoint neighbor = {gx + DX[i], gy + DY[i]};\n            if (cells.find(neighbor) == cells.end()) {\n                Point p1 = corners[i];\n                Point p2 = corners[(i + 3) % 4];\n                adj[p1].push_back(p2);\n                adj[p2].push_back(p1);\n            }\n        }\n    }\n    \n    std::vector<Point> vertices;\n    if (adj.empty()) return Polygon{};\n    \n    Point start_node = adj.begin()->first;\n    Point current_node = start_node;\n    Point prev_node = {start_node.x, start_node.y - 1};\n\n    for(size_t i = 0; i < 2 * adj.size(); ++i) {\n        vertices.push_back(current_node);\n        auto& neighbors = adj[current_node];\n        \n        std::sort(neighbors.begin(), neighbors.end(), [&](const Point& a, const Point& b) {\n            long long cp_a = cross_product(prev_node, current_node, a);\n            long long cp_b = cross_product(prev_node, current_node, b);\n            if (cp_a > 0 && cp_b <= 0) return true;\n            if (cp_a <= 0 && cp_b > 0) return false;\n            return cp_a > cp_b;\n        });\n        \n        Point next_node = neighbors[0];\n        for(const auto& neighbor : neighbors) {\n            if (!(neighbor == prev_node)) {\n                next_node = neighbor;\n                break;\n            }\n        }\n        \n        prev_node = current_node;\n        current_node = next_node;\n        if (current_node == start_node) break;\n    }\n\n    if (vertices.size() > 2) {\n        std::vector<Point> simplified;\n        for (size_t i = 0; i < vertices.size(); ++i) {\n            Point p_prev = simplified.empty() ? vertices.back() : simplified.back();\n            Point p_curr = vertices[i];\n            Point p_next = vertices[(i + 1) % vertices.size()];\n            if (cross_product(p_prev, p_curr, p_next) != 0 || simplified.size() < 2) {\n                simplified.push_back(p_curr);\n            }\n        }\n        vertices = simplified;\n    }\n    \n    return Polygon{vertices};\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    start_time = std::chrono::high_resolution_clock::now();\n\n    std::cin >> N;\n    mackerels.resize(N);\n    sardines.resize(N);\n    for (int i = 0; i < N; ++i) std::cin >> mackerels[i].x >> mackerels[i].y;\n    for (int i = 0; i < N; ++i) std::cin >> sardines[i].x >> sardines[i].y;\n    \n    int best_a = 0, best_b = 0;\n    Polygon best_polygon;\n    \n    std::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n    std::vector<int> cell_sizes = {1000, 667, 500, 400, 333, 250, 200};\n    int time_per_grid = 1980 / cell_sizes.size();\n\n    for (int cell_size : cell_sizes) {\n        auto loop_start_time = std::chrono::high_resolution_clock::now();\n        \n        int grid_dim_x = 100001 / cell_size + 1;\n        int grid_dim_y = 100001 / cell_size + 1;\n        std::vector<std::vector<int>> grid_scores(grid_dim_x, std::vector<int>(grid_dim_y, 0));\n\n        for (const auto& p : mackerels) grid_scores[p.x / cell_size][p.y / cell_size]++;\n        for (const auto& p : sardines) grid_scores[p.x / cell_size][p.y / cell_size]--;\n\n        std::vector<std::vector<bool>> visited(grid_dim_x, std::vector<bool>(grid_dim_y, false));\n\n        for (int gx = 0; gx < grid_dim_x; ++gx) {\n            for (int gy = 0; gy < grid_dim_y; ++gy) {\n                 auto now = std::chrono::high_resolution_clock::now();\n                 if (std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time).count() > 1980) break;\n                 \n                if (grid_scores[gx][gy] > 0 && !visited[gx][gy]) {\n                    std::set<GridPoint> component_cells;\n                    std::queue<GridPoint> q;\n\n                    q.push({gx, gy});\n                    visited[gx][gy] = true;\n                    while (!q.empty()) {\n                        GridPoint curr = q.front(); q.pop();\n                        component_cells.insert(curr);\n                        for (int i = 0; i < 4; ++i) {\n                            GridPoint next = {curr.first + DX[i], curr.second + DY[i]};\n                            if (next.first >= 0 && next.first < grid_dim_x && next.second >= 0 && next.second < grid_dim_y &&\n                                !visited[next.first][next.second] && grid_scores[next.first][next.second] > 0) {\n                                visited[next.first][next.second] = true;\n                                q.push(next);\n                            }\n                        }\n                    }\n\n                    std::set<GridPoint> current_cells = component_cells;\n                    \n                    double T = 5.0;\n                    double T_end = 0.01;\n                    int sa_iter = 0;\n                    \n                    while (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - loop_start_time).count() < time_per_grid - 20 && T > T_end) {\n                        sa_iter++;\n                        if (sa_iter % 200 == 0) T *= 0.99;\n                        \n                        std::vector<GridPoint> boundary_plus_neighbors;\n                        for(const auto& cell : current_cells) {\n                            for(int i=0; i<4; ++i) {\n                                GridPoint neighbor = {cell.first + DX[i], cell.second + DY[i]};\n                                if (neighbor.first >= 0 && neighbor.first < grid_dim_x && neighbor.second >= 0 && neighbor.second < grid_dim_y) {\n                                    boundary_plus_neighbors.push_back(neighbor);\n                                }\n                            }\n                        }\n                        if(boundary_plus_neighbors.empty()) continue;\n                        std::uniform_int_distribution<int> dist_op(0, boundary_plus_neighbors.size() - 1);\n                        GridPoint cand_cell = boundary_plus_neighbors[dist_op(rng)];\n\n                        bool is_in = current_cells.count(cand_cell);\n                        long long delta_score = grid_scores[cand_cell.first][cand_cell.second];\n                        if (is_in) delta_score = -delta_score;\n\n                        std::uniform_real_distribution<double> prob_dist(0.0, 1.0);\n                        if (delta_score > 0 || prob_dist(rng) < std::exp(delta_score / T)) {\n                            if (is_in) { if(current_cells.size() > 1) current_cells.erase(cand_cell); }\n                            else current_cells.insert(cand_cell);\n                        }\n                    }\n\n                    std::set<GridPoint> filled_cells = current_cells;\n                    if (!filled_cells.empty()) {\n                        std::vector<std::vector<bool>> is_component(grid_dim_x, std::vector<bool>(grid_dim_y, false));\n                        for(const auto& cell : filled_cells) is_component[cell.first][cell.second] = true;\n\n                        std::queue<GridPoint> hole_q;\n                        std::vector<std::vector<bool>> visited_bfs(grid_dim_x, std::vector<bool>(grid_dim_y, false));\n                        for(int i=0; i<grid_dim_x; ++i) {\n                            if (!is_component[i][0] && !visited_bfs[i][0]) { hole_q.push({i,0}); visited_bfs[i][0] = true; }\n                            if (grid_dim_y > 1 && !is_component[i][grid_dim_y-1] && !visited_bfs[i][grid_dim_y-1]) { hole_q.push({i,grid_dim_y-1}); visited_bfs[i][grid_dim_y-1] = true; }\n                        }\n                        for(int i=0; i<grid_dim_y; ++i) {\n                            if (!is_component[0][i] && !visited_bfs[0][i]) { hole_q.push({0,i}); visited_bfs[0][i] = true; }\n                            if (grid_dim_x > 1 && !is_component[grid_dim_x-1][i] && !visited_bfs[grid_dim_x-1][i]) { hole_q.push({grid_dim_x-1,i}); visited_bfs[grid_dim_x-1][i] = true; }\n                        }\n\n                        while(!hole_q.empty()){\n                            GridPoint curr = hole_q.front(); hole_q.pop();\n                            for(int i=0; i<4; ++i){\n                                GridPoint next = {curr.first + DX[i], curr.second + DY[i]};\n                                if (next.first >= 0 && next.first < grid_dim_x && next.second >= 0 && next.second < grid_dim_y && !visited_bfs[next.first][next.second] && !is_component[next.first][next.second]){\n                                    visited_bfs[next.first][next.second] = true;\n                                    hole_q.push(next);\n                                }\n                            }\n                        }\n                        \n                        for(int i=0; i<grid_dim_x; ++i) for(int j=0; j<grid_dim_y; ++j) {\n                            if(!visited_bfs[i][j] && !is_component[i][j]) filled_cells.insert({i,j});\n                        }\n                    }\n\n                    Polygon p = generate_polygon_from_cells(filled_cells, cell_size);\n                    if (p.vertices.size() >= 4 && p.vertices.size() <= 1000 && p.calculate_perimeter() <= 400000) {\n                        int current_a = 0, current_b = 0;\n                        for (const auto& m : mackerels) if (p.is_inside(m)) current_a++;\n                        for (const auto& s : sardines) if (p.is_inside(s)) current_b++;\n\n                        if (current_a - current_b > best_a - best_b) {\n                            best_a = current_a;\n                            best_b = current_b;\n                            best_polygon = p;\n                        }\n                    }\n                }\n            }\n             if (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start_time).count() > 1980) break;\n        }\n    }\n\n    if (best_polygon.vertices.empty()) {\n        if (!mackerels.empty()) {\n            Point m = mackerels[0];\n            best_polygon.vertices.push_back({m.x, m.y});\n            best_polygon.vertices.push_back({m.x + 1, m.y});\n            best_polygon.vertices.push_back({m.x + 1, m.y + 1});\n            best_polygon.vertices.push_back({m.x, m.y + 1});\n        }\n    }\n\n    std::cout << best_polygon.vertices.size() << '\\n';\n    for (const auto& v : best_polygon.vertices) {\n        std::cout << v.x << \" \" << v.y << '\\n';\n    }\n\n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <string>\n#include <chrono>\n#include <random>\n#include <numeric>\n#include <algorithm>\n#include <map>\n#include <tuple>\n#include <cmath>\n\n#include <Eigen/Dense>\n\n// --- Timer ---\nusing namespace std;\nusing namespace std::chrono;\n\nlong long start_time;\n\nlong long get_time() {\n    return duration_cast<milliseconds>(high_resolution_clock::now().time_since_epoch()).count();\n}\n\n// --- Random ---\nmt19937 rng(0);\n\n// --- Problem specific structs ---\nstruct Rect {\n    long long x, y, w, h;\n};\n\nstruct Action {\n    int p, r;\n    char d;\n    int b;\n};\n\nusing Plan = vector<Action>;\n\n// O(N^2) simulation. N = plan.size().\npair<long long, long long> simulate(int N_total, const vector<double>& w_est, const vector<double>& h_est, const Plan& plan) {\n    if (plan.empty()) return {0,0};\n\n    vector<Rect> placed_rects;\n    long long W = 0, H = 0;\n    vector<int> p_to_idx(N_total, -1);\n\n    for (const auto& action : plan) {\n        long long w = round((action.r == 0) ? w_est[action.p] : h_est[action.p]);\n        long long h = round((action.r == 0) ? h_est[action.p] : w_est[action.p]);\n        long long new_x, new_y;\n        if (action.d == 'U') {\n            new_x = 0;\n            if (action.b != -1) {\n                const auto& ref_rect = placed_rects[p_to_idx[action.b]];\n                new_x = ref_rect.x + ref_rect.w;\n            }\n            new_y = 0;\n            for (const auto& rect : placed_rects) {\n                if (max(new_x, rect.x) < min(new_x + w, rect.x + rect.w)) {\n                    new_y = max(new_y, rect.y + rect.h);\n                }\n            }\n        } else { // 'L'\n            new_y = 0;\n            if (action.b != -1) {\n                const auto& ref_rect = placed_rects[p_to_idx[action.b]];\n                new_y = ref_rect.y + ref_rect.h;\n            }\n            new_x = 0;\n            for (const auto& rect : placed_rects) {\n                if (max(new_y, rect.y) < min(new_y + h, rect.y + rect.h)) {\n                    new_x = max(new_x, rect.x + rect.w);\n                }\n            }\n        }\n        p_to_idx[action.p] = placed_rects.size();\n        placed_rects.push_back({new_x, new_y, w, h});\n        W = max(W, new_x + w);\n        H = max(H, new_y + h);\n    }\n    return {W, H};\n}\n\n\n// --- Main logic ---\nint N, T;\ndouble SIGMA;\nvector<double> w_obs, h_obs;\nvector<double> w_mean, h_mean;\n\nvector<Plan> exploratory_plans;\nvector<tuple<Plan, long long, long long>> history;\n\nlong long best_score = -1;\nPlan best_plan;\n\nvoid generate_exploratory_plans() {\n    for (int k = 0; k < 4; ++k) {\n        Plan p_L, p_U;\n        for (int i = 0; i < N; ++i) {\n            p_L.push_back({i, (int)(rng() % 2), 'L', i > 0 ? i-1 : -1});\n            p_U.push_back({i, (int)(rng() % 2), 'U', i > 0 ? i-1 : -1});\n        }\n        exploratory_plans.push_back(p_L);\n        exploratory_plans.push_back(p_U);\n    }\n}\n\nvoid update_estimates_by_lsq() {\n    int num_vars = 2 * N;\n    \n    vector<vector<pair<int, double>>> A_rows;\n    vector<double> b_vals;\n\n    for (int i = 0; i < N; ++i) {\n        A_rows.push_back({{i, 1.0}}); b_vals.push_back(w_obs[i]);\n        A_rows.push_back({{N + i, 1.0}}); b_vals.push_back(h_obs[i]);\n    }\n\n    for (const auto& [plan, W_prime, H_prime] : history) {\n        if(plan.size() != N) continue;\n        bool is_sum_plan = true;\n        char first_d = plan[0].d;\n        for(size_t j=1; j<plan.size(); ++j) {\n            if(plan[j].d != first_d) { is_sum_plan = false; break; }\n        }\n        if(!is_sum_plan) continue;\n\n        vector<pair<int, double>> row;\n        if (first_d == 'L') {\n            for (const auto& action : plan) {\n                if (action.r == 0) row.push_back({action.p, 1.0});\n                else row.push_back({N + action.p, 1.0});\n            }\n            A_rows.push_back(row); b_vals.push_back(W_prime);\n        } else {\n            for (const auto& action : plan) {\n                if (action.r == 0) row.push_back({N + action.p, 1.0});\n                else row.push_back({action.p, 1.0});\n            }\n            A_rows.push_back(row); b_vals.push_back(H_prime);\n        }\n    }\n\n    int num_equations = A_rows.size();\n    Eigen::MatrixXd A(num_equations, num_vars);\n    Eigen::VectorXd b(num_equations);\n    A.setZero();\n    for(int i=0; i<num_equations; ++i){\n        for(auto const& [col, val] : A_rows[i]) {\n            A(i, col) = val;\n        }\n        b(i) = b_vals[i];\n    }\n    \n    Eigen::VectorXd x = A.bdcSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(b);\n\n    for (int i = 0; i < N; ++i) {\n        w_mean[i] = max(1.0, x(i));\n        h_mean[i] = max(1.0, x(N + i));\n    }\n}\n\nPlan greedy_search() {\n    Plan plan;\n    vector<Rect> placed_rects;\n    long long current_W = 0, current_H = 0;\n\n    for (int i = 0; i < N; ++i) { // Assuming p_i = i\n        Action best_action;\n        long long best_score = -1;\n        \n        for (int r = 0; r < 2; ++r) {\n            long long w = round((r == 0) ? w_mean[i] : h_mean[i]);\n            long long h = round((r == 0) ? h_mean[i] : w_mean[i]);\n            for (char d : {'U', 'L'}) {\n                vector<int> b_candidates;\n                const int B_SAMPLES = 10;\n                const int FULL_SEARCH_THRESHOLD = 20;\n\n                b_candidates.push_back(-1);\n                if (i > 0) {\n                    if (i < FULL_SEARCH_THRESHOLD) {\n                        for(int k=0; k<i; ++k) b_candidates.push_back(k);\n                    } else {\n                        b_candidates.push_back(i - 1);\n                        uniform_int_distribution<int> dist(0, i - 1);\n                        for (int k=0; k < B_SAMPLES; ++k) {\n                            b_candidates.push_back(dist(rng));\n                        }\n                    }\n                }\n                sort(b_candidates.begin(), b_candidates.end());\n                b_candidates.erase(unique(b_candidates.begin(), b_candidates.end()), b_candidates.end());\n\n                for (int b_val : b_candidates) {\n                    long long new_x, new_y;\n                    if(d == 'U'){\n                        new_x = 0; \n                        if (b_val != -1) new_x = placed_rects[b_val].x + placed_rects[b_val].w;\n                        new_y = 0;\n                        for(const auto& rect : placed_rects) {\n                            if(max(new_x, rect.x) < min(new_x+w, rect.x+rect.w)) {\n                                new_y = max(new_y, rect.y+rect.h);\n                            }\n                        }\n                    } else { // 'L'\n                        new_y = 0;\n                        if (b_val != -1) new_y = placed_rects[b_val].y + placed_rects[b_val].h;\n                        new_x = 0;\n                        for(const auto& rect : placed_rects) {\n                            if(max(new_y, rect.y) < min(new_y+h, rect.y+rect.h)) {\n                                new_x = max(new_x, rect.x+rect.w);\n                            }\n                        }\n                    }\n                    long long next_W = max(current_W, new_x+w);\n                    long long next_H = max(current_H, new_y+h);\n\n                    long long current_score = next_W + next_H;\n                    if (best_score == -1 || current_score < best_score) {\n                        best_score = current_score;\n                        best_action = {i, r, d, b_val};\n                    }\n                }\n            }\n        }\n        \n        plan.push_back(best_action);\n        long long w = round((best_action.r == 0) ? w_mean[i] : h_mean[i]);\n        long long h = round((best_action.r == 0) ? h_mean[i] : w_mean[i]);\n        long long new_x, new_y;\n        if(best_action.d == 'U'){\n            new_x = 0; if (best_action.b != -1) new_x = placed_rects[best_action.b].x + placed_rects[best_action.b].w;\n            new_y = 0;\n            for(const auto& rect : placed_rects) if(max(new_x, rect.x) < min(new_x+w, rect.x+rect.w)) new_y = max(new_y, rect.y+rect.h);\n        } else {\n            new_y = 0; if (best_action.b != -1) new_y = placed_rects[best_action.b].y + placed_rects[best_action.b].h;\n            new_x = 0;\n            for(const auto& rect : placed_rects) if(max(new_y, rect.y) < min(new_y+h, rect.y+rect.h)) new_x = max(new_x, rect.x+rect.w);\n        }\n        placed_rects.push_back({new_x, new_y, w, h});\n        current_W = max(current_W, new_x+w);\n        current_H = max(current_H, new_y+h);\n    }\n    return plan;\n}\n\nPlan local_search(Plan initial_plan, int time_limit_ms) {\n    long long turn_start_time = get_time();\n    Plan current_best_plan = initial_plan;\n    auto [W, H] = simulate(N, w_mean, h_mean, current_best_plan);\n    long long best_eval_score = W + H;\n\n    while(get_time() - turn_start_time < time_limit_ms) {\n        Plan current_plan = current_best_plan;\n        int i = rng() % N;\n        \n        int change_type = uniform_int_distribution<int>(0, 2)(rng);\n        if (change_type == 0) {\n            current_plan[i].r = 1 - current_plan[i].r;\n        } else if (change_type == 1) {\n            current_plan[i].d = (current_plan[i].d == 'U' ? 'L' : 'U');\n        } else { // change_type == 2\n            if (i > 0) {\n                current_plan[i].b = uniform_int_distribution<int>(-1, i - 1)(rng);\n            }\n        }\n        \n        auto [cur_W, cur_H] = simulate(N, w_mean, h_mean, current_plan);\n        long long current_eval_score = cur_W + cur_H;\n\n        if (current_eval_score < best_eval_score) {\n            best_eval_score = current_eval_score;\n            current_best_plan = current_plan;\n        }\n    }\n    return current_best_plan;\n}\n\nvoid solve() {\n    cin >> N >> T >> SIGMA;\n    w_obs.resize(N); h_obs.resize(N);\n    w_mean.resize(N); h_mean.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> w_obs[i] >> h_obs[i];\n        w_mean[i] = w_obs[i];\n        h_mean[i] = h_obs[i];\n    }\n    \n    generate_exploratory_plans();\n    \n    int K = min((int)exploratory_plans.size(), T / 2);\n    \n    for (int t = 0; t < T; ++t) {\n        Plan p_to_submit;\n        if (t < K) {\n            p_to_submit = exploratory_plans[t];\n        } else {\n            if (t == K && K > 0) { // Update estimates only once after exploration\n                update_estimates_by_lsq();\n            }\n            \n            long long time_left = 2800 - (get_time() - start_time);\n            long long time_per_turn = time_left / (T - t + 1);\n            \n            long long greedy_start_time = get_time();\n            Plan initial_plan = greedy_search();\n            long long greedy_time = get_time() - greedy_start_time;\n\n            p_to_submit = local_search(initial_plan, max(0LL, time_per_turn - greedy_time));\n            \n            if (!best_plan.empty()) {\n                auto [w_cand, h_cand] = simulate(N, w_mean, h_mean, p_to_submit);\n                auto [w_best, h_best] = simulate(N, w_mean, h_mean, best_plan);\n                if (w_best + h_best < w_cand + h_cand) {\n                    p_to_submit = best_plan;\n                }\n            }\n        }\n        \n        cout << p_to_submit.size() << endl;\n        for (const auto& action : p_to_submit) {\n            cout << action.p << \" \" << action.r << \" \" << action.d << \" \" << action.b << endl;\n        }\n\n        long long W_prime, H_prime;\n        cin >> W_prime >> H_prime;\n        \n        if (t < K) {\n            history.emplace_back(p_to_submit, W_prime, H_prime);\n        }\n        \n        long long current_score = W_prime + H_prime;\n        if (best_score == -1 || current_score < best_score) {\n            best_score = current_score;\n            best_plan = p_to_submit;\n        }\n    }\n}\n\nint main() {\n    start_time = get_time();\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <cmath>\n#include <tuple>\n\nusing namespace std;\n\n// --- Utilities ---\nstruct XorShift {\n    unsigned int x, y, z, w;\n    XorShift(unsigned int seed) : x(seed), y(362436069), z(521288629), w(88675123) {}\n    unsigned int next() {\n        unsigned int t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));\n    }\n    int next_int(int n) {\n        if (n == 0) return 0;\n        return next() % n;\n    }\n    double next_double() {\n        return (double)next() / ((long long)1 << 32);\n    }\n};\n\nXorShift rnd(12345);\nauto start_time = chrono::steady_clock::now();\n\n// --- Problem data ---\nint N, M, H;\nvector<int> A;\nvector<pair<int, int>> edges;\nvector<vector<int>> adj;\n\n// --- Solution state and helpers ---\nstruct Solution {\n    vector<int> p;\n    long long score;\n\n    vector<vector<int>> children;\n    vector<int> h;\n    vector<int> max_d;\n    vector<long long> sum_A_sub;\n    vector<int> root_of;\n\n    Solution() {}\n\n    void init(int n_nodes) {\n        p.assign(n_nodes, -1);\n        children.assign(n_nodes, {});\n        h.assign(n_nodes, 0);\n        max_d.assign(n_nodes, 0);\n        sum_A_sub.assign(n_nodes, 0);\n        root_of.assign(n_nodes, -1);\n    }\n\n    void compute_properties() {\n        for(int i=0; i<N; ++i) children[i].clear();\n        vector<int> roots;\n        for (int i = 0; i < N; ++i) {\n            if (p[i] == -1) {\n                roots.push_back(i);\n            } else {\n                children[p[i]].push_back(i);\n            }\n        }\n\n        for (int r : roots) {\n            vector<int> q;\n            q.push_back(r);\n            root_of[r] = r;\n            h[r] = 0;\n            \n            int head = 0;\n            while(head < q.size()){\n                int u = q[head++];\n                for(int v : children[u]){\n                    h[v] = h[u] + 1;\n                    root_of[v] = r;\n                    q.push_back(v);\n                }\n            }\n            \n            reverse(q.begin(), q.end());\n            for(int u : q){\n                sum_A_sub[u] = A[u];\n                max_d[u] = 0;\n                for(int v : children[u]){\n                    sum_A_sub[u] += sum_A_sub[v];\n                    max_d[u] = max(max_d[u], max_d[v] + 1);\n                }\n            }\n        }\n        score = 0;\n        for(int i=0; i<N; ++i) {\n            if (h[i] > H) {\n                score = -1; // Invalid\n                return;\n            }\n            score += (long long)(h[i] + 1) * A[i];\n        }\n    }\n};\n\nvoid solve() {\n    Solution sol;\n    sol.init(N);\n    \n    // --- Greedy construction ---\n    double greedy_time_limit = 0.8;\n    int roots_count = N;\n    while(roots_count > 1) {\n        auto current_time = chrono::steady_clock::now();\n        double elapsed_time = chrono::duration_cast<chrono::milliseconds>(current_time - start_time).count() / 1000.0;\n        if (elapsed_time > greedy_time_limit) break;\n\n        sol.compute_properties();\n\n        double best_gain = -1.0;\n        int best_u = -1, best_v = -1;\n\n        for (const auto& edge : edges) {\n            int u1 = edge.first;\n            int v1 = edge.second;\n\n            if (sol.root_of[u1] == sol.root_of[v1]) continue;\n\n            // Try u1 -> v1\n            if (sol.p[v1] == -1) {\n                if (sol.h[u1] + 1 + sol.max_d[v1] <= H) {\n                    double gain = (double)(sol.h[u1] + 1) * sol.sum_A_sub[v1];\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        best_u = u1;\n                        best_v = v1;\n                    }\n                }\n            }\n            // Try v1 -> u1\n            if (sol.p[u1] == -1) {\n                if (sol.h[v1] + 1 + sol.max_d[u1] <= H) {\n                    double gain = (double)(sol.h[v1] + 1) * sol.sum_A_sub[u1];\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        best_u = v1;\n                        best_v = u1;\n                    }\n                }\n            }\n        }\n\n        if (best_u == -1) break;\n        sol.p[best_v] = best_u;\n        roots_count--;\n    }\n\n    sol.compute_properties();\n    Solution best_sol = sol;\n\n    // --- Simulated Annealing ---\n    double time_limit = 1.95;\n    double temp_start = 500.0, temp_end = 0.1;\n\n    while (true) {\n        auto current_time = chrono::steady_clock::now();\n        double elapsed_time = chrono::duration_cast<chrono::milliseconds>(current_time - start_time).count() / 1000.0;\n        if (elapsed_time > time_limit) break;\n\n        double progress = (elapsed_time - greedy_time_limit) / (time_limit - greedy_time_limit);\n        if (progress < 0) progress = 0;\n        if (progress > 1) progress = 1;\n\n        double temp = temp_start * pow(temp_end / temp_start, progress);\n\n        int v = rnd.next_int(N);\n        \n        vector<int> candidates = adj[v];\n        candidates.push_back(-1);\n        int u = candidates[rnd.next_int(candidates.size())];\n\n        int old_p = sol.p[v];\n        if (u == old_p) continue;\n        \n        bool is_ancestor = false;\n        if (u != -1) {\n            int curr = u;\n            while(curr != -1) {\n                if (curr == v) {\n                    is_ancestor = true;\n                    break;\n                }\n                curr = sol.p[curr];\n            }\n        }\n        if (is_ancestor) continue;\n        \n        int u_h = (u == -1) ? -1 : sol.h[u];\n        if (u_h + 1 + sol.max_d[v] > H) continue;\n\n        int old_p_h = (old_p == -1) ? -1 : sol.h[old_p];\n        long long score_delta = (long long)(u_h - old_p_h) * sol.sum_A_sub[v];\n\n        if (score_delta > 0 || (temp > 1e-9 && rnd.next_double() < exp(score_delta / temp))) {\n            sol.p[v] = u;\n            sol.compute_properties();\n            if (sol.score > best_sol.score) {\n                best_sol = sol;\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << best_sol.p[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N >> M >> H;\n    A.resize(N);\n    adj.resize(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        edges.push_back({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    solve();\n\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <array>\n\nusing namespace std;\n\nconst int N = 20;\n\nstruct Piece {\n    int id; // unique id for Oni (0 to 2N-1), -1 for Fuku\n    int r, c;\n    bool removed = false;\n};\n\nstruct Action {\n    char dir;\n    int line_idx;\n    int cost;\n    vector<int> covered_oni_ids;\n};\n\n// Calculate initial safe directions to determine weights\nauto precompute_oni_weights(const vector<Piece>& onis, const vector<Piece>& fukus) {\n    int num_onis = onis.size();\n    vector<double> oni_weights(num_onis);\n\n    for (int i = 0; i < num_onis; ++i) {\n        const auto& oni = onis[i];\n        bool safe_u = true, safe_d = true, safe_l = true, safe_r = true;\n\n        for (const auto& fuku : fukus) {\n            if (fuku.c == oni.c) {\n                if (fuku.r < oni.r) safe_u = false;\n                if (fuku.r > oni.r) safe_d = false;\n            }\n            if (fuku.r == oni.r) {\n                if (fuku.c < oni.c) safe_l = false;\n                if (fuku.c > oni.c) safe_r = false;\n            }\n        }\n        int num_ways = safe_u + safe_d + safe_l + safe_r;\n        if (num_ways > 0) {\n            oni_weights[i] = 1.0 / num_ways;\n        } else {\n            oni_weights[i] = 1.0; \n        }\n    }\n    return oni_weights;\n}\n\nvoid apply_action(const Action& action, vector<Piece>& onis, vector<Piece>& fukus, int& uncovered_count) {\n    auto update_piece = [&](Piece& p) {\n        if (p.removed) return;\n        switch(action.dir) {\n            case 'U':\n                if (p.c == action.line_idx) {\n                    if (p.r < action.cost) p.removed = true;\n                    else p.r -= action.cost;\n                }\n                break;\n            case 'D':\n                if (p.c == action.line_idx) {\n                    if (p.r > N - 1 - action.cost) p.removed = true;\n                    else p.r += action.cost;\n                }\n                break;\n            case 'L':\n                 if (p.r == action.line_idx) {\n                    if (p.c < action.cost) p.removed = true;\n                    else p.c -= action.cost;\n                }\n                break;\n            case 'R':\n                if (p.r == action.line_idx) {\n                    if (p.c > N - 1 - action.cost) p.removed = true;\n                    else p.c += action.cost;\n                }\n                break;\n        }\n    };\n\n    for (auto& oni : onis) {\n        bool was_active = !oni.removed;\n        update_piece(oni);\n        if (was_active && oni.removed) {\n            uncovered_count--;\n        }\n    }\n    for (auto& fuku : fukus) {\n        update_piece(fuku);\n    }\n}\n\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n_dummy;\n    cin >> n_dummy;\n\n    vector<Piece> initial_onis;\n    vector<Piece> initial_fukus;\n\n    int oni_id_counter = 0;\n    for (int i = 0; i < N; ++i) {\n        string row_str;\n        cin >> row_str;\n        for (int j = 0; j < N; ++j) {\n            if (row_str[j] == 'x') {\n                initial_onis.push_back({oni_id_counter++, i, j});\n            } else if (row_str[j] == 'o') {\n                initial_fukus.push_back({-1, i, j});\n            }\n        }\n    }\n\n    auto oni_weights = precompute_oni_weights(initial_onis, initial_fukus);\n    \n    vector<Piece> onis = initial_onis;\n    vector<Piece> fukus = initial_fukus;\n    int uncovered_count = onis.size();\n    \n    vector<pair<char, int>> moves;\n\n    while (uncovered_count > 0) {\n        Action best_action = {' ', -1, -1, {}};\n        double best_score = 1e18;\n\n        vector<vector<int>> onis_in_row(N), fukus_in_row(N);\n        vector<vector<int>> onis_in_col(N), fukus_in_col(N);\n\n        for (const auto& oni : onis) {\n            if (!oni.removed) {\n                onis_in_row[oni.r].push_back(oni.id);\n                onis_in_col[oni.c].push_back(oni.id);\n            }\n        }\n        for (const auto& fuku : fukus) {\n            if (!fuku.removed) {\n                fukus_in_row[fuku.r].push_back(fuku.id);\n                fukus_in_col[fuku.c].push_back(fuku.id);\n            }\n        }\n\n        auto process_line = [&](char dir, int idx) {\n            vector<int> covered_ids;\n            int cost = 0;\n            double value = 0.0;\n            \n            const auto& line_onis = (dir == 'U' || dir == 'D') ? onis_in_col[idx] : onis_in_row[idx];\n            const auto& line_fukus = (dir == 'U' || dir == 'D') ? fukus_in_col[idx] : fukus_in_row[idx];\n\n            for(int oni_id : line_onis) {\n                bool safe = true;\n                for (int fuku_id : line_fukus) {\n                    if ((dir == 'U' && fukus[fuku_id].r < onis[oni_id].r) ||\n                        (dir == 'D' && fukus[fuku_id].r > onis[oni_id].r) ||\n                        (dir == 'L' && fukus[fuku_id].c < onis[oni_id].c) ||\n                        (dir == 'R' && fukus[fuku_id].c > onis[oni_id].c)) {\n                        safe = false;\n                        break;\n                    }\n                }\n                if (safe) {\n                    covered_ids.push_back(oni_id);\n                    if(dir == 'U') cost = max(cost, onis[oni_id].r + 1);\n                    if(dir == 'D') cost = max(cost, N - onis[oni_id].r);\n                    if(dir == 'L') cost = max(cost, onis[oni_id].c + 1);\n                    if(dir == 'R') cost = max(cost, N - onis[oni_id].c);\n                    value += oni_weights[oni_id];\n                }\n            }\n\n            if (!covered_ids.empty()) {\n                double score = (double)cost / value;\n                if (score < best_score || (score == best_score && cost < best_action.cost)) {\n                    best_score = score;\n                    best_action = {dir, idx, cost, covered_ids};\n                }\n            }\n        };\n\n        for (int i = 0; i < N; ++i) {\n            process_line('L', i);\n            process_line('R', i);\n        }\n        for (int j = 0; j < N; ++j) {\n            process_line('U', j);\n            process_line('D', j);\n        }\n\n        if (best_action.line_idx == -1) {\n            break; \n        }\n\n        for (int i = 0; i < best_action.cost; ++i) {\n            moves.push_back({best_action.dir, best_action.line_idx});\n        }\n        \n        apply_action(best_action, onis, fukus, uncovered_count);\n    }\n\n    for (const auto& move : moves) {\n        cout << move.first << \" \" << move.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <algorithm>\n\n// --- Start of Timer and RNG Utilities ---\nclass Timer {\n    std::chrono::high_resolution_clock::time_point start_time;\npublic:\n    Timer() {\n        start_time = std::chrono::high_resolution_clock::now();\n    }\n    double get_elapsed_sec() {\n        auto now = std::chrono::high_resolution_clock::now();\n        return std::chrono::duration_cast<std::chrono::duration<double>>(now - start_time).count();\n    }\n};\n\nclass XorShiftRng {\n    uint64_t x;\npublic:\n    XorShiftRng() : x(std::chrono::high_resolution_clock::now().time_since_epoch().count()) {}\n    uint64_t next() {\n        x ^= x << 13;\n        x ^= x >> 7;\n        x ^= x << 17;\n        return x;\n    }\n    int next_int(int max) { // [0, max-1]\n        if (max <= 0) return 0;\n        return next() % max;\n    }\n    double next_double() { // [0.0, 1.0)\n        return static_cast<double>(next()) / UINT64_MAX;\n    }\n};\n// --- End of Timer and RNG Utilities ---\n\nconst int N_CONST = 100;\nconst int L_CONST = 500000;\nconst double TIME_LIMIT_SEC = 1.95;\n\nstruct EvalResult {\n    long long error;\n    std::vector<int> t;\n};\n\nEvalResult evaluate(const std::vector<int>& a, const std::vector<int>& b, const std::vector<int>& T) {\n    std::vector<int> t(N_CONST, 0);\n    int cleaner = 0;\n    \n    t[cleaner]++;\n    \n    for (int k = 1; k < L_CONST; ++k) {\n        int last_cleaner = cleaner;\n        int count_of_last_cleaner = t[last_cleaner];\n        \n        if (count_of_last_cleaner % 2 != 0) {\n            cleaner = a[last_cleaner];\n        } else {\n            cleaner = b[last_cleaner];\n        }\n        t[cleaner]++;\n    }\n    \n    long long error = 0;\n    for (int i = 0; i < N_CONST; ++i) {\n        error += std::abs(static_cast<long long>(t[i]) - T[i]);\n    }\n    \n    return {error, std::move(t)};\n}\n\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    Timer timer;\n    \n    int n_in, l_in;\n    std::cin >> n_in >> l_in; \n    std::vector<int> T(N_CONST);\n    for (int i = 0; i < N_CONST; ++i) {\n        std::cin >> T[i];\n    }\n\n    XorShiftRng rng;\n\n    // --- Initial solution ---\n    std::vector<int> a(N_CONST), b(N_CONST);\n    \n    std::mt19937 mt_for_dist(rng.next());\n    std::vector<double> weights(N_CONST);\n    for(int i = 0; i < N_CONST; ++i) {\n         weights[i] = T[i] > 0 ? static_cast<double>(T[i]) : 1.0;\n    }\n    std::discrete_distribution<> dist(weights.begin(), weights.end());\n\n    for (int i = 0; i < N_CONST; ++i) {\n        a[i] = dist(mt_for_dist);\n        b[i] = dist(mt_for_dist);\n    }\n\n    auto current_eval = evaluate(a, b, T);\n    long long current_error = current_eval.error;\n    std::vector<int> current_t = std::move(current_eval.t);\n\n    std::vector<int> best_a = a;\n    std::vector<int> best_b = b;\n    long long best_error = current_error;\n\n    // --- Simulated Annealing ---\n    double T_start = 2000.0;\n    double T_end = 0.1;\n    \n    while (timer.get_elapsed_sec() < TIME_LIMIT_SEC) {\n        double progress = timer.get_elapsed_sec() / TIME_LIMIT_SEC;\n        double temp = T_start * std::pow(T_end / T_start, progress);\n\n        std::vector<int> next_a = a;\n        std::vector<int> next_b = b;\n\n        // --- Generate Neighbor ---\n        int change_i;\n        int change_ab; // 0 for a, 1 for b\n        int new_val;\n        \n        std::vector<int> over_served;\n        std::vector<int> under_served;\n        for(int j=0; j<N_CONST; ++j) {\n            if(current_t[j] > T[j]) over_served.push_back(j);\n            else if (current_t[j] < T[j]) under_served.push_back(j);\n        }\n\n        bool smart_move_possible = !over_served.empty() && !under_served.empty();\n        \n        if (rng.next_double() < 0.1 || !smart_move_possible) { // Random move\n            change_i = rng.next_int(N_CONST);\n            change_ab = rng.next_int(2);\n            new_val = rng.next_int(N_CONST);\n        } else { // Smart move: Reroute an edge from an over-served node to an under-served node\n            std::vector<bool> is_over_served(N_CONST, false);\n            for(int v : over_served) is_over_served[v] = true;\n            \n            std::vector<std::pair<int, int>> redirectable_edges;\n            redirectable_edges.reserve(2 * N_CONST);\n            for (int u = 0; u < N_CONST; ++u) {\n                if (is_over_served[a[u]]) redirectable_edges.push_back({u, 0});\n                if (is_over_served[b[u]]) redirectable_edges.push_back({u, 1});\n            }\n            \n            if (redirectable_edges.empty()) { // Fallback to random move\n                change_i = rng.next_int(N_CONST);\n                change_ab = rng.next_int(2);\n                new_val = rng.next_int(N_CONST);\n            } else {\n                auto& edge_to_change = redirectable_edges[rng.next_int(redirectable_edges.size())];\n                change_i = edge_to_change.first;\n                change_ab = edge_to_change.second;\n                new_val = under_served[rng.next_int(under_served.size())];\n            }\n        }\n\n        if (change_ab == 0) {\n            next_a[change_i] = new_val;\n        } else {\n            next_b[change_i] = new_val;\n        }\n        \n        auto neighbor_eval = evaluate(next_a, next_b, T);\n        long long neighbor_error = neighbor_eval.error;\n\n        double delta_e = static_cast<double>(neighbor_error) - current_error;\n\n        if (delta_e < 0 || rng.next_double() < std::exp(-delta_e / temp)) {\n            a = std::move(next_a);\n            b = std::move(next_b);\n            current_error = neighbor_error;\n            current_t = std::move(neighbor_eval.t);\n            if (current_error < best_error) {\n                best_error = current_error;\n                best_a = a;\n                best_b = b;\n            }\n        }\n    }\n\n    // Output best solution found\n    for (int i = 0; i < N_CONST; ++i) {\n        std::cout << best_a[i] << \" \" << best_b[i] << \"\\n\";\n    }\n    \n    return 0;\n}","ahc045":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <set>\n#include <map>\n#include <queue>\n#include <tuple>\n#include <chrono>\n\n// Start timer\nauto start_time = std::chrono::high_resolution_clock::now();\ndouble time_limit = 1.95; // seconds\n\nstruct City {\n    int id;\n    long long lx, rx, ly, ry;\n    long long cx, cy;\n};\n\n// Z-order curve (Morton code)\nuint64_t z_order(uint32_t x, uint32_t y) {\n    uint64_t z = 0;\n    x &= 0x7FFF; // Max coord is 10000, 15 bits are enough\n    y &= 0x7FFF;\n    for (int i = 0; i < 15; ++i) {\n        z |= (static_cast<uint64_t>(x) & (1u << i)) << (i + 1);\n        z |= (static_cast<uint64_t>(y) & (1u << i)) << i;\n    }\n    return z;\n}\n\nstruct DSU {\n    std::vector<int> parent;\n    DSU(int n) {\n        parent.resize(n);\n        std::iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int i) {\n        if (parent[i] == i)\n            return i;\n        return parent[i] = find(parent[i]);\n    }\n    void unite(int i, int j) {\n        int root_i = find(i);\n        int root_j = find(j);\n        if (root_i != root_j) {\n            parent[root_i] = root_j;\n        }\n    }\n};\n\nlong long dist_sq(const City& a, const City& b) {\n    return (a.cx - b.cx) * (a.cx - b.cx) + (a.cy - b.cy) * (a.cy - b.cy);\n}\n\nstd::vector<std::pair<int, int>> do_query(const std::vector<int>& c) {\n    std::cout << \"? \" << c.size();\n    for (int city_id : c) {\n        std::cout << \" \" << city_id;\n    }\n    std::cout << std::endl;\n\n    std::vector<std::pair<int, int>> edges;\n    if (c.size() > 1) {\n        for (size_t i = 0; i < c.size() - 1; ++i) {\n            int u, v;\n            std::cin >> u >> v;\n            edges.emplace_back(u, v);\n        }\n    }\n    return edges;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\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<City> cities(N);\n    for (int i = 0; i < N; ++i) {\n        cities[i].id = i;\n        std::cin >> cities[i].lx >> cities[i].rx >> cities[i].ly >> cities[i].ry;\n        cities[i].cx = (cities[i].lx + cities[i].rx) / 2;\n        cities[i].cy = (cities[i].ly + cities[i].ry) / 2;\n    }\n\n    // 1. Grouping\n    std::vector<int> city_indices(N);\n    std::iota(city_indices.begin(), city_indices.end(), 0);\n    std::sort(city_indices.begin(), city_indices.end(), [&](int a, int b) {\n        return z_order(cities[a].cx, cities[a].cy) < z_order(cities[b].cx, cities[b].cy);\n    });\n    \n    std::vector<std::vector<int>> groups(M);\n    int current_city_idx = 0;\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < G[i]; ++j) {\n            groups[i].push_back(city_indices[current_city_idx++]);\n        }\n    }\n\n    // 2. Querying\n    int queries_left = Q;\n    std::vector<std::tuple<int, int, int>> all_edges; // u, v, group_idx\n\n    // Main query loop\n    for (int k = 0; k < M; ++k) {\n        if (queries_left == 0) break;\n        if (G[k] < 2) continue;\n        \n        const auto& current_group = groups[k];\n        \n        if (G[k] <= L) {\n            auto edges = do_query(current_group);\n            for (const auto& edge : edges) {\n                all_edges.emplace_back(edge.first, edge.second, k);\n            }\n            queries_left--;\n            continue;\n        }\n\n        int step = L - 1;\n        for (int i = 0; ; ++i) {\n             int start = i * step;\n             if (start >= G[k] - 1) break;\n             if (queries_left == 0) break;\n             \n             int end = std::min(start + L, G[k]);\n             if (end - start < 2) continue;\n             \n             std::vector<int> query_cities;\n             for (int j = start; j < end; ++j) {\n                 query_cities.push_back(current_group[j]);\n             }\n             auto edges = do_query(query_cities);\n             for (const auto& edge : edges) {\n                all_edges.emplace_back(edge.first, edge.second, k);\n             }\n             queries_left--;\n        }\n    }\n\n    // Improvement queries\n    std::mt19937 rng(0);\n    std::vector<int> large_groups_indices;\n    for(int i=0; i<M; ++i) {\n        if (G[i] > L) {\n            large_groups_indices.push_back(i);\n        }\n    }\n    \n    if (!large_groups_indices.empty()) {\n        int large_group_ptr = 0;\n        while(queries_left > 0) {\n            auto now = std::chrono::high_resolution_clock::now();\n            if (std::chrono::duration<double>(now - start_time).count() > time_limit) break;\n\n            int k = large_groups_indices[large_group_ptr];\n            const auto& current_group = groups[k];\n\n            std::vector<int> query_cities_indices(G[k]);\n            std::iota(query_cities_indices.begin(), query_cities_indices.end(), 0);\n            std::shuffle(query_cities_indices.begin(), query_cities_indices.end(), rng);\n            \n            std::vector<int> query_cities;\n            for(int i=0; i < std::min((int)query_cities_indices.size(), L); ++i) {\n                query_cities.push_back(current_group[query_cities_indices[i]]);\n            }\n            \n            if (query_cities.size() < 2) continue;\n            \n            auto edges = do_query(query_cities);\n            for (const auto& edge : edges) {\n                all_edges.emplace_back(edge.first, edge.second, k);\n            }\n            queries_left--;\n            large_group_ptr = (large_group_ptr + 1) % large_groups_indices.size();\n        }\n    }\n    \n    // 3. Output\n    std::cout << \"!\" << std::endl;\n    \n    for (int k = 0; k < M; ++k) {\n        for (size_t i = 0; i < groups[k].size(); ++i) {\n            std::cout << groups[k][i] << (i == groups[k].size() - 1 ? \"\" : \" \");\n        }\n        std::cout << std::endl;\n\n        if (G[k] > 1) {\n            std::vector<std::pair<int,int>> final_edges;\n            DSU dsu(N);\n            for (const auto& [u, v, group_idx] : all_edges) {\n                if (group_idx == k) {\n                    if (dsu.find(u) != dsu.find(v)) {\n                        dsu.unite(u, v);\n                        final_edges.emplace_back(u, v);\n                    }\n                }\n            }\n            \n            std::map<int, std::vector<int>> components;\n            for (int city_id : groups[k]) {\n                components[dsu.find(city_id)].push_back(city_id);\n            }\n\n            if (components.size() > 1) {\n                std::vector<std::tuple<long long, int, int>> candidate_edges;\n                auto it1 = components.begin();\n                while(it1 != components.end()){\n                    auto it2 = std::next(it1);\n                    while(it2 != components.end()){\n                        for(int u : it1->second){\n                            for(int v : it2->second){\n                                candidate_edges.emplace_back(dist_sq(cities[u], cities[v]), u, v);\n                            }\n                        }\n                        it2++;\n                    }\n                    it1++;\n                }\n                \n                std::sort(candidate_edges.begin(), candidate_edges.end());\n\n                for (const auto& [d_sq, u, v] : candidate_edges) {\n                    if (dsu.find(u) != dsu.find(v)) {\n                        dsu.unite(u, v);\n                        final_edges.emplace_back(u, v);\n                        if ((int)final_edges.size() == G[k] - 1) break;\n                    }\n                }\n            }\n            // For groups of size 2 we might not have queried if budget was low\n            if (G[k] == 2 && final_edges.empty()) {\n                 final_edges.emplace_back(groups[k][0], groups[k][1]);\n            }\n\n            for(const auto& edge : final_edges) {\n                std::cout << edge.first << \" \" << edge.second << std::endl;\n            }\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <map>\n#include <set>\n#include <cmath>\n#include <algorithm>\n#include <tuple>\n\nusing namespace std;\n\nconst int N = 20;\nconst int M = 40;\n\nstruct Pos {\n    int r, c;\n\n    bool operator<(const Pos& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n    bool operator==(const Pos& other) const {\n        return r == other.r && c == other.c;\n    }\n};\n\nint manhattan_distance(const Pos& a, const Pos& b) {\n    return abs(a.r - b.r) + abs(a.c - b.c);\n}\n\nbool is_valid(const Pos& p) {\n    return p.r >= 0 && p.r < N && p.c >= 0 && p.c < N;\n}\n\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\nconst char dir_char[] = {'U', 'D', 'L', 'R'};\n\nstruct Action {\n    char act, dir;\n};\n\nmap<Pos, int> dijkstra(const Pos& start, const set<Pos>& blocks) {\n    map<Pos, int> dist;\n    priority_queue<pair<int, Pos>, vector<pair<int, Pos>>, greater<pair<int, Pos>>> pq;\n\n    if (blocks.count(start)) return dist;\n\n    dist[start] = 0;\n    pq.push({0, start});\n\n    while (!pq.empty()) {\n        auto [cost, pos] = pq.top();\n        pq.pop();\n\n        if (cost > dist.at(pos)) {\n            continue;\n        }\n\n        // Move\n        for (int i = 0; i < 4; ++i) {\n            Pos next_pos = {pos.r + dr[i], pos.c + dc[i]};\n            if (is_valid(next_pos) && !blocks.count(next_pos)) {\n                int next_cost = cost + 1;\n                if (!dist.count(next_pos) || next_cost < dist.at(next_pos)) {\n                    dist[next_pos] = next_cost;\n                    pq.push({next_cost, next_pos});\n                }\n            }\n        }\n        \n        // Slide\n        for (int i = 0; i < 4; ++i) {\n            Pos stop_pos = pos;\n            Pos next_pos = {stop_pos.r + dr[i], stop_pos.c + dc[i]};\n            while (is_valid(next_pos) && !blocks.count(next_pos)) {\n                stop_pos = next_pos;\n                next_pos = {stop_pos.r + dr[i], stop_pos.c + dc[i]};\n            }\n            \n            if (stop_pos == pos) continue;\n\n            int next_cost = cost + 1;\n            if (!dist.count(stop_pos) || next_cost < dist.at(stop_pos)) {\n                dist[stop_pos] = next_cost;\n                pq.push({next_cost, stop_pos});\n            }\n        }\n    }\n    return dist;\n}\n\npair<int, vector<Action>> a_star_full(const Pos& start, const Pos& end, const set<Pos>& blocks) {\n    if (start == end) return {0, {}};\n    if (blocks.count(end)) return {1000000, {}};\n\n    map<Pos, int> dist;\n    map<Pos, Action> parent_action;\n    map<Pos, Pos> parent_pos;\n\n    priority_queue<pair<int, Pos>, vector<pair<int, Pos>>, greater<pair<int, Pos>>> pq;\n\n    dist[start] = 0;\n    pq.push({manhattan_distance(start, end), start});\n\n    while (!pq.empty()) {\n        auto [est_cost_pq, pos] = pq.top();\n        pq.pop();\n        \n        int cost = dist.at(pos);\n\n        if (pos == end) {\n            vector<Action> actions;\n            Pos curr = end;\n            while (!(curr == start)) {\n                actions.push_back(parent_action.at(curr));\n                curr = parent_pos.at(curr);\n            }\n            reverse(actions.begin(), actions.end());\n            return {cost, actions};\n        }\n\n        // Move\n        for (int i = 0; i < 4; ++i) {\n            Pos next_pos = {pos.r + dr[i], pos.c + dc[i]};\n            if (is_valid(next_pos) && !blocks.count(next_pos)) {\n                int next_cost = cost + 1;\n                if (!dist.count(next_pos) || next_cost < dist.at(next_pos)) {\n                    dist[next_pos] = next_cost;\n                    parent_pos[next_pos] = pos;\n                    parent_action[next_pos] = {'M', dir_char[i]};\n                    pq.push({next_cost + manhattan_distance(next_pos, end), next_pos});\n                }\n            }\n        }\n        \n        // Slide\n        for (int i = 0; i < 4; ++i) {\n            Pos stop_pos = pos;\n            Pos next_pos = {stop_pos.r + dr[i], stop_pos.c + dc[i]};\n            while (is_valid(next_pos) && !blocks.count(next_pos)) {\n                stop_pos = next_pos;\n                next_pos = {stop_pos.r + dr[i], stop_pos.c + dc[i]};\n            }\n            \n            if (stop_pos == pos) continue;\n\n            int next_cost = cost + 1;\n            if (!dist.count(stop_pos) || next_cost < dist.at(stop_pos)) {\n                dist[stop_pos] = next_cost;\n                parent_pos[stop_pos] = pos;\n                parent_action[stop_pos] = {'S', dir_char[i]};\n                pq.push({next_cost + manhattan_distance(stop_pos, end), stop_pos});\n            }\n        }\n    }\n\n    return {1000000, {}};\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N_in, M_in;\n    cin >> N_in >> M_in;\n\n    vector<Pos> targets(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> targets[i].r >> targets[i].c;\n    }\n\n    Pos current_pos = targets[0];\n    set<Pos> blocks;\n    vector<Action> total_actions;\n    \n    const int K = 20;\n\n    for (int k = 0; k < M - 1; ++k) {\n        Pos start_node = current_pos;\n        Pos end_node = targets[k + 1];\n\n        int best_cost = 1000000;\n        vector<Action> best_actions;\n        char best_plan_type = ' '; // B=base, A=add, R=remove\n        Pos best_alter_block, best_alter_adj;\n        \n        auto [base_cost, base_acts] = a_star_full(start_node, end_node, blocks);\n        if (base_cost < best_cost) {\n            best_cost = base_cost;\n            best_actions = base_acts;\n            best_plan_type = 'B';\n        }\n\n        auto dist_from_start = dijkstra(start_node, blocks);\n\n        set<Pos> cand_targets;\n        cand_targets.insert(end_node);\n        cand_targets.insert({start_node.r, end_node.c});\n        cand_targets.insert({end_node.r, start_node.c});\n        \n        set<Pos> cand_add_blocks;\n        for(const auto& t : cand_targets) {\n            for(int i=0; i<4; ++i) {\n                cand_add_blocks.insert({t.r + dr[i], t.c + dc[i]});\n            }\n        }\n\n        for (const auto& b : cand_add_blocks) {\n            if (!is_valid(b) || blocks.count(b)) continue;\n\n            set<Pos> next_blocks = blocks;\n            next_blocks.insert(b);\n            auto dist_to_end = dijkstra(end_node, next_blocks);\n            \n            for (int i = 0; i < 4; ++i) {\n                Pos adj_b = {b.r - dr[i], b.c - dc[i]};\n                if (!is_valid(adj_b) || blocks.count(adj_b)) continue;\n                \n                if (dist_from_start.count(adj_b) && dist_to_end.count(adj_b)) {\n                    int cost = dist_from_start.at(adj_b) + 1 + dist_to_end.at(adj_b);\n                    if (cost < best_cost) {\n                        best_cost = cost;\n                        best_plan_type = 'A';\n                        best_alter_block = b;\n                        best_alter_adj = adj_b;\n                    }\n                }\n            }\n        }\n\n        for (const auto& b : blocks) {\n            set<Pos> next_blocks = blocks;\n            next_blocks.erase(b);\n            auto dist_to_end = dijkstra(end_node, next_blocks);\n\n            for (int i = 0; i < 4; ++i) {\n                Pos adj_b = {b.r - dr[i], b.c - dc[i]};\n                if (!is_valid(adj_b) || blocks.count(adj_b)) continue;\n                \n                if (dist_from_start.count(adj_b) && dist_to_end.count(adj_b)) {\n                    int cost = dist_from_start.at(adj_b) + 1 + dist_to_end.at(adj_b);\n                     if (cost < best_cost) {\n                        best_cost = cost;\n                        best_plan_type = 'R';\n                        best_alter_block = b;\n                        best_alter_adj = adj_b;\n                    }\n                }\n            }\n        }\n        \n        if (best_cost >= 1000000) {\n            // Target is unreachable, just update position and hope for the best\n            // This case should ideally not happen in this problem\n        } else if (best_plan_type == 'B') {\n            total_actions.insert(total_actions.end(), best_actions.begin(), best_actions.end());\n        } else {\n            auto [c1, p1] = a_star_full(start_node, best_alter_adj, blocks);\n            total_actions.insert(total_actions.end(), p1.begin(), p1.end());\n            \n            char alter_dir = ' ';\n            for (int j = 0; j < 4; ++j) {\n                if (best_alter_block.r == best_alter_adj.r + dr[j] && best_alter_block.c == best_alter_adj.c + dc[j]) {\n                    alter_dir = dir_char[j];\n                    break;\n                }\n            }\n            total_actions.push_back({'A', alter_dir});\n\n            if (best_plan_type == 'A') {\n                blocks.insert(best_alter_block);\n            } else { // 'R'\n                blocks.erase(best_alter_block);\n            }\n            auto [c2, p2] = a_star_full(best_alter_adj, end_node, blocks);\n            total_actions.insert(total_actions.end(), p2.begin(), p2.end());\n        }\n        current_pos = end_node;\n\n        if (blocks.size() > K) {\n            Pos to_evict;\n            long long max_score = -1;\n\n            for (const auto& b : blocks) {\n                long long current_score = 0;\n                for (int i = k + 2; i < M; ++i) {\n                    current_score += manhattan_distance(b, targets[i]);\n                }\n                if (current_score > max_score) {\n                    max_score = current_score;\n                    to_evict = b;\n                }\n            }\n            \n            Pos adj_to_evict;\n            int min_dist = 1000000;\n            \n            auto dist_from_curr = dijkstra(current_pos, blocks);\n            \n            for (int i = 0; i < 4; ++i) {\n                Pos adj_b = {to_evict.r - dr[i], to_evict.c - dc[i]};\n                if (is_valid(adj_b) && !blocks.count(adj_b)) {\n                    if (dist_from_curr.count(adj_b)) {\n                        int d = dist_from_curr.at(adj_b);\n                        if (d < min_dist) {\n                            min_dist = d;\n                            adj_to_evict = adj_b;\n                        }\n                    }\n                }\n            }\n\n            if (min_dist < 1000000) {\n                auto [c, p] = a_star_full(current_pos, adj_to_evict, blocks);\n                total_actions.insert(total_actions.end(), p.begin(), p.end());\n                current_pos = adj_to_evict;\n\n                char alter_dir = ' ';\n                 for (int j = 0; j < 4; ++j) {\n                    if (to_evict.r == current_pos.r + dr[j] && to_evict.c == current_pos.c + dc[j]) {\n                        alter_dir = dir_char[j];\n                        break;\n                    }\n                }\n                total_actions.push_back({'A', alter_dir});\n                blocks.erase(to_evict);\n            }\n        }\n    }\n\n    for (const auto& action : total_actions) {\n        cout << action.act << \" \" << action.dir << \"\\n\";\n    }\n\n    return 0;\n}"},"4":{"ahc001":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <cfloat>\n#include <chrono>\n#include <random>\n\n// --- Utilities and Structs ---\nstruct Company {\n    int id;\n    int x, y;\n    long long r;\n};\n\nstruct Rect {\n    int x1, y1, x2, y2;\n};\n\nstruct PointBox {\n    int min_x = 10001, min_y = 10001, max_x = -1, max_y = -1;\n    void update(const Company& c) {\n        min_x = std::min(min_x, c.x);\n        min_y = std::min(min_y, c.y);\n        max_x = std::max(max_x, c.x);\n        max_y = std::max(max_y, c.y);\n    }\n    void merge(const PointBox& other) {\n        min_x = std::min(min_x, other.min_x);\n        min_y = std::min(min_y, other.min_y);\n        max_x = std::max(max_x, other.max_x);\n        max_y = std::max(max_y, other.max_y);\n    }\n};\n\nstruct Node {\n    bool is_leaf = false;\n    int company_id = -1;\n\n    // For internal nodes\n    int parent = -1;\n    bool is_vertical = false;\n    int split_coord = 0;\n    int children[2] = {-1, -1};\n    std::vector<int> company_indices;\n    PointBox pbox;\n};\n\n// --- Global State ---\nint N;\nstd::vector<Company> companies;\nstd::vector<bool> is_in_partition1; // Temporary helper for partitioning\n\n// --- For SA ---\nstd::vector<Node> tree;\nstd::vector<int> internal_node_indices;\nstd::mt19937 rnd;\nstd::chrono::time_point<std::chrono::high_resolution_clock> start_time_chrono;\nstd::vector<Rect> best_result;\ndouble best_score = -1.0;\nstd::vector<Rect> current_result;\ndouble current_score;\n\n// --- Helper Functions ---\ndouble get_time() {\n    return std::chrono::duration<double>(std::chrono::high_resolution_clock::now() - start_time_chrono).count();\n}\n\ndouble calculate_satisfaction(long long s, long long r) {\n    if (s <= 0 || r <= 0) return 0;\n    double ratio = std::min((double)s / r, (double)r / s);\n    double error = 1.0 - ratio;\n    return 1.0 - error * error;\n}\n\ndouble calculate_total_score(const std::vector<Rect>& rects) {\n    double total_sat = 0;\n    for (int i = 0; i < N; ++i) {\n        long long s = (long long)(rects[i].x2 - rects[i].x1) * (rects[i].y2 - rects[i].y1);\n        total_sat += calculate_satisfaction(s, companies[i].r);\n    }\n    return total_sat;\n}\n\n// --- Core Algorithm: Greedy Construction + SA ---\n\nint build_tree(int x1, int y1, int x2, int y2, std::vector<int>& indices_by_x, std::vector<int>& indices_by_y, int parent_idx) {\n    int n = indices_by_x.size();\n    int current_node_idx = tree.size();\n    tree.emplace_back();\n    tree[current_node_idx].parent = parent_idx;\n    \n    if (n == 0) return -1;\n\n    if (n == 1) {\n        int company_idx = indices_by_x[0];\n        tree[current_node_idx].is_leaf = true;\n        tree[current_node_idx].company_id = company_idx;\n        tree[current_node_idx].company_indices = {company_idx};\n        tree[current_node_idx].pbox.update(companies[company_idx]);\n        return current_node_idx;\n    }\n\n    int best_k_v = -1, best_x_split = -1;\n    double min_badness_v = DBL_MAX;\n    long long total_r = 0;\n    for (int idx : indices_by_x) total_r += companies[idx].r;\n    \n    if (companies[indices_by_x.front()].x < companies[indices_by_x.back()].x) {\n        long long current_r_sum = 0;\n        for (int k = 1; k < n; ++k) {\n            current_r_sum += companies[indices_by_x[k - 1]].r;\n            if (companies[indices_by_x[k - 1]].x < companies[indices_by_x[k]].x) {\n                double target_ratio = (double)current_r_sum / total_r;\n                double ideal_x_split = x1 + (double)(x2 - x1) * target_ratio;\n                int lower_bound = companies[indices_by_x[k - 1]].x + 1;\n                int upper_bound = companies[indices_by_x[k]].x;\n                \n                std::vector<int> candidates;\n                candidates.push_back(std::max(lower_bound, std::min(upper_bound, (int)round(ideal_x_split))));\n                candidates.push_back(lower_bound);\n                candidates.push_back(upper_bound);\n                std::sort(candidates.begin(), candidates.end());\n                candidates.erase(std::unique(candidates.begin(), candidates.end()), candidates.end());\n\n                for (int x_split : candidates) {\n                    double actual_ratio = (x2 - x1 == 0) ? 0.5 : (double)(x_split - x1) / (x2 - x1);\n                    double badness = std::pow(actual_ratio - target_ratio, 2);\n                    if (badness < min_badness_v) {\n                        min_badness_v = badness;\n                        best_k_v = k;\n                        best_x_split = x_split;\n                    }\n                }\n            }\n        }\n    }\n\n    int best_k_h = -1, best_y_split = -1;\n    double min_badness_h = DBL_MAX;\n    if (companies[indices_by_y.front()].y < companies[indices_by_y.back()].y) {\n        long long current_r_sum = 0;\n        for (int k = 1; k < n; ++k) {\n            current_r_sum += companies[indices_by_y[k - 1]].r;\n            if (companies[indices_by_y[k - 1]].y < companies[indices_by_y[k]].y) {\n                double target_ratio = (double)current_r_sum / total_r;\n                double ideal_y_split = y1 + (double)(y2 - y1) * target_ratio;\n                int lower_bound = companies[indices_by_y[k - 1]].y + 1;\n                int upper_bound = companies[indices_by_y[k]].y;\n\n                std::vector<int> candidates;\n                candidates.push_back(std::max(lower_bound, std::min(upper_bound, (int)round(ideal_y_split))));\n                candidates.push_back(lower_bound);\n                candidates.push_back(upper_bound);\n                std::sort(candidates.begin(), candidates.end());\n                candidates.erase(std::unique(candidates.begin(), candidates.end()), candidates.end());\n                \n                for (int y_split : candidates) {\n                     double actual_ratio = (y2 - y1 == 0) ? 0.5 : (double)(y_split - y1) / (y2 - y1);\n                     double badness = std::pow(actual_ratio - target_ratio, 2);\n                     if (badness < min_badness_h) {\n                         min_badness_h = badness;\n                         best_k_h = k;\n                         best_y_split = y_split;\n                     }\n                }\n            }\n        }\n    }\n\n    bool perform_vertical_split = (x2 - x1) >= (y2 - y1);\n    if (best_k_v != -1 && best_k_h == -1) perform_vertical_split = true;\n    else if (best_k_v == -1 && best_k_h != -1) perform_vertical_split = false;\n    else if (best_k_v != -1 && best_k_h != -1) {\n        if (min_badness_v < min_badness_h) perform_vertical_split = true;\n        else if (min_badness_h < min_badness_v) perform_vertical_split = false;\n    }\n    \n    internal_node_indices.push_back(current_node_idx);\n    tree[current_node_idx].is_vertical = perform_vertical_split;\n    \n    if (perform_vertical_split) {\n        tree[current_node_idx].split_coord = best_x_split;\n        int k = best_k_v;\n        for (int i = 0; i < k; ++i) is_in_partition1[indices_by_x[i]] = true;\n        for (int i = k; i < n; ++i) is_in_partition1[indices_by_x[i]] = false;\n\n        std::vector<int> left_x(indices_by_x.begin(), indices_by_x.begin() + k);\n        std::vector<int> right_x(indices_by_x.begin() + k, indices_by_x.end());\n        std::vector<int> left_y, right_y;\n        for (int idx : indices_by_y) (is_in_partition1[idx] ? left_y : right_y).push_back(idx);\n\n        tree[current_node_idx].children[0] = build_tree(x1, y1, best_x_split, y2, left_x, left_y, current_node_idx);\n        tree[current_node_idx].children[1] = build_tree(best_x_split, y1, x2, y2, right_x, right_y, current_node_idx);\n    } else {\n        tree[current_node_idx].split_coord = best_y_split;\n        int k = best_k_h;\n        for (int i = 0; i < k; ++i) is_in_partition1[indices_by_y[i]] = true;\n        for (int i = k; i < n; ++i) is_in_partition1[indices_by_y[i]] = false;\n        \n        std::vector<int> bottom_y(indices_by_y.begin(), indices_by_y.begin() + k);\n        std::vector<int> top_y(indices_by_y.begin() + k, indices_by_y.end());\n        std::vector<int> bottom_x, top_x;\n        for (int idx : indices_by_x) (is_in_partition1[idx] ? bottom_x : top_x).push_back(idx);\n        \n        tree[current_node_idx].children[0] = build_tree(x1, y1, x2, best_y_split, bottom_x, bottom_y, current_node_idx);\n        tree[current_node_idx].children[1] = build_tree(x1, best_y_split, x2, y2, top_x, top_y, current_node_idx);\n    }\n\n    tree[current_node_idx].pbox = tree[tree[current_node_idx].children[0]].pbox;\n    tree[current_node_idx].pbox.merge(tree[tree[current_node_idx].children[1]].pbox);\n    tree[current_node_idx].company_indices = tree[tree[current_node_idx].children[0]].company_indices;\n    tree[current_node_idx].company_indices.insert(\n        tree[current_node_idx].company_indices.end(),\n        tree[tree[current_node_idx].children[1]].company_indices.begin(),\n        tree[tree[current_node_idx].children[1]].company_indices.end()\n    );\n\n    return current_node_idx;\n}\n\nvoid recompute_rects(int node_idx, const Rect& bbox, std::vector<Rect>& target_rects) {\n    if (node_idx == -1) return;\n    const auto& node = tree[node_idx];\n    if (node.is_leaf) {\n        target_rects[node.company_id] = bbox;\n        return;\n    }\n    if (node.is_vertical) {\n        recompute_rects(node.children[0], {bbox.x1, bbox.y1, node.split_coord, bbox.y2}, target_rects);\n        recompute_rects(node.children[1], {node.split_coord, bbox.y1, bbox.x2, bbox.y2}, target_rects);\n    } else {\n        recompute_rects(node.children[0], {bbox.x1, bbox.y1, bbox.x2, node.split_coord}, target_rects);\n        recompute_rects(node.children[1], {bbox.x1, node.split_coord, bbox.x2, bbox.y2}, target_rects);\n    }\n}\n\nRect get_bbox(int node_idx) {\n    if (tree[node_idx].parent == -1) return {0, 0, 10000, 10000};\n    const auto& parent = tree[tree[node_idx].parent];\n    Rect parent_bbox = get_bbox(tree[node_idx].parent);\n    bool is_child0 = (parent.children[0] == node_idx);\n    if (parent.is_vertical) {\n        return is_child0 ? Rect{parent_bbox.x1, parent_bbox.y1, parent.split_coord, parent_bbox.y2}\n                         : Rect{parent.split_coord, parent_bbox.y1, parent_bbox.x2, parent_bbox.y2};\n    } else {\n        return is_child0 ? Rect{parent_bbox.x1, parent_bbox.y1, parent_bbox.x2, parent.split_coord}\n                         : Rect{parent_bbox.x1, parent.split_coord, parent_bbox.x2, parent_bbox.y2};\n    }\n}\n\n\nvoid simulated_annealing() {\n    const double TIME_LIMIT = 4.95;\n    \n    current_score = calculate_total_score(current_result);\n    best_score = current_score;\n    best_result = current_result;\n    \n    double T_start = 0.05, T_end = 1e-9;\n    \n    std::uniform_int_distribution<int> node_dist(0, internal_node_indices.size() - 1);\n    std::uniform_real_distribution<double> accept_dist(0.0, 1.0);\n\n    while (true) {\n        double elapsed_time = get_time();\n        if (elapsed_time > TIME_LIMIT) break;\n\n        int node_idx = internal_node_indices[node_dist(rnd)];\n        auto& node = tree[node_idx];\n        \n        int c_old = node.split_coord;\n        int c_min, c_max;\n        if (node.is_vertical) {\n            c_min = tree[node.children[0]].pbox.max_x + 1;\n            c_max = tree[node.children[1]].pbox.min_x;\n        } else {\n            c_min = tree[node.children[0]].pbox.max_y + 1;\n            c_max = tree[node.children[1]].pbox.min_y;\n        }\n        \n        if (c_min > c_max) continue;\n        \n        double progress = elapsed_time / TIME_LIMIT;\n        \n        Rect bbox = get_bbox(node_idx);\n        double dim_size = node.is_vertical ? (bbox.x2 - bbox.x1) : (bbox.y2 - bbox.y1);\n        double W = std::max(1.0, 20.0 * sqrt(dim_size) * (1.0 - progress));\n        \n        std::uniform_int_distribution<int> delta_dist(-(int)W, (int)W);\n        int c_new = c_old + delta_dist(rnd);\n        c_new = std::max(c_min, std::min(c_max, c_new));\n\n        if (c_new == c_old) continue;\n        \n        double score_before_move = 0;\n        double score_after_move = 0;\n\n        for (int company_idx : node.company_indices) {\n            const auto& rect = current_result[company_idx];\n            long long s = (long long)(rect.x2 - rect.x1) * (rect.y2 - rect.y1);\n            score_before_move += calculate_satisfaction(s, companies[company_idx].r);\n        }\n\n        node.split_coord = c_new;\n        recompute_rects(node_idx, bbox, current_result);\n        \n        for (int company_idx : node.company_indices) {\n            const auto& rect = current_result[company_idx];\n            long long s = (long long)(rect.x2 - rect.x1) * (rect.y2 - rect.y1);\n            score_after_move += calculate_satisfaction(s, companies[company_idx].r);\n        }\n\n        double delta_score = score_after_move - score_before_move;\n        double T = T_start * std::pow(T_end / T_start, progress);\n\n        if (delta_score > 0 || accept_dist(rnd) < std::exp(delta_score / T)) { // Accept\n            current_score += delta_score;\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_result = current_result;\n            }\n        } else { // Reject\n            node.split_coord = c_old;\n            recompute_rects(node_idx, bbox, current_result); // Revert changes\n        }\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    start_time_chrono = std::chrono::high_resolution_clock::now();\n    \n    rnd.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());\n    \n    std::cin >> N;\n    companies.resize(N);\n    is_in_partition1.resize(N);\n    tree.reserve(2 * N);\n\n    std::vector<int> indices_by_x(N), indices_by_y(N);\n    for (int i = 0; i < N; ++i) {\n        companies[i].id = i;\n        std::cin >> companies[i].x >> companies[i].y >> companies[i].r;\n        indices_by_x[i] = i;\n        indices_by_y[i] = i;\n    }\n\n    std::sort(indices_by_x.begin(), indices_by_x.end(), [&](int a, int b) {\n        if (companies[a].x != companies[b].x) return companies[a].x < companies[b].x;\n        return companies[a].y < companies[b].y;\n    });\n    std::sort(indices_by_y.begin(), indices_by_y.end(), [&](int a, int b) {\n        if (companies[a].y != companies[b].y) return companies[a].y < companies[b].y;\n        return companies[a].x < companies[b].x;\n    });\n\n    int root_node = build_tree(0, 0, 10000, 10000, indices_by_x, indices_by_y, -1);\n    \n    current_result.resize(N);\n    recompute_rects(root_node, {0, 0, 10000, 10000}, current_result);\n\n    simulated_annealing();\n\n    for (int i = 0; i < N; ++i) {\n        std::cout << best_result[i].x1 << \" \" << best_result[i].y1 << \" \" << best_result[i].x2 << \" \" << best_result[i].y2 << \"\\n\";\n    }\n\n    return 0;\n}","ahc002":"#include <iostream>\n#include <vector>\n#include <string>\n#include <map>\n#include <utility>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n\n// Fast I/O\nvoid fast_io() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n}\n\n// Timer\nstruct Timer {\n    std::chrono::steady_clock::time_point start_time;\n    Timer() : start_time(std::chrono::steady_clock::now()) {}\n    long long get_ms() {\n        return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count();\n    }\n};\n\nconstexpr int N = 50;\n\n#ifdef LOCAL_TEST\nconstexpr int TIME_LIMIT_MS = 1980;\nconstexpr int BEAM_WIDTH = 200;\n#else\nconstexpr int TIME_LIMIT_MS = 1980;\nconstexpr int BEAM_WIDTH = 2000;\n#endif\n\nint si, sj;\nint t[N][N];\nint p[N][N];\n\nstruct Tile {\n    int id;\n    std::vector<std::pair<int, int>> squares;\n};\n\nint tile_id_map[N][N];\nstd::vector<Tile> tiles;\nint M; // number of tiles\n\nstruct State {\n    long long score;\n    std::pair<int, int> pos;\n    std::vector<bool> visited_tiles;\n\n    int prev_idx_in_history;\n    std::string path_segment;\n};\n\nchar get_move_char(const std::pair<int, int>& from, const std::pair<int, int>& to) {\n    if (to.first == from.first - 1 && to.second == from.second) return 'U';\n    if (to.first == from.first + 1 && to.second == from.second) return 'D';\n    if (to.second == from.second - 1 && to.first == from.first) return 'L';\n    if (to.second == from.second + 1 && to.first == from.first) return 'R';\n    return ' '; // Should not happen\n}\n\nvoid solve() {\n    Timer timer;\n\n    std::cin >> si >> sj;\n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) std::cin >> t[i][j];\n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) std::cin >> p[i][j];\n\n    std::map<int, int> raw_id_to_my_id;\n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) {\n        if (raw_id_to_my_id.find(t[i][j]) == raw_id_to_my_id.end()) {\n            raw_id_to_my_id[t[i][j]] = raw_id_to_my_id.size();\n        }\n    }\n    M = raw_id_to_my_id.size();\n    tiles.resize(M);\n    for (int i=0; i<M; ++i) tiles[i].id = i;\n\n    for (int i=0; i<N; ++i) for(int j=0; j<N; ++j) {\n        int my_id = raw_id_to_my_id[t[i][j]];\n        tile_id_map[i][j] = my_id;\n        tiles[my_id].squares.push_back({i,j});\n    }\n\n    State initial_state;\n    int start_tile_id = tile_id_map[si][sj];\n    const auto& start_tile = tiles[start_tile_id];\n    \n    initial_state.score = 0;\n    initial_state.visited_tiles.assign(M, false);\n    initial_state.visited_tiles[start_tile_id] = true;\n    initial_state.prev_idx_in_history = -1;\n\n    std::pair<int, int> current_pos = {si, sj};\n    initial_state.score += p[si][sj];\n\n    if (start_tile.squares.size() == 2) {\n        std::pair<int, int> other_pos = (start_tile.squares[0] == current_pos) ? start_tile.squares[1] : start_tile.squares[0];\n        char move = get_move_char(current_pos, other_pos);\n        initial_state.path_segment += move;\n        initial_state.score += p[other_pos.first][other_pos.second];\n        current_pos = other_pos;\n    }\n    initial_state.pos = current_pos;\n\n    long long best_score = initial_state.score;\n    std::pair<int, int> best_state_locus = {0, 0};\n\n    std::vector<std::vector<State>> history;\n    std::vector<State> beam;\n    beam.push_back(std::move(initial_state));\n    history.push_back(std::move(beam));\n    \n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n    char move_chars[] = {'U', 'D', 'L', 'R'};\n\n    while (timer.get_ms() < TIME_LIMIT_MS) {\n        const auto& current_beam = history.back();\n        std::vector<State> candidates;\n        \n        for (int i = 0; i < current_beam.size(); ++i) {\n            const auto& s = current_beam[i];\n            int r = s.pos.first;\n            int c = s.pos.second;\n\n            for (int k = 0; k < 4; ++k) {\n                int nr = r + dr[k];\n                int nc = c + dc[k];\n\n                if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n\n                int next_tile_id = tile_id_map[nr][nc];\n                if (s.visited_tiles[next_tile_id]) continue;\n\n                State new_s;\n                new_s.visited_tiles = s.visited_tiles;\n                new_s.visited_tiles[next_tile_id] = true;\n\n                std::string path_ext;\n                long long score_ext = 0;\n                std::pair<int, int> next_pos = {nr, nc};\n\n                path_ext += move_chars[k];\n                score_ext += p[nr][nc];\n\n                const auto& next_tile = tiles[next_tile_id];\n                if (next_tile.squares.size() == 2) {\n                    std::pair<int, int> other_pos = (next_tile.squares[0] == next_pos) ? next_tile.squares[1] : next_tile.squares[0];\n                    char move = get_move_char(next_pos, other_pos);\n                    path_ext += move;\n                    score_ext += p[other_pos.first][other_pos.second];\n                    next_pos = other_pos;\n                }\n                \n                new_s.score = s.score + score_ext;\n                new_s.pos = next_pos;\n                new_s.path_segment = path_ext;\n                new_s.prev_idx_in_history = i;\n                candidates.push_back(std::move(new_s));\n            }\n        }\n\n        if (candidates.empty()) break;\n\n        size_t sort_end_idx = std::min((size_t)candidates.size(), (size_t)BEAM_WIDTH);\n        std::partial_sort(candidates.begin(), candidates.begin() + sort_end_idx, candidates.end(), \n            [](const State& a, const State& b){ return a.score > b.score; });\n\n        std::vector<State> next_beam;\n        next_beam.reserve(sort_end_idx);\n        for (int i = 0; i < sort_end_idx; ++i) {\n            next_beam.push_back(std::move(candidates[i]));\n        }\n        \n        if (next_beam[0].score > best_score) {\n            best_score = next_beam[0].score;\n            best_state_locus = {(int)history.size(), 0};\n        }\n        history.push_back(std::move(next_beam));\n    }\n    \n    std::string final_path = \"\";\n    int hist_idx = best_state_locus.first;\n    int beam_idx = best_state_locus.second;\n    while (hist_idx >= 0) {\n        const auto& s = history[hist_idx][beam_idx];\n        final_path = s.path_segment + final_path;\n        if (s.prev_idx_in_history == -1) break;\n        beam_idx = s.prev_idx_in_history;\n        hist_idx--;\n    }\n    std::cout << final_path << std::endl;\n}\n\nint main() {\n    fast_io();\n    solve();\n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <numeric>\n#include <random>\n#include <algorithm>\n#include <iomanip>\n#include <chrono>\n\n// Constants\nconstexpr int GRID_SIZE = 30;\nconstexpr int NUM_QUERIES = 1000;\n\n// Grid coordinates\nstruct Point {\n    int r, c;\n    bool operator==(const Point& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Point& other) const {\n        return !(*this == other);\n    }\n};\n\n// For priority queue in Dijkstra\nstruct State {\n    Point pos;\n    double dist;\n\n    bool operator>(const State& other) const {\n        return dist > other.dist;\n    }\n};\n\n// Global state for our estimates and models\ndouble est_h[GRID_SIZE][GRID_SIZE - 1]; // Raw estimates\ndouble est_v[GRID_SIZE - 1][GRID_SIZE];\ndouble model_h[GRID_SIZE][GRID_SIZE - 1]; // Smoothed/model-based estimates\ndouble model_v[GRID_SIZE - 1][GRID_SIZE];\nint updates_h[GRID_SIZE][GRID_SIZE - 1];\nint updates_v[GRID_SIZE - 1][GRID_SIZE];\n\n// Randomness\nstd::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// Helper function to check bounds\nbool is_valid(int r, int c) {\n    return r >= 0 && r < GRID_SIZE && c >= 0 && c < GRID_SIZE;\n}\n\n// Dijkstra's algorithm\nPoint parent[GRID_SIZE][GRID_SIZE];\nchar move_char[GRID_SIZE][GRID_SIZE];\ndouble dist[GRID_SIZE][GRID_SIZE];\n\nstd::string find_path(Point start, Point goal, int k) {\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            dist[i][j] = 1e18;\n        }\n    }\n\n    std::priority_queue<State, std::vector<State>, std::greater<State>> pq;\n\n    dist[start.r][start.c] = 0;\n    pq.push({start, 0.0});\n\n    double progress = static_cast<double>(k) / (NUM_QUERIES - 1);\n    double C_k = 0.3 * (1.0 - std::pow(progress, 1.5));\n    if (k > NUM_QUERIES - 50) C_k = 0;\n\n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n    char moves[] = {'U', 'D', 'L', 'R'};\n\n    while (!pq.empty()) {\n        State current = pq.top();\n        pq.pop();\n\n        Point pos = current.pos;\n\n        if (current.dist > dist[pos.r][pos.c]) {\n            continue;\n        }\n\n        if (pos == goal) {\n            break;\n        }\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = pos.r + dr[i];\n            int nc = pos.c + dc[i];\n\n            if (!is_valid(nr, nc)) {\n                continue;\n            }\n\n            double edge_cost;\n            if (i == 0) { // Up\n                edge_cost = model_v[nr][nc];\n            } else if (i == 1) { // Down\n                edge_cost = model_v[pos.r][pos.c];\n            } else if (i == 2) { // Left\n                edge_cost = model_h[nr][nc];\n            } else { // Right\n                edge_cost = model_h[pos.r][pos.c];\n            }\n            \n            std::uniform_real_distribution<double> dist_expl(1.0 - C_k, 1.0 + C_k);\n            double noisy_cost = edge_cost * dist_expl(rng);\n            \n            if (dist[pos.r][pos.c] + noisy_cost < dist[nr][nc]) {\n                dist[nr][nc] = dist[pos.r][pos.c] + noisy_cost;\n                parent[nr][nc] = pos;\n                move_char[nr][nc] = moves[i];\n                pq.push({{nr, nc}, dist[nr][nc]});\n            }\n        }\n    }\n\n    std::string path_str = \"\";\n    Point current = goal;\n    while (current != start) {\n        path_str += move_char[current.r][current.c];\n        current = parent[current.r][current.c];\n    }\n    std::reverse(path_str.begin(), path_str.end());\n    return path_str;\n}\n\nvoid update_estimates(const std::string& path_str, Point start, long long noisy_path_length, int k) {\n    if (path_str.empty()) return;\n\n    double estimated_length = 0;\n    double Z = 0.0;\n    \n    Point current = start;\n    // First pass: calculate estimated length and normalization factor Z for weighted SGD\n    for (char move : path_str) {\n        Point next = current;\n        if (move == 'U') {\n            next.r--;\n            estimated_length += est_v[next.r][next.c];\n            Z += 1.0 / (updates_v[next.r][next.c] + 1.0);\n        } else if (move == 'D') {\n            estimated_length += est_v[current.r][current.c];\n            Z += 1.0 / (updates_v[current.r][current.c] + 1.0);\n            next.r++;\n        } else if (move == 'L') {\n            next.c--;\n            estimated_length += est_h[next.r][next.c];\n            Z += 1.0 / (updates_h[next.r][next.c] + 1.0);\n        } else if (move == 'R') {\n            estimated_length += est_h[current.r][current.c];\n            Z += 1.0 / (updates_h[current.r][current.c] + 1.0);\n            next.c++;\n        }\n        current = next;\n    }\n    \n    if (Z < 1e-9) return;\n\n    double error = static_cast<double>(noisy_path_length) - estimated_length;\n    double alpha_k = 0.5 * std::pow(0.01, static_cast<double>(k) / (NUM_QUERIES - 1));\n    double base_update = alpha_k * error / Z;\n\n    current = start;\n    // Second pass: apply updates\n    for (char move : path_str) {\n        Point next = current;\n        if (move == 'U') {\n            next.r--;\n            double weight = 1.0 / (updates_v[next.r][next.c] + 1.0);\n            est_v[next.r][next.c] += base_update * weight;\n            est_v[next.r][next.c] = std::clamp(est_v[next.r][next.c], 100.0, 15000.0);\n            updates_v[next.r][next.c]++;\n        } else if (move == 'D') {\n            double weight = 1.0 / (updates_v[current.r][current.c] + 1.0);\n            est_v[current.r][current.c] += base_update * weight;\n            est_v[current.r][current.c] = std::clamp(est_v[current.r][current.c], 100.0, 15000.0);\n            updates_v[current.r][current.c]++;\n            next.r++;\n        } else if (move == 'L') {\n            next.c--;\n            double weight = 1.0 / (updates_h[next.r][next.c] + 1.0);\n            est_h[next.r][next.c] += base_update * weight;\n            est_h[next.r][next.c] = std::clamp(est_h[next.r][next.c], 100.0, 15000.0);\n            updates_h[next.r][next.c]++;\n        } else if (move == 'R') {\n            double weight = 1.0 / (updates_h[current.r][current.c] + 1.0);\n            est_h[current.r][current.c] += base_update * weight;\n            est_h[current.r][current.c] = std::clamp(est_h[current.r][current.c], 100.0, 15000.0);\n            updates_h[current.r][current.c]++;\n            next.c++;\n        }\n        current = next;\n    }\n}\n\nvoid update_model() {\n    // Horizontal edges\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        std::vector<double> val_pref(GRID_SIZE - 1, 0.0);\n        std::vector<double> sq_val_pref(GRID_SIZE - 1, 0.0);\n        std::vector<int> count_pref(GRID_SIZE - 1, 0);\n\n        if (updates_h[i][0] > 0) {\n            val_pref[0] = est_h[i][0];\n            sq_val_pref[0] = est_h[i][0] * est_h[i][0];\n            count_pref[0] = 1;\n        }\n        for (int j = 1; j < GRID_SIZE - 1; ++j) {\n            val_pref[j] = val_pref[j - 1];\n            sq_val_pref[j] = sq_val_pref[j - 1];\n            count_pref[j] = count_pref[j - 1];\n            if (updates_h[i][j] > 0) {\n                val_pref[j] += est_h[i][j];\n                sq_val_pref[j] += est_h[i][j] * est_h[i][j];\n                count_pref[j]++;\n            }\n        }\n\n        int total_count = count_pref[GRID_SIZE - 2];\n        if (total_count == 0) continue;\n\n        double total_sum = val_pref[GRID_SIZE - 2];\n        double total_sq_sum = sq_val_pref[GRID_SIZE - 2];\n        double mean1 = total_sum / total_count;\n        double sse1 = total_sq_sum - total_sum * mean1;\n\n        for (int j = 0; j < GRID_SIZE - 1; ++j) model_h[i][j] = mean1;\n        \n        if (total_count >= 2) {\n            double best_sse2 = 1e18;\n            int best_split = -1;\n            double best_mean_l = 0, best_mean_r = 0;\n\n            for (int split = 1; split < GRID_SIZE - 1; ++split) {\n                int count_l = count_pref[split - 1];\n                int count_r = total_count - count_l;\n                if (count_l < 1 || count_r < 1) continue;\n\n                double sum_l = val_pref[split - 1];\n                double sq_sum_l = sq_val_pref[split - 1];\n                double mean_l = sum_l / count_l;\n                double sse_l = sq_sum_l - sum_l * mean_l;\n\n                double sum_r = total_sum - sum_l;\n                double sq_sum_r = total_sq_sum - sq_sum_l;\n                double mean_r = sum_r / count_r;\n                double sse_r = sq_sum_r - sum_r * mean_r;\n                \n                if (sse_l + sse_r < best_sse2) {\n                    best_sse2 = sse_l + sse_r;\n                    best_split = split;\n                    best_mean_l = mean_l;\n                    best_mean_r = mean_r;\n                }\n            }\n\n            if (best_split != -1 && sse1 > 1e-9) {\n                if (total_count * log(best_sse2 / sse1) < -log(static_cast<double>(total_count))) {\n                    for (int j = 0; j < best_split; ++j) model_h[i][j] = best_mean_l;\n                    for (int j = best_split; j < GRID_SIZE - 1; ++j) model_h[i][j] = best_mean_r;\n                }\n            }\n        }\n    }\n\n    // Vertical edges\n    for (int j = 0; j < GRID_SIZE; ++j) {\n        std::vector<double> val_pref(GRID_SIZE - 1, 0.0);\n        std::vector<double> sq_val_pref(GRID_SIZE - 1, 0.0);\n        std::vector<int> count_pref(GRID_SIZE - 1, 0);\n\n        if (updates_v[0][j] > 0) {\n            val_pref[0] = est_v[0][j];\n            sq_val_pref[0] = est_v[0][j] * est_v[0][j];\n            count_pref[0] = 1;\n        }\n        for (int i = 1; i < GRID_SIZE - 1; ++i) {\n            val_pref[i] = val_pref[i - 1];\n            sq_val_pref[i] = sq_val_pref[i - 1];\n            count_pref[i] = count_pref[i - 1];\n            if (updates_v[i][j] > 0) {\n                val_pref[i] += est_v[i][j];\n                sq_val_pref[i] += est_v[i][j] * est_v[i][j];\n                count_pref[i]++;\n            }\n        }\n\n        int total_count = count_pref[GRID_SIZE - 2];\n        if (total_count == 0) continue;\n\n        double total_sum = val_pref[GRID_SIZE - 2];\n        double total_sq_sum = sq_val_pref[GRID_SIZE - 2];\n        double mean1 = total_sum / total_count;\n        double sse1 = total_sq_sum - total_sum * mean1;\n        \n        for (int i = 0; i < GRID_SIZE - 1; ++i) model_v[i][j] = mean1;\n        \n        if (total_count >= 2) {\n            double best_sse2 = 1e18;\n            int best_split = -1;\n            double best_mean_u = 0, best_mean_d = 0;\n\n            for (int split = 1; split < GRID_SIZE - 1; ++split) {\n                int count_u = count_pref[split - 1];\n                int count_d = total_count - count_u;\n                if (count_u < 1 || count_d < 1) continue;\n\n                double sum_u = val_pref[split - 1];\n                double sq_sum_u = sq_val_pref[split - 1];\n                double mean_u = sum_u / count_u;\n                double sse_u = sq_sum_u - sum_u * mean_u;\n\n                double sum_d = total_sum - sum_u;\n                double sq_sum_d = total_sq_sum - sq_sum_u;\n                double mean_d = sum_d / count_d;\n                double sse_d = sq_sum_d - sum_d * mean_d;\n                \n                if (sse_u + sse_d < best_sse2) {\n                    best_sse2 = sse_u + sse_d;\n                    best_split = split;\n                    best_mean_u = mean_u;\n                    best_mean_d = mean_d;\n                }\n            }\n            \n            if (best_split != -1 && sse1 > 1e-9) {\n                 if (total_count * log(best_sse2 / sse1) < -log(static_cast<double>(total_count))) {\n                    for (int i = 0; i < best_split; ++i) model_v[i][j] = best_mean_u;\n                    for (int i = best_split; i < GRID_SIZE - 1; ++i) model_v[i][j] = best_mean_d;\n                }\n            }\n        }\n    }\n}\n\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE - 1; ++j) {\n            est_h[i][j] = model_h[i][j] = 5000.0;\n            updates_h[i][j] = 0;\n        }\n    }\n    for (int i = 0; i < GRID_SIZE - 1; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            est_v[i][j] = model_v[i][j] = 5000.0;\n            updates_v[i][j] = 0;\n        }\n    }\n\n    for (int k = 0; k < NUM_QUERIES; ++k) {\n        Point start, goal;\n        std::cin >> start.r >> start.c >> goal.r >> goal.c;\n\n        std::string path = find_path(start, goal, k);\n        std::cout << path << std::endl;\n\n        long long noisy_path_length;\n        std::cin >> noisy_path_length;\n\n        update_estimates(path, start, noisy_path_length, k);\n        update_model();\n    }\n\n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <chrono>\n#include <random>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <map>\n\n// --- Constants and Globals ---\nconstexpr int N_CONST = 20;\nconstexpr int NUM_CHARS = 8;\nconstexpr long long W_CONFLICT = 10000;\nconst double TIME_LIMIT = 2.95;\n\nint N_in, M;\nstd::vector<std::string> S;\nstd::vector<int> S_len;\nstd::vector<std::vector<int>> S_int;\n\nstd::mt19937 rng;\nstd::chrono::steady_clock::time_point start_time;\n\nstruct Placement {\n    int r, c, dir; // dir=0: horizontal, dir=1: vertical\n    bool operator==(const Placement& other) const {\n        return r == other.r && c == other.c && dir == other.dir;\n    }\n};\n\n// --- State Representation ---\nstd::vector<Placement> current_placements;\nstd::vector<Placement> best_placements;\nlong long current_energy;\nlong long best_energy;\n\nint counts[N_CONST][N_CONST][NUM_CHARS];\nint covered_count[N_CONST][N_CONST];\n\n// --- Utilities ---\nint ctoi(char c) { return c - 'A'; }\nchar itoc(int i) { return (char)('A' + i); }\n\n// --- Core Logic ---\nstd::pair<long long, int> get_cell_energy_contrib(int r, int c) {\n    if (covered_count[r][c] == 0) {\n        return {0, 0};\n    }\n    int max_c = 0;\n    for (int k = 0; k < NUM_CHARS; ++k) {\n        max_c = std::max(max_c, counts[r][c][k]);\n    }\n    long long conflict_contrib = covered_count[r][c] - max_c;\n    return {conflict_contrib, 1};\n}\n\nvoid update_state_for_move(int str_idx, const Placement& p, int sign) {\n    const auto& s = S_int[str_idx];\n    int len = S_len[str_idx];\n    if (p.dir == 0) { // Horizontal\n        for (int i = 0; i < len; ++i) {\n            int r = p.r;\n            int c = (p.c + i) % N_CONST;\n            counts[r][c][s[i]] += sign;\n            covered_count[r][c] += sign;\n        }\n    } else { // Vertical\n        for (int i = 0; i < len; ++i) {\n            int r = (p.r + i) % N_CONST;\n            int c = p.c;\n            counts[r][c][s[i]] += sign;\n            covered_count[r][c] += sign;\n        }\n    }\n}\n\nlong long calculate_delta_energy(int str_idx, const Placement& old_p, const Placement& new_p) {\n    long long delta = 0;\n    const auto& s = S_int[str_idx];\n    int len = S_len[str_idx];\n    \n    std::vector<std::pair<int, int>> affected_coords;\n    if (old_p.dir == 0) for (int i=0; i<len; ++i) affected_coords.push_back({old_p.r, (old_p.c+i)%N_CONST});\n    else for (int i=0; i<len; ++i) affected_coords.push_back({(old_p.r+i)%N_CONST, old_p.c});\n    \n    if (new_p.dir == 0) for (int i=0; i<len; ++i) affected_coords.push_back({new_p.r, (new_p.c+i)%N_CONST});\n    else for (int i=0; i<len; ++i) affected_coords.push_back({(new_p.r+i)%N_CONST, new_p.c});\n\n    std::sort(affected_coords.begin(), affected_coords.end());\n    affected_coords.erase(std::unique(affected_coords.begin(), affected_coords.end()), affected_coords.end());\n\n    for (const auto& cell : affected_coords) {\n        int r = cell.first;\n        int c = cell.second;\n\n        auto [conflicts_before, covered_before] = get_cell_energy_contrib(r, c);\n        delta -= (conflicts_before * W_CONFLICT + covered_before);\n\n        int old_p_char = -1, new_p_char = -1;\n        if (old_p.dir == 0) {\n            if (r == old_p.r && (c - old_p.c + N_CONST)%N_CONST < len) old_p_char = s[(c-old_p.c+N_CONST)%N_CONST];\n        } else {\n            if (c == old_p.c && (r - old_p.r + N_CONST)%N_CONST < len) old_p_char = s[(r-old_p.r+N_CONST)%N_CONST];\n        }\n        if (new_p.dir == 0) {\n            if (r == new_p.r && (c - new_p.c + N_CONST)%N_CONST < len) new_p_char = s[(c-new_p.c+N_CONST)%N_CONST];\n        } else {\n            if (c == new_p.c && (r - new_p.r + N_CONST)%N_CONST < len) new_p_char = s[(r-new_p.r+N_CONST)%N_CONST];\n        }\n        \n        int new_covered_total = covered_count[r][c];\n        if(old_p_char != -1) new_covered_total--;\n        if(new_p_char != -1) new_covered_total++;\n\n        if (new_covered_total > 0) {\n            int max_c = 0;\n            for (int k=0; k<NUM_CHARS; ++k) {\n                int current_cnt = counts[r][c][k];\n                if(k == old_p_char) current_cnt--;\n                if(k == new_p_char) current_cnt++;\n                max_c = std::max(max_c, current_cnt);\n            }\n            long long conflicts_after = new_covered_total - max_c;\n            delta += (conflicts_after * W_CONFLICT + 1);\n        }\n    }\n    return delta;\n}\n\nvoid greedy_initialization() {\n    current_placements.resize(M);\n    std::vector<int> p(M);\n    std::iota(p.begin(), p.end(), 0);\n    std::sort(p.begin(), p.end(), [&](int i, int j){ return S_len[i] > S_len[j]; });\n\n    std::vector<std::vector<int>> grid(N_CONST, std::vector<int>(N_CONST, -1));\n\n    for (int str_idx : p) {\n        Placement best_p;\n        int min_conflicts = 1e9;\n        for (int r = 0; r < N_CONST; ++r) {\n        for (int c = 0; c < N_CONST; ++c) {\n        for (int dir = 0; dir < 2; ++dir) {\n            int current_conflicts = 0;\n            const auto& s = S_int[str_idx];\n            int len = S_len[str_idx];\n            if (dir == 0) {\n                for (int i = 0; i < len; ++i) {\n                    if (grid[r][(c + i) % N_CONST] != -1 && grid[r][(c + i) % N_CONST] != s[i]) current_conflicts++;\n                }\n            } else {\n                for (int i = 0; i < len; ++i) {\n                    if (grid[(r + i) % N_CONST][c] != -1 && grid[(r + i) % N_CONST][c] != s[i]) current_conflicts++;\n                }\n            }\n            if (current_conflicts < min_conflicts) {\n                min_conflicts = current_conflicts;\n                best_p = {r, c, dir};\n            }\n        }}}\n        current_placements[str_idx] = best_p;\n        const auto& s = S_int[str_idx];\n        int len = S_len[str_idx];\n        if (best_p.dir == 0) for(int i=0; i<len; ++i) grid[best_p.r][(best_p.c+i)%N_CONST] = s[i];\n        else for(int i=0; i<len; ++i) grid[(best_p.r+i)%N_CONST][best_p.c] = s[i];\n    }\n}\n\nlong long calculate_full_energy() {\n    long long total_conflicts = 0;\n    int total_covered = 0;\n    for (int r = 0; r < N_CONST; ++r) {\n        for (int c = 0; c < N_CONST; ++c) {\n            auto [conflicts, covered] = get_cell_energy_contrib(r, c);\n            total_conflicts += conflicts;\n            total_covered += covered;\n        }\n    }\n    return total_conflicts * W_CONFLICT + total_covered;\n}\n\nvoid solve() {\n    start_time = std::chrono::steady_clock::now();\n    rng.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    S_int.resize(M); S_len.resize(M);\n    for (int i = 0; i < M; ++i) {\n        S_len[i] = S[i].length();\n        S_int[i].resize(S_len[i]);\n        for (int j = 0; j < S_len[i]; ++j) S_int[i][j] = ctoi(S[i][j]);\n    }\n\n    greedy_initialization();\n    for (int i = 0; i < M; ++i) {\n        update_state_for_move(i, current_placements[i], +1);\n    }\n    \n    // Initial Refinement Phase\n    for (int iter = 0; iter < 2; ++iter) {\n        for (int i = 0; i < M; ++i) {\n            Placement old_p = current_placements[i];\n            Placement best_p = old_p;\n            long long min_delta = 1e18;\n\n            for (int r = 0; r < N_CONST; ++r) {\n            for (int c = 0; c < N_CONST; ++c) {\n            for (int dir = 0; dir < 2; ++dir) {\n                Placement cand_p = {r, c, dir};\n                long long delta = calculate_delta_energy(i, old_p, cand_p);\n                if (delta < min_delta) {\n                    min_delta = delta;\n                    best_p = cand_p;\n                }\n            }}}\n            \n            if (!(best_p == old_p)) {\n                update_state_for_move(i, old_p, -1);\n                update_state_for_move(i, best_p, +1);\n                current_placements[i] = best_p;\n            }\n        }\n    }\n    \n    current_energy = calculate_full_energy();\n    best_energy = current_energy;\n    best_placements = current_placements;\n\n    double start_temp = 5000.0;\n    double end_temp = 0.1;\n    int iters_since_best = 0;\n    const int STAGNATION_LIMIT = M * 100;\n    \n    while (true) {\n        auto now = std::chrono::steady_clock::now();\n        double elapsed_time = std::chrono::duration_cast<std::chrono::duration<double>>(now - start_time).count();\n        if (elapsed_time > TIME_LIMIT) break;\n\n        iters_since_best++;\n        double temp = start_temp * std::pow(end_temp / start_temp, elapsed_time / TIME_LIMIT);\n\n        int str_idx;\n        long long current_conflicts = current_energy / W_CONFLICT;\n        \n        if (current_conflicts > 0 && std::uniform_real_distribution<>(0.0, 1.0)(rng) < 0.95) {\n            std::vector<std::pair<int, int>> conflicted_cells;\n            for(int r=0; r<N_CONST; ++r) for(int c=0; c<N_CONST; ++c) {\n                if(get_cell_energy_contrib(r,c).first > 0) {\n                    conflicted_cells.emplace_back(r, c);\n                }\n            }\n\n            if (!conflicted_cells.empty()) {\n                std::pair<int, int> target_cell = conflicted_cells[std::uniform_int_distribution<int>(0, conflicted_cells.size() - 1)(rng)];\n                int r0 = target_cell.first; int c0 = target_cell.second;\n\n                std::vector<int> candidates;\n                for(int i=0; i<M; ++i) {\n                    const Placement& p = current_placements[i];\n                    int len = S_len[i];\n                    bool covers = false;\n                    if (p.dir == 0) {\n                        if (p.r == r0 && (c0 - p.c + N_CONST) % N_CONST < len) covers = true;\n                    } else {\n                        if (p.c == c0 && (r0 - p.r + N_CONST) % N_CONST < len) covers = true;\n                    }\n                    if (covers) candidates.push_back(i);\n                }\n                if (!candidates.empty()) {\n                    str_idx = candidates[std::uniform_int_distribution<int>(0, candidates.size() - 1)(rng)];\n                } else {\n                    str_idx = std::uniform_int_distribution<int>(0, M - 1)(rng);\n                }\n            } else {\n                 str_idx = std::uniform_int_distribution<int>(0, M - 1)(rng);\n            }\n        } else {\n            str_idx = std::uniform_int_distribution<int>(0, M - 1)(rng);\n        }\n\n        Placement old_p = current_placements[str_idx];\n        Placement new_p;\n\n        double p_powerful = 0.2 + 0.6 * (elapsed_time / TIME_LIMIT);\n        if (std::uniform_real_distribution<double>(0.0, 1.0)(rng) < p_powerful) {\n            new_p = old_p;\n            long long min_delta = 1e18;\n            for (int r = 0; r < N_CONST; ++r) for (int c = 0; c < N_CONST; ++c) for (int dir = 0; dir < 2; ++dir) {\n                Placement p_candidate = {r, c, dir};\n                long long delta = calculate_delta_energy(str_idx, old_p, p_candidate);\n                if (delta < min_delta) {\n                    min_delta = delta;\n                    new_p = p_candidate;\n                }\n            }\n        } else {\n            if (std::uniform_real_distribution<>(0.0, 1.0)(rng) < 0.1) {\n                 new_p = old_p;\n                 int move_type = std::uniform_int_distribution<int>(0, 2)(rng);\n                 if (move_type == 0) new_p.r = (new_p.r + std::uniform_int_distribution<int>(-2, 2)(rng) + N_CONST) % N_CONST;\n                 else if (move_type == 1) new_p.c = (new_p.c + std::uniform_int_distribution<int>(-2, 2)(rng) + N_CONST) % N_CONST;\n                 else new_p.dir = 1 - new_p.dir;\n            } else {\n                new_p = { std::uniform_int_distribution<int>(0, N_CONST - 1)(rng), std::uniform_int_distribution<int>(0, N_CONST - 1)(rng), std::uniform_int_distribution<int>(0, 1)(rng) };\n            }\n        }\n        \n        if (old_p == new_p) continue;\n        \n        long long delta_energy = calculate_delta_energy(str_idx, old_p, new_p);\n\n        if (delta_energy <= 0 || std::uniform_real_distribution<double>(0.0, 1.0)(rng) < std::exp(-delta_energy / temp)) {\n            current_energy += delta_energy;\n            update_state_for_move(str_idx, old_p, -1);\n            update_state_for_move(str_idx, new_p, +1);\n            current_placements[str_idx] = new_p;\n\n            if (current_energy < best_energy) {\n                best_energy = current_energy;\n                best_placements = current_placements;\n                iters_since_best = 0;\n            }\n        }\n        \n        if (best_energy >= W_CONFLICT && iters_since_best > STAGNATION_LIMIT) {\n            current_placements = best_placements;\n            std::fill(&counts[0][0][0], &counts[0][0][0] + sizeof(counts)/sizeof(int), 0);\n            for(int r=0; r<N_CONST; ++r) for(int c=0; c<N_CONST; ++c) covered_count[r][c] = 0;\n            for(int i=0; i<M; ++i) {\n                update_state_for_move(i, current_placements[i], +1);\n            }\n            \n            std::vector<int> conflicted_strings;\n            std::vector<bool> is_conflicted_cell(N_CONST * N_CONST, false);\n            for(int r=0; r<N_CONST; ++r) for(int c=0; c<N_CONST; ++c) {\n                if(get_cell_energy_contrib(r,c).first > 0) is_conflicted_cell[r*N_CONST+c] = true;\n            }\n            for(int i=0; i<M; ++i) {\n                const auto& p = current_placements[i];\n                int len = S_len[i];\n                if (p.dir == 0) {\n                    for (int j=0; j<len; ++j) if(is_conflicted_cell[p.r*N_CONST+((p.c+j)%N_CONST)]) { conflicted_strings.push_back(i); break; }\n                } else {\n                    for (int j=0; j<len; ++j) if(is_conflicted_cell[((p.r+j)%N_CONST)*N_CONST+p.c]) { conflicted_strings.push_back(i); break; }\n                }\n            }\n\n            int num_to_kick = std::max(1, M / 50);\n            if (!conflicted_strings.empty()) {\n                std::shuffle(conflicted_strings.begin(), conflicted_strings.end(), rng);\n                for (int i = 0; i < num_to_kick && i < conflicted_strings.size(); ++i) {\n                    int kick_idx = conflicted_strings[i];\n                    update_state_for_move(kick_idx, current_placements[kick_idx], -1);\n                    current_placements[kick_idx] = { std::uniform_int_distribution<int>(0, N_CONST - 1)(rng), std::uniform_int_distribution<int>(0, N_CONST - 1)(rng), std::uniform_int_distribution<int>(0, 1)(rng) };\n                    update_state_for_move(kick_idx, current_placements[kick_idx], +1);\n                }\n            }\n            current_energy = calculate_full_energy();\n            iters_since_best = 0;\n        }\n    }\n\n    std::fill(&counts[0][0][0], &counts[0][0][0] + sizeof(counts)/sizeof(int), 0);\n    for(int r=0; r<N_CONST; ++r) for(int c=0; c<N_CONST; ++c) covered_count[r][c] = 0;\n    for(int i=0; i<M; ++i) {\n        update_state_for_move(i, best_placements[i], +1);\n    }\n    \n    std::vector<std::string> final_grid(N_CONST, std::string(N_CONST, '.'));\n    for (int r = 0; r < N_CONST; ++r) {\n        for (int c = 0; c < N_CONST; ++c) {\n            if (covered_count[r][c] > 0) {\n                int max_k = 0, max_cnt = 0;\n                for (int k = 0; k < NUM_CHARS; ++k) {\n                    if (counts[r][c][k] > max_cnt) {\n                        max_cnt = counts[r][c][k];\n                        max_k = k;\n                    }\n                }\n                final_grid[r][c] = itoc(max_k);\n            }\n        }\n    }\n\n    for (int i = 0; i < N_CONST; ++i) {\n        std::cout << final_grid[i] << std::endl;\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    std::cin >> N_in >> M;\n    S.resize(M);\n    for (int i = 0; i < M; ++i) std::cin >> S[i];\n    solve();\n    return 0;\n}","ahc005":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <map>\n#include <set>\n#include <algorithm>\n#include <chrono>\n#include <random>\n\nusing namespace std;\n\n// Timer\nchrono::high_resolution_clock::time_point start_time;\n\n// Constants\nconst int INF = 1e9;\nconst int DR[] = {-1, 1, 0, 0};\nconst int DC[] = {0, 0, -1, 1};\nconst char MOVES[] = {'U', 'D', 'L', 'R'};\n\n// Globals\nint N, si, sj;\nvector<string> grid;\nvector<pair<int, int>> road_squares;\nmap<pair<int, int>, int> coord_to_id;\nvector<vector<pair<int, int>>> adj;\n\nstruct Segment {\n    int id;\n    vector<pair<int, int>> squares;\n};\nvector<Segment> segments;\n\n// Pre-computation functions\nvoid find_road_squares_and_build_graph() {\n    int current_id = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != '#') {\n                road_squares.push_back({i, j});\n                coord_to_id[{i, j}] = current_id++;\n            }\n        }\n    }\n\n    adj.resize(road_squares.size());\n    for (size_t i = 0; i < road_squares.size(); ++i) {\n        auto [r, c] = road_squares[i];\n        for (int move = 0; move < 4; ++move) {\n            int nr = r + DR[move];\n            int nc = c + DC[move];\n            if (nr >= 0 && nr < N && nc >= 0 && nc < N && grid[nr][nc] != '#') {\n                int neighbor_id = coord_to_id.at({nr, nc});\n                int cost = grid[nr][nc] - '0';\n                adj[i].push_back({neighbor_id, cost});\n            }\n        }\n    }\n}\n\nvoid find_segments() {\n    map<pair<int, int>, bool> visited_horz, visited_vert;\n    int seg_id_counter = 0;\n    for (const auto& p : road_squares) {\n        int r = p.first;\n        int c = p.second;\n\n        if (visited_horz.find(p) == visited_horz.end()) {\n            Segment seg;\n            seg.id = seg_id_counter++;\n            int c_start = c;\n            while (c_start > 0 && grid[r][c_start - 1] != '#') {\n                c_start--;\n            }\n            int c_end = c;\n            while (c_end < N - 1 && grid[r][c_end + 1] != '#') {\n                c_end++;\n            }\n            for (int j = c_start; j <= c_end; ++j) {\n                seg.squares.push_back({r, j});\n                visited_horz[{r, j}] = true;\n            }\n            segments.push_back(seg);\n        }\n\n        if (visited_vert.find(p) == visited_vert.end()) {\n            Segment seg;\n            seg.id = seg_id_counter++;\n            int r_start = r;\n            while (r_start > 0 && grid[r_start - 1][c] != '#') {\n                r_start--;\n            }\n            int r_end = r;\n            while (r_end < N - 1 && grid[r_end + 1][c] != '#') {\n                r_end++;\n            }\n            for (int i = r_start; i <= r_end; ++i) {\n                seg.squares.push_back({i, c});\n                visited_vert[{i, c}] = true;\n            }\n            segments.push_back(seg);\n        }\n    }\n}\n\n\n// Dijkstra for APSP\npair<vector<int>, vector<int>> dijkstra(int start_node_id) {\n    int n = road_squares.size();\n    vector<int> dist(n, INF);\n    vector<int> parent(n, -1);\n    dist[start_node_id] = 0;\n\n    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;\n    pq.push({0, start_node_id});\n\n    while (!pq.empty()) {\n        auto [d, u] = pq.top();\n        pq.pop();\n\n        if (d > dist[u]) continue;\n\n        for (auto& edge : adj[u]) {\n            int v = edge.first;\n            int weight = edge.second;\n            if (dist[u] + weight < dist[v]) {\n                dist[v] = dist[u] + weight;\n                parent[v] = u;\n                pq.push({dist[v], v});\n            }\n        }\n    }\n    return {dist, parent};\n}\n\n// Main logic\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    start_time = chrono::high_resolution_clock::now();\n\n    cin >> N >> si >> sj;\n    grid.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> grid[i];\n    }\n\n    find_road_squares_and_build_graph();\n    find_segments();\n    \n    // Step 3: Define Key Points and Solve Set Cover\n    set<pair<int, int>> key_points_set;\n    key_points_set.insert({si, sj});\n\n    for (const auto& seg : segments) {\n        key_points_set.insert(seg.squares.front());\n        if(seg.squares.size() > 1) {\n            key_points_set.insert(seg.squares.back());\n        }\n    }\n\n    for (int r = 0; r < N; r+=1) {\n        for (int c = 0; c < N; c+=1) {\n            if (grid[r][c] != '#') {\n                bool has_horz = false, has_vert = false;\n                if (c > 0 && grid[r][c-1] != '#') has_horz = true;\n                if (c < N-1 && grid[r][c+1] != '#') has_horz = true;\n                if (r > 0 && grid[r-1][c] != '#') has_vert = true;\n                if (r < N-1 && grid[r+1][c] != '#') has_vert = true;\n                if(has_horz && has_vert) {\n                     bool is_straight = (c > 0 && grid[r][c-1] != '#' && c < N-1 && grid[r][c+1] != '#') && !(r > 0 && grid[r-1][c] != '#') && !(r < N-1 && grid[r+1][c] != '#');\n                     is_straight |= (r > 0 && grid[r-1][c] != '#' && r < N-1 && grid[r+1][c] != '#') && !(c > 0 && grid[r][c-1] != '#') && !(c < N-1 && grid[r][c+1] != '#');\n                     if(!is_straight) key_points_set.insert({r,c});\n                }\n            }\n        }\n    }\n    \n    vector<pair<int, int>> key_points(key_points_set.begin(), key_points_set.end());\n    map<pair<int, int>, int> kp_to_idx;\n    for(size_t i=0; i<key_points.size(); ++i) kp_to_idx[key_points[i]] = i;\n\n    vector<vector<int>> kp_covers(key_points.size());\n    vector<vector<int>> seg_covered_by(segments.size());\n\n    for(size_t i=0; i<key_points.size(); ++i) {\n        for(const auto& seg : segments) {\n            for(const auto& sq : seg.squares) {\n                if(sq == key_points[i]) {\n                    kp_covers[i].push_back(seg.id);\n                    seg_covered_by[seg.id].push_back(i);\n                    break;\n                }\n            }\n        }\n    }\n    \n    set<int> segments_to_cover;\n    for (size_t i = 0; i < segments.size(); ++i) segments_to_cover.insert(i);\n\n    vector<int> kp_uncovered_count(key_points.size());\n    for(size_t i=0; i<key_points.size(); ++i) {\n        kp_uncovered_count[i] = kp_covers[i].size();\n    }\n    \n    set<pair<int, int>> target_kps_set;\n    while(!segments_to_cover.empty()) {\n        int best_kp_idx = -1;\n        int max_cover = -1;\n        \n        for(size_t i=0; i<key_points.size(); ++i) {\n            if(kp_uncovered_count[i] > max_cover) {\n                max_cover = kp_uncovered_count[i];\n                best_kp_idx = i;\n            }\n        }\n        \n        if (best_kp_idx == -1) break;\n\n        pair<int,int> best_kp_coord = key_points[best_kp_idx];\n        target_kps_set.insert(best_kp_coord);\n        \n        vector<int> segs_just_covered;\n        for(int seg_id : kp_covers[best_kp_idx]) {\n            if(segments_to_cover.count(seg_id)) {\n                segs_just_covered.push_back(seg_id);\n            }\n        }\n\n        for(int seg_id : segs_just_covered) {\n            segments_to_cover.erase(seg_id);\n            for(int kp_idx : seg_covered_by[seg_id]) {\n                kp_uncovered_count[kp_idx]--;\n            }\n        }\n    }\n\n    target_kps_set.insert({si, sj});\n    vector<pair<int, int>> V_tsp_coords(target_kps_set.begin(), target_kps_set.end());\n    int num_tsp_nodes = V_tsp_coords.size();\n    map<pair<int, int>, int> tsp_coord_to_idx;\n    for(int i=0; i<num_tsp_nodes; ++i) tsp_coord_to_idx[V_tsp_coords[i]] = i;\n\n    // Step 4: APSP\n    vector<vector<int>> dist_matrix(num_tsp_nodes, vector<int>(num_tsp_nodes));\n    vector<vector<int>> parents_matrix(num_tsp_nodes, vector<int>(road_squares.size()));\n\n    for(int i=0; i<num_tsp_nodes; ++i) {\n        int start_node_id = coord_to_id.at(V_tsp_coords[i]);\n        auto [dist, parent] = dijkstra(start_node_id);\n        parents_matrix[i] = parent;\n        for(int j=0; j<num_tsp_nodes; ++j) {\n            int end_node_id = coord_to_id.at(V_tsp_coords[j]);\n            dist_matrix[i][j] = dist[end_node_id];\n        }\n    }\n\n    // Step 5: Solve TSP\n    int start_tsp_idx = tsp_coord_to_idx.at({si, sj});\n    vector<int> tour;\n    tour.push_back(start_tsp_idx);\n    vector<bool> visited(num_tsp_nodes, false);\n    visited[start_tsp_idx] = true;\n\n    int current_tsp_idx = start_tsp_idx;\n    while(tour.size() < (size_t)num_tsp_nodes) {\n        int next_tsp_idx = -1;\n        int min_dist = INF;\n        for(int i=0; i<num_tsp_nodes; ++i) {\n            if(!visited[i]) {\n                if(dist_matrix[current_tsp_idx][i] < min_dist) {\n                    min_dist = dist_matrix[current_tsp_idx][i];\n                    next_tsp_idx = i;\n                }\n            }\n        }\n        if (next_tsp_idx == -1) break; // All remaining are unreachable\n        tour.push_back(next_tsp_idx);\n        visited[next_tsp_idx] = true;\n        current_tsp_idx = next_tsp_idx;\n    }\n    \n    // 2-opt\n    bool improved = true;\n    while(improved) {\n        auto elapsed_time = chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count();\n        if (elapsed_time > 2800) break;\n        improved = false;\n        for(int i=0; i<num_tsp_nodes; ++i) {\n            for(int j=i+2; j<num_tsp_nodes; ++j) {\n                if (i == 0 && j == num_tsp_nodes - 1) continue;\n                \n                int u1 = tour[i], v1 = tour[(i+1)%num_tsp_nodes];\n                int u2 = tour[j], v2 = tour[(j+1)%num_tsp_nodes];\n                \n                long long current_dist = dist_matrix[u1][v1] + dist_matrix[u2][v2];\n                long long new_dist = dist_matrix[u1][u2] + dist_matrix[v1][v2];\n                \n                if(new_dist < current_dist) {\n                    reverse(tour.begin() + i + 1, tour.begin() + j + 1);\n                    improved = true;\n                }\n            }\n        }\n    }\n    \n    auto it = find(tour.begin(), tour.end(), start_tsp_idx);\n    rotate(tour.begin(), it, tour.end());\n\n    // Step 6: Generate Output\n    string path_str = \"\";\n    for(size_t i=0; i<tour.size(); ++i) {\n        int u_tsp_idx = tour[i];\n        int v_tsp_idx = tour[(i+1)%tour.size()];\n        \n        int u_node_id = coord_to_id.at(V_tsp_coords[u_tsp_idx]);\n        int v_node_id = coord_to_id.at(V_tsp_coords[v_tsp_idx]);\n\n        vector<int> path;\n        int curr = v_node_id;\n        while(curr != -1 && curr != u_node_id) {\n            path.push_back(curr);\n            curr = parents_matrix[u_tsp_idx][curr];\n        }\n        reverse(path.begin(), path.end());\n        \n        pair<int, int> last_coord = V_tsp_coords[u_tsp_idx];\n        for(int node_id : path) {\n            auto [r, c] = road_squares[node_id];\n            if(r < last_coord.first) path_str += 'U';\n            else if(r > last_coord.first) path_str += 'D';\n            else if(c < last_coord.second) path_str += 'L';\n            else if(c > last_coord.second) path_str += 'R';\n            last_coord = {r, c};\n        }\n    }\n\n    cout << path_str << endl;\n\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <string>\n#include <sstream>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <functional>\n\n#include <atcoder/mincostflow>\n\n// Constants\nconstexpr int N_TASKS = 1000;\nconstexpr int M_MEMBERS = 20;\nconstexpr int MAX_DAYS = 2000;\n\n// Hyperparameters\nconst double INITIAL_SKILL_ESTIMATE = 0.0;\nconst double SKILL_UPDATE_LEARNING_RATE = 0.15; // Tuned from 0.1\nconst double EXPLORATION_DECAY_DAYS = 400.0;   // Tuned from 600.0\nconst double EXPLORATION_LAMBDA_0 = 0.5;\nconst double OVERESTIMATE_CORRECTION_FACTOR = 0.1;\nconst int CANDIDATE_TASK_POOL_SIZE = 3 * M_MEMBERS; // Increased from 2*M\n\n// Problem data\nint K, R;\nstd::vector<std::vector<int>> D; // Task difficulties\nstd::vector<std::vector<int>> adj; // Task dependencies (u -> v means u must be done before v)\nstd::vector<std::vector<int>> rev_adj; // Reverse dependencies\n\n// State\nenum class TaskStatus { NOT_STARTED, IN_PROGRESS, COMPLETED };\nstd::vector<TaskStatus> task_status;\nint completed_task_count;\n\nstruct Member {\n    bool is_busy = false;\n    int task_id = -1;\n    int start_day = -1;\n};\nstd::vector<Member> members;\n\nstd::vector<std::vector<double>> estimated_skills;\nstd::vector<std::vector<int>> skill_lower_bounds;\nstd::vector<std::vector<int>> max_d_seen;\n\n// --- Function Declarations ---\ndouble estimate_work(int task_id, int member_id);\ndouble estimate_time(int task_id, int member_id);\nvoid read_initial_input();\nvoid initialize_state();\nvoid update_skills(int member_id, int task_id, int duration);\n\n// --- Main Logic ---\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int N_dummy, M_dummy;\n    std::cin >> N_dummy >> M_dummy;\n    \n    read_initial_input();\n    initialize_state();\n\n    for (int day = 1; day <= MAX_DAYS; ++day) {\n        // --- Find free members and schedulable tasks ---\n        std::vector<int> free_members_ids;\n        for (int i = 0; i < M_MEMBERS; ++i) {\n            if (!members[i].is_busy) {\n                free_members_ids.push_back(i);\n            }\n        }\n\n        std::vector<int> schedulable_tasks_ids;\n        if (!free_members_ids.empty()) {\n            for (int i = 0; i < N_TASKS; ++i) {\n                if (task_status[i] == TaskStatus::NOT_STARTED) {\n                    bool all_deps_done = true;\n                    for (int dep : rev_adj[i]) {\n                        if (task_status[dep] != TaskStatus::COMPLETED) {\n                            all_deps_done = false;\n                            break;\n                        }\n                    }\n                    if (all_deps_done) {\n                        schedulable_tasks_ids.push_back(i);\n                    }\n                }\n            }\n        }\n\n        std::vector<std::pair<int, int>> assignments;\n        if (!free_members_ids.empty() && !schedulable_tasks_ids.empty()) {\n            \n            // --- Dynamic Longest Path (DLP) calculation ---\n            std::vector<double> best_time_for_task(N_TASKS);\n            for (int i = 0; i < N_TASKS; ++i) {\n                if (task_status[i] == TaskStatus::COMPLETED) {\n                    best_time_for_task[i] = 0;\n                } else {\n                    double min_t = 1e9;\n                    for (int j = 0; j < M_MEMBERS; ++j) {\n                        min_t = std::min(min_t, estimate_time(i, j));\n                    }\n                    best_time_for_task[i] = min_t;\n                }\n            }\n            std::vector<double> dlp(N_TASKS, 0.0);\n            for (int i = N_TASKS - 1; i >= 0; --i) {\n                double max_succ_dlp = 0.0;\n                for (int neighbor : adj[i]) {\n                    max_succ_dlp = std::max(max_succ_dlp, dlp[neighbor]);\n                }\n                dlp[i] = best_time_for_task[i] + max_succ_dlp;\n            }\n\n            // --- Candidate Task Selection ---\n            std::sort(schedulable_tasks_ids.begin(), schedulable_tasks_ids.end(), [&](int a, int b) {\n                if (std::abs(dlp[a] - dlp[b]) > 1e-9) return dlp[a] > dlp[b];\n                return a < b;\n            });\n            if (schedulable_tasks_ids.size() > CANDIDATE_TASK_POOL_SIZE) {\n                schedulable_tasks_ids.resize(CANDIDATE_TASK_POOL_SIZE);\n            }\n\n            // --- Bipartite Matching using Min-Cost Max-Flow ---\n            int num_free_members = free_members_ids.size();\n            int num_cand_tasks = schedulable_tasks_ids.size();\n            atcoder::mcf_graph<int, long long> graph(num_free_members + num_cand_tasks + 2);\n            int s = num_free_members + num_cand_tasks;\n            int t = s + 1;\n            \n            double lambda = EXPLORATION_LAMBDA_0 * exp(-(double)day / EXPLORATION_DECAY_DAYS);\n\n            for (int i = 0; i < num_free_members; ++i) graph.add_edge(s, i, 1, 0);\n            for (int i = 0; i < num_cand_tasks; ++i) graph.add_edge(num_free_members + i, t, 1, 0);\n\n            for (int i = 0; i < num_free_members; ++i) {\n                int member_id = free_members_ids[i];\n                for (int j = 0; j < num_cand_tasks; ++j) {\n                    int task_id = schedulable_tasks_ids[j];\n                    double t_est = estimate_time(task_id, member_id);\n                    double novelty = 0;\n                    for (int k = 0; k < K; ++k) {\n                        novelty += std::max(0, D[task_id][k] - max_d_seen[member_id][k]);\n                    }\n                    long long cost = static_cast<long long>(round(100.0 * t_est - 100.0 * lambda * novelty));\n                    graph.add_edge(i, num_free_members + j, 1, cost);\n                }\n            }\n\n            graph.flow(s, t, std::min(num_free_members, num_cand_tasks));\n            for (const auto& edge : graph.edges()) {\n                if (edge.from >= 0 && edge.from < num_free_members && \n                    edge.to >= num_free_members && edge.to < s && edge.flow > 0) {\n                    int member_idx = edge.from;\n                    int task_idx = edge.to - num_free_members;\n                    assignments.emplace_back(free_members_ids[member_idx], schedulable_tasks_ids[task_idx]);\n                }\n            }\n        }\n        \n        // --- Output assignments ---\n        std::cout << assignments.size();\n        for (const auto& p : assignments) {\n            int member_id = p.first;\n            int task_id = p.second;\n            std::cout << \" \" << member_id + 1 << \" \" << task_id + 1;\n            members[member_id] = {true, task_id, day};\n            task_status[task_id] = TaskStatus::IN_PROGRESS;\n        }\n        std::cout << std::endl;\n\n        // --- Read daily feedback ---\n        int n_finished;\n        std::cin >> n_finished;\n        if (n_finished == -1) break;\n        \n        for (int i = 0; i < n_finished; ++i) {\n            int finished_member_id;\n            std::cin >> finished_member_id;\n            --finished_member_id;\n\n            int task_id = members[finished_member_id].task_id;\n            int start_day = members[finished_member_id].start_day;\n            int duration = day - start_day + 1;\n\n            members[finished_member_id] = {false, -1, -1};\n            task_status[task_id] = TaskStatus::COMPLETED;\n            completed_task_count++;\n            \n            update_skills(finished_member_id, task_id, duration);\n        }\n    }\n    return 0;\n}\n\n// --- Function Implementations ---\ndouble estimate_work(int task_id, int member_id) {\n    double work = 0;\n    for (int k = 0; k < K; ++k) {\n        work += std::max(0.0, (double)D[task_id][k] - estimated_skills[member_id][k]);\n    }\n    return work;\n}\n\ndouble estimate_time(int task_id, int member_id) {\n    double work = estimate_work(task_id, member_id);\n    return std::max(1.0, work);\n}\n\nvoid read_initial_input() {\n    std::cin >> K >> R;\n    D.resize(N_TASKS, std::vector<int>(K));\n    for (int i = 0; i < N_TASKS; ++i) {\n        for (int j = 0; j < K; ++j) {\n            std::cin >> D[i][j];\n        }\n    }\n    adj.assign(N_TASKS, std::vector<int>());\n    rev_adj.assign(N_TASKS, std::vector<int>());\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        std::cin >> u >> v;\n        --u; --v;\n        adj[u].push_back(v);\n        rev_adj[v].push_back(u);\n    }\n}\n\nvoid initialize_state() {\n    task_status.assign(N_TASKS, TaskStatus::NOT_STARTED);\n    completed_task_count = 0;\n    members.resize(M_MEMBERS);\n    estimated_skills.assign(M_MEMBERS, std::vector<double>(K, INITIAL_SKILL_ESTIMATE));\n    skill_lower_bounds.assign(M_MEMBERS, std::vector<int>(K, 0));\n    max_d_seen.assign(M_MEMBERS, std::vector<int>(K, 0));\n}\n\nvoid update_skills(int member_id, int task_id, int duration) {\n    for (int k = 0; k < K; ++k) {\n        max_d_seen[member_id][k] = std::max(max_d_seen[member_id][k], D[task_id][k]);\n    }\n\n    double predicted_w = estimate_work(task_id, member_id);\n    \n    if (duration == 1) {\n        for (int k = 0; k < K; ++k) {\n            skill_lower_bounds[member_id][k] = std::max(skill_lower_bounds[member_id][k], D[task_id][k]);\n            estimated_skills[member_id][k] = std::max(estimated_skills[member_id][k], (double)skill_lower_bounds[member_id][k]);\n        }\n    } else {\n        double observed_w = duration;\n        \n        if (predicted_w < 1e-6) { // Predicted T=1, but was wrong\n            std::vector<int> candidate_k;\n            for(int k=0; k<K; ++k) {\n                if(D[task_id][k] > 0) candidate_k.push_back(k);\n            }\n\n            if (!candidate_k.empty()) {\n                std::vector<double> blame_weights;\n                double total_blame = 0;\n                for (int k : candidate_k) {\n                    double weight = exp(-OVERESTIMATE_CORRECTION_FACTOR * (estimated_skills[member_id][k] - D[task_id][k]));\n                    blame_weights.push_back(weight);\n                    total_blame += weight;\n                }\n                \n                if (total_blame > 1e-9) {\n                    for (size_t i = 0; i < candidate_k.size(); ++i) {\n                        int k = candidate_k[i];\n                        double blamed_deficiency = observed_w * blame_weights[i] / total_blame;\n                        double target_s_k = (double)D[task_id][k] - blamed_deficiency;\n                        estimated_skills[member_id][k] = (1.0 - SKILL_UPDATE_LEARNING_RATE) * estimated_skills[member_id][k] \n                                                        + SKILL_UPDATE_LEARNING_RATE * target_s_k;\n                    }\n                }\n            }\n        } else { // Standard update\n            double error = observed_w - predicted_w;\n            std::vector<int> deficient_skills;\n            double total_predicted_deficiency = 0;\n            for (int k = 0; k < K; ++k) {\n                if (D[task_id][k] > estimated_skills[member_id][k]) {\n                    deficient_skills.push_back(k);\n                    total_predicted_deficiency += (D[task_id][k] - estimated_skills[member_id][k]);\n                }\n            }\n\n            if (!deficient_skills.empty() && total_predicted_deficiency > 1e-9) {\n                for (int k : deficient_skills) {\n                    double current_deficiency = D[task_id][k] - estimated_skills[member_id][k];\n                    double adjustment = error * (current_deficiency / total_predicted_deficiency);\n                    estimated_skills[member_id][k] -= SKILL_UPDATE_LEARNING_RATE * adjustment;\n                }\n            }\n        }\n    }\n\n    for (int k = 0; k < K; ++k) {\n        estimated_skills[member_id][k] = std::max((double)skill_lower_bounds[member_id][k], estimated_skills[member_id][k]);\n        estimated_skills[member_id][k] = std::max(0.0, estimated_skills[member_id][k]);\n    }\n    \n    std::cout << \"#s \" << member_id + 1;\n    for (int k = 0; k < K; ++k) {\n        std::cout << \" \" << static_cast<int>(round(estimated_skills[member_id][k]));\n    }\n    std::cout << std::endl;\n}","ahc006":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n#include <chrono>\n#include <random>\n\n// A fast random number generator\nclass Xoshiro256pp {\npublic:\n    using result_type = uint64_t;\n    static constexpr result_type min() { return std::numeric_limits<result_type>::min(); }\n    static constexpr result_type max() { return std::numeric_limits<result_type>::max(); }\n\n    Xoshiro256pp() : Xoshiro256pp(std::random_device{}()) {}\n    explicit Xoshiro256pp(uint64_t seed) {\n        s[0] = seed; s[1] = 0; s[2] = 0; s[3] = 0;\n    }\n\n    result_type operator()() {\n        const uint64_t result = rotl(s[0] + s[3], 23) + s[0];\n        const uint64_t t = s[1] << 17;\n        s[2] ^= s[0]; s[3] ^= s[1]; s[1] ^= s[2]; s[0] ^= s[3];\n        s[2] ^= t; s[3] = rotl(s[3], 45);\n        return result;\n    }\n\n    int next_int(int min, int max) {\n        if (min > max) return min;\n        return min + operator()() % (uint64_t)(max - min + 1);\n    }\n\n    double next_double() {\n        return (operator()() >> 11) * (1.0 / (1ULL << 53));\n    }\n\nprivate:\n    static inline uint64_t rotl(const uint64_t x, int k) {\n        return (x << k) | (x >> (64 - k));\n    }\n    uint64_t s[4];\n};\n\nXoshiro256pp rng;\n\nstruct Point {\n    int x, y;\n};\n\nstruct Order {\n    int id;\n    Point p, d;\n};\n\nconst int NUM_ORDERS_TOTAL = 1000;\nconst int ORDERS_TO_DELIVER = 50;\nconst int PATH_LEN = ORDERS_TO_DELIVER * 2;\nconst Point OFFICE = {400, 400};\nstd::vector<Order> ALL_ORDERS;\n\nint manhattan(Point p1, Point p2) {\n    return std::abs(p1.x - p2.x) + std::abs(p1.y - p2.y);\n}\n\nstruct State {\n    std::vector<int> selected_g_indices;\n    std::vector<int> path;\n    std::vector<int> pos;\n    long long cost;\n\n    State() : pos(PATH_LEN) {}\n\n    void update_pos() {\n        for (int i = 0; i < PATH_LEN; ++i) {\n            pos[path[i]] = i;\n        }\n    }\n};\n\nPoint get_coord(int node_id, const std::vector<int>& selected_g_indices) {\n    if (node_id < ORDERS_TO_DELIVER) {\n        return ALL_ORDERS[selected_g_indices[node_id]].p;\n    } else {\n        return ALL_ORDERS[selected_g_indices[node_id - ORDERS_TO_DELIVER]].d;\n    }\n}\n\nlong long calculate_full_cost(const std::vector<int>& path, const std::vector<int>& selected_g_indices) {\n    if (path.empty()) return 0;\n    long long total_dist = 0;\n    total_dist += manhattan(OFFICE, get_coord(path[0], selected_g_indices));\n    for (size_t i = 0; i < path.size() - 1; ++i) {\n        total_dist += manhattan(get_coord(path[i], selected_g_indices), get_coord(path[i+1], selected_g_indices));\n    }\n    total_dist += manhattan(get_coord(path.back(), selected_g_indices), OFFICE);\n    return total_dist;\n}\n\nlong long calculate_replace_delta(int local_idx, int new_g_idx, const State& state) {\n    int g_idx_to_remove = state.selected_g_indices[local_idx];\n    int p_node = local_idx;\n    int d_node = local_idx + ORDERS_TO_DELIVER;\n    int p_pos = state.pos[p_node];\n    int d_pos = state.pos[d_node];\n\n    Point p_old = ALL_ORDERS[g_idx_to_remove].p;\n    Point d_old = ALL_ORDERS[g_idx_to_remove].d;\n    Point p_new = ALL_ORDERS[new_g_idx].p;\n    Point d_new = ALL_ORDERS[new_g_idx].d;\n    long long delta = 0;\n    \n    Point p_prev_coord = (p_pos == 0) ? OFFICE : get_coord(state.path[p_pos-1], state.selected_g_indices);\n    Point p_next_coord = get_coord(state.path[p_pos+1], state.selected_g_indices);\n    Point d_prev_coord = get_coord(state.path[d_pos-1], state.selected_g_indices);\n    Point d_next_coord = (d_pos == PATH_LEN-1) ? OFFICE : get_coord(state.path[d_pos+1], state.selected_g_indices);\n\n    if (d_pos == p_pos + 1) { // adjacent\n        delta -= manhattan(p_prev_coord, p_old) + manhattan(p_old, d_old) + manhattan(d_old, d_next_coord);\n        delta += manhattan(p_prev_coord, p_new) + manhattan(p_new, d_new) + manhattan(d_new, d_next_coord);\n    } else {\n        delta -= manhattan(p_prev_coord, p_old) + manhattan(p_old, p_next_coord);\n        delta += manhattan(p_prev_coord, p_new) + manhattan(p_new, p_next_coord);\n        delta -= manhattan(d_prev_coord, d_old) + manhattan(d_old, d_next_coord);\n        delta += manhattan(d_prev_coord, d_new) + manhattan(d_new, d_next_coord);\n    }\n    return delta;\n}\n\nvoid solve() {\n    auto start_time = std::chrono::steady_clock::now();\n\n    ALL_ORDERS.resize(NUM_ORDERS_TOTAL);\n    for (int i = 0; i < NUM_ORDERS_TOTAL; ++i) {\n        ALL_ORDERS[i].id = i + 1;\n        std::cin >> ALL_ORDERS[i].p.x >> ALL_ORDERS[i].p.y >> ALL_ORDERS[i].d.x >> ALL_ORDERS[i].d.y;\n    }\n\n    // --- Initial Solution ---\n    State current_state;\n    std::vector<int> order_indices(NUM_ORDERS_TOTAL);\n    std::iota(order_indices.begin(), order_indices.end(), 0);\n    std::sort(order_indices.begin(), order_indices.end(), [&](int a, int b) {\n        Point center_a = {(ALL_ORDERS[a].p.x + ALL_ORDERS[a].d.x) / 2, (ALL_ORDERS[a].p.y + ALL_ORDERS[a].d.y) / 2};\n        Point center_b = {(ALL_ORDERS[b].p.x + ALL_ORDERS[b].d.x) / 2, (ALL_ORDERS[b].p.y + ALL_ORDERS[b].d.y) / 2};\n        return manhattan(OFFICE, center_a) < manhattan(OFFICE, center_b);\n    });\n    current_state.selected_g_indices.assign(order_indices.begin(), order_indices.begin() + ORDERS_TO_DELIVER);\n\n    for (int i = 0; i < ORDERS_TO_DELIVER; ++i) { // Greedy Insertion\n        int p_node = i;\n        int d_node = i + ORDERS_TO_DELIVER;\n        \n        long long min_p_cost_increase = -1; int best_p_pos = 0;\n        for (int j = 0; j <= (int)current_state.path.size(); ++j) {\n            Point prev = (j == 0) ? OFFICE : get_coord(current_state.path[j-1], current_state.selected_g_indices);\n            Point next = (j == (int)current_state.path.size()) ? OFFICE : get_coord(current_state.path[j], current_state.selected_g_indices);\n            Point current = get_coord(p_node, current_state.selected_g_indices);\n            long long cost_increase = manhattan(prev, current) + manhattan(current, next) - manhattan(prev, next);\n            if (min_p_cost_increase == -1 || cost_increase < min_p_cost_increase) {\n                min_p_cost_increase = cost_increase; best_p_pos = j;\n            }\n        }\n        current_state.path.insert(current_state.path.begin() + best_p_pos, p_node);\n\n        long long min_d_cost_increase = -1; int best_d_pos = 0;\n        for (int j = best_p_pos + 1; j <= (int)current_state.path.size(); ++j) {\n            Point prev = get_coord(current_state.path[j-1], current_state.selected_g_indices);\n            Point next = (j == (int)current_state.path.size()) ? OFFICE : get_coord(current_state.path[j], current_state.selected_g_indices);\n            Point current = get_coord(d_node, current_state.selected_g_indices);\n            long long cost_increase = manhattan(prev, current) + manhattan(current, next) - manhattan(prev, next);\n            if (min_d_cost_increase == -1 || cost_increase < min_d_cost_increase) {\n                min_d_cost_increase = cost_increase; best_d_pos = j;\n            }\n        }\n        current_state.path.insert(current_state.path.begin() + best_d_pos, d_node);\n    }\n    \n    current_state.cost = calculate_full_cost(current_state.path, current_state.selected_g_indices);\n    current_state.update_pos();\n    State best_state = current_state;\n\n    std::vector<int> not_selected_g_indices;\n    {\n        std::vector<bool> is_selected_flags(NUM_ORDERS_TOTAL, false);\n        for(int g_idx : current_state.selected_g_indices) is_selected_flags[g_idx] = true;\n        not_selected_g_indices.reserve(NUM_ORDERS_TOTAL - ORDERS_TO_DELIVER);\n        for(int i=0; i<NUM_ORDERS_TOTAL; ++i) if(!is_selected_flags[i]) not_selected_g_indices.push_back(i);\n    }\n    \n    // --- Simulated Annealing ---\n    double T_start = 5000;\n    double T_end = 2;\n    double time_limit = 1.95;\n    \n    while (true) {\n        auto current_time = std::chrono::steady_clock::now();\n        double elapsed_time = std::chrono::duration<double>(current_time - start_time).count();\n        if (elapsed_time > time_limit) break;\n        double T = T_start * std::pow(T_end / T_start, elapsed_time / time_limit);\n        \n        double move_type = rng.next_double();\n        \n        if (move_type < 0.4) { // Move 1: Smart Replace Order\n            int local_idx_to_remove = rng.next_int(0, ORDERS_TO_DELIVER - 1);\n            int g_idx_to_remove = current_state.selected_g_indices[local_idx_to_remove];\n\n            int best_not_selected_vec_idx = -1;\n            int best_new_g_idx = -1;\n            long long best_delta = -1;\n            const int K = 10;\n            for (int k = 0; k < K; ++k) {\n                int not_selected_vec_idx = rng.next_int(0, not_selected_g_indices.size() - 1);\n                int new_g_idx = not_selected_g_indices[not_selected_vec_idx];\n                long long current_delta = calculate_replace_delta(local_idx_to_remove, new_g_idx, current_state);\n                if (best_delta == -1 || current_delta < best_delta) {\n                    best_delta = current_delta;\n                    best_not_selected_vec_idx = not_selected_vec_idx;\n                    best_new_g_idx = new_g_idx;\n                }\n            }\n            if (best_delta < 0 || rng.next_double() < std::exp(-best_delta / T)) {\n                current_state.selected_g_indices[local_idx_to_remove] = best_new_g_idx;\n                not_selected_g_indices[best_not_selected_vec_idx] = g_idx_to_remove;\n                current_state.cost += best_delta;\n                if (current_state.cost < best_state.cost) best_state = current_state;\n            }\n        } else if (move_type < 0.65) { // Move 2: 2-opt\n            int i = rng.next_int(0, PATH_LEN - 1);\n            int j = rng.next_int(0, PATH_LEN - 1);\n            if (i >= j) std::swap(i, j);\n            if (j <= i) continue;\n            \n            bool possible = true;\n            for (int k = 0; k < ORDERS_TO_DELIVER; ++k) {\n                if (current_state.pos[k] >= i && current_state.pos[k] <= j && current_state.pos[k + ORDERS_TO_DELIVER] >= i && current_state.pos[k + ORDERS_TO_DELIVER] <= j) {\n                    possible = false; break;\n                }\n            }\n            if (!possible) continue;\n            \n            Point pi = get_coord(current_state.path[i], current_state.selected_g_indices);\n            Point pj = get_coord(current_state.path[j], current_state.selected_g_indices);\n            Point pi_prev = (i > 0) ? get_coord(current_state.path[i-1], current_state.selected_g_indices) : OFFICE;\n            Point pj_next = (j < PATH_LEN-1) ? get_coord(current_state.path[j+1], current_state.selected_g_indices) : OFFICE;\n            long long delta = manhattan(pi_prev, pj) + manhattan(pi, pj_next) - manhattan(pi_prev, pi) - manhattan(pj, pj_next);\n\n            if (delta < 0 || rng.next_double() < std::exp(-delta / T)) {\n                std::reverse(current_state.path.begin() + i, current_state.path.begin() + j + 1);\n                for(int k=i; k<=j; ++k) current_state.pos[current_state.path[k]] = k;\n                current_state.cost += delta;\n                if (current_state.cost < best_state.cost) best_state = current_state;\n            }\n        } else if (move_type < 0.9) { // Move 3: Relocate\n            int i = rng.next_int(0, PATH_LEN - 1);\n            int node_to_move = current_state.path[i];\n\n            int order_idx = node_to_move % ORDERS_TO_DELIVER;\n            int min_j, max_j;\n            if (node_to_move < ORDERS_TO_DELIVER) {\n                min_j = 0; max_j = current_state.pos[order_idx + ORDERS_TO_DELIVER];\n            } else {\n                min_j = current_state.pos[order_idx] + 1; max_j = PATH_LEN;\n            }\n            if (max_j - min_j <= 1) continue;\n            \n            int j = rng.next_int(min_j, max_j);\n            if (j == i || j == i + 1) continue;\n\n            Point pi = get_coord(current_state.path[i], current_state.selected_g_indices);\n            Point pi_prev = (i > 0) ? get_coord(current_state.path[i-1], current_state.selected_g_indices) : OFFICE;\n            Point pi_next = (i < PATH_LEN-1) ? get_coord(current_state.path[i+1], current_state.selected_g_indices) : OFFICE;\n            \n            long long delta = (manhattan(pi_prev, pi_next) - manhattan(pi_prev, pi) - manhattan(pi, pi_next));\n            \n            int temp_path_len = PATH_LEN - 1;\n            int insert_idx_in_temp = (j > i) ? j - 1 : j;\n            Point pj_prev = (insert_idx_in_temp > 0) ? get_coord(current_state.path[insert_idx_in_temp -1 + (i < insert_idx_in_temp)], current_state.selected_g_indices) : OFFICE;\n            Point pj = (insert_idx_in_temp < temp_path_len) ? get_coord(current_state.path[insert_idx_in_temp + (i < insert_idx_in_temp)], current_state.selected_g_indices) : OFFICE;\n            delta += (manhattan(pj_prev, pi) + manhattan(pi, pj) - manhattan(pj_prev, pj));\n\n            if (delta < 0 || rng.next_double() < std::exp(-delta / T)) {\n                current_state.path.erase(current_state.path.begin() + i);\n                current_state.path.insert(current_state.path.begin() + (j > i ? j - 1 : j), node_to_move);\n                current_state.update_pos();\n                current_state.cost += delta;\n                if (current_state.cost < best_state.cost) best_state = current_state;\n            }\n        } else { // Move 4: Swap\n            int i = rng.next_int(0, PATH_LEN - 1);\n            int j = rng.next_int(0, PATH_LEN - 1);\n            if (i >= j) std::swap(i,j);\n            if (i == j) continue;\n            \n            int u = current_state.path[i], v = current_state.path[j];\n            if (u % ORDERS_TO_DELIVER == v % ORDERS_TO_DELIVER) continue;\n            \n            if (u < ORDERS_TO_DELIVER) { if (j > current_state.pos[u + ORDERS_TO_DELIVER]) continue; } \n            else { if (j < current_state.pos[u - ORDERS_TO_DELIVER]) continue; }\n            if (v < ORDERS_TO_DELIVER) { if (i > current_state.pos[v + ORDERS_TO_DELIVER]) continue; }\n            else { if (i < current_state.pos[v - ORDERS_TO_DELIVER]) continue; }\n\n            long long delta = 0;\n            Point Pu = get_coord(u, current_state.selected_g_indices);\n            Point Pv = get_coord(v, current_state.selected_g_indices);\n            Point Pu_prev = (i > 0) ? get_coord(current_state.path[i-1], current_state.selected_g_indices) : OFFICE;\n            Point Pv_next = (j < PATH_LEN-1) ? get_coord(current_state.path[j+1], current_state.selected_g_indices) : OFFICE;\n            \n            if (j == i + 1) {\n                delta = manhattan(Pu_prev, Pv) + manhattan(Pu, Pv_next) - manhattan(Pu_prev, Pu) - manhattan(Pv, Pv_next);\n            } else {\n                Point Pu_next = get_coord(current_state.path[i+1], current_state.selected_g_indices);\n                Point Pv_prev = get_coord(current_state.path[j-1], current_state.selected_g_indices);\n                delta -= manhattan(Pu_prev, Pu) + manhattan(Pu, Pu_next);\n                delta -= manhattan(Pv_prev, Pv) + manhattan(Pv, Pv_next);\n                delta += manhattan(Pu_prev, Pv) + manhattan(Pv, Pu_next);\n                delta += manhattan(Pv_prev, Pu) + manhattan(Pu, Pv_next);\n            }\n\n            if (delta < 0 || rng.next_double() < std::exp(-delta / T)) {\n                std::swap(current_state.path[i], current_state.path[j]);\n                current_state.pos[u] = j; current_state.pos[v] = i;\n                current_state.cost += delta;\n                if (current_state.cost < best_state.cost) best_state = current_state;\n            }\n        }\n    }\n    \n    // Output\n    std::cout << ORDERS_TO_DELIVER;\n    for (int g_idx : best_state.selected_g_indices) std::cout << \" \" << ALL_ORDERS[g_idx].id;\n    std::cout << std::endl;\n\n    std::cout << best_state.path.size() + 2;\n    std::cout << \" \" << OFFICE.x << \" \" << OFFICE.y;\n    for (int node_id : best_state.path) {\n        Point p = get_coord(node_id, best_state.selected_g_indices);\n        std::cout << \" \" << p.x << \" \" << p.y;\n    }\n    std::cout << \" \" << OFFICE.x << \" \" << OFFICE.y << std::endl;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <map>\n#include <tuple>\n#include <iterator> // For std::make_move_iterator\n\n// Using AtCoder Library's DSU\n#include <atcoder/dsu>\n\nstruct Point {\n    int x, y;\n};\n\nstruct Edge {\n    int u, v, id;\n    int original_d;\n};\n\nlong long dist_sq(const Point& p1, const Point& p2) {\n    long long dx = p1.x - p2.x;\n    long long dy = p1.y - p2.y;\n    return dx * dx + dy * dy;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    const int N = 400;\n    const int M = 1995;\n\n    std::vector<Point> vertices(N);\n    for (int i = 0; i < N; ++i) {\n        std::cin >> vertices[i].x >> vertices[i].y;\n    }\n\n    std::vector<Edge> edges(M);\n    // Since u_i < v_i and pairs are unique, this map is sufficient.\n    std::map<std::pair<int, int>, int> edge_to_id;\n    for (int i = 0; i < M; ++i) {\n        edges[i].id = i;\n        std::cin >> edges[i].u >> edges[i].v;\n        edges[i].original_d = std::round(std::sqrt(dist_sq(vertices[edges[i].u], vertices[edges[i].v])));\n        edge_to_id[{edges[i].u, edges[i].v}] = i;\n    }\n\n    // --- Preprocessing ---\n\n    // 1. Calculate importance levels by simulating MST generation\n    std::vector<int> importance(M, 0);\n    {\n        std::vector<std::tuple<int, int, int>> all_possible_edges;\n        all_possible_edges.reserve(N * (N - 1) / 2);\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) {\n                int d = std::round(std::sqrt(dist_sq(vertices[i], vertices[j])));\n                all_possible_edges.emplace_back(d, i, j);\n            }\n        }\n        std::sort(all_possible_edges.begin(), all_possible_edges.end());\n\n        std::vector<bool> used_in_mst(all_possible_edges.size(), false);\n        for (int k = 1; k <= 5; ++k) {\n            atcoder::dsu dsu_mst(N);\n            int edges_in_tree = 0;\n            for (size_t i = 0; i < all_possible_edges.size(); ++i) {\n                if (used_in_mst[i]) continue;\n                auto [d, u, v] = all_possible_edges[i];\n                if (dsu_mst.same(u, v)) continue;\n\n                dsu_mst.merge(u, v);\n                used_in_mst[i] = true;\n                \n                if (edge_to_id.count({u, v})) {\n                    int original_id = edge_to_id.at({u, v});\n                    if (importance[original_id] == 0) {\n                        importance[original_id] = k;\n                    }\n                }\n                edges_in_tree++;\n                if (edges_in_tree == N - 1) break;\n            }\n        }\n    }\n\n    // 2. Map vertex pairs to the single edge ID connecting them.\n    std::map<std::pair<int, int>, int> edge_id_by_pair;\n    for (int i = 0; i < M; ++i) {\n        edge_id_by_pair[{edges[i].u, edges[i].v}] = i;\n    }\n\n    // --- Main Loop ---\n    atcoder::dsu dsu_main(N);\n    std::vector<std::vector<int>> component_members(N);\n    for(int i = 0; i < N; ++i) {\n        component_members[i] = {i};\n    }\n\n    for (int i = 0; i < M; ++i) {\n        int l;\n        std::cin >> l;\n\n        int u = edges[i].u;\n        int v = edges[i].v;\n\n        if (dsu_main.same(u, v)) {\n            std::cout << 0 << std::endl;\n            continue;\n        }\n\n        int root_u = dsu_main.leader(u);\n        int root_v = dsu_main.leader(v);\n\n        // Find the minimum original_d of any future edge connecting the two components.\n        auto find_min_d_alternative = \n            [&](const std::vector<int>& comp1, const std::vector<int>& comp2, int current_edge_id) {\n            int min_d = -1; \n            for (int member1 : comp1) {\n                for (int member2 : comp2) {\n                    int p1 = std::min(member1, member2);\n                    int p2 = std::max(member1, member2);\n                    auto it = edge_id_by_pair.find({p1, p2});\n                    if (it != edge_id_by_pair.end()) {\n                        int edge_idx = it->second;\n                        if (edge_idx > current_edge_id) {\n                            int d_val = edges[edge_idx].original_d;\n                            if (min_d == -1 || d_val < min_d) {\n                                min_d = d_val;\n                            }\n                        }\n                    }\n                }\n            }\n            return min_d;\n        };\n        \n        int min_d_alt;\n        if (component_members[root_u].size() < component_members[root_v].size()) {\n            min_d_alt = find_min_d_alternative(component_members[root_u], component_members[root_v], i);\n        } else {\n            min_d_alt = find_min_d_alternative(component_members[root_v], component_members[root_u], i);\n        }\n        \n        bool take_edge = false;\n        if (min_d_alt == -1) {\n            // Last chance to connect these components, must take it.\n            take_edge = true;\n        } else {\n            // Heuristic decision based on comparing current cost to expected cost of best alternative\n            int imp = importance[i];\n            if (imp == 0) imp = 6;\n            \n            double alpha_k;\n            switch(imp) {\n                case 1: alpha_k = 1.4; break;  // More willing to pay a premium for important edges\n                case 2: alpha_k = 1.2; break;\n                case 3: alpha_k = 1.0; break;\n                case 4: alpha_k = 0.85; break;\n                case 5: alpha_k = 0.7; break;  // Demand a bigger bargain for less important edges\n                default: alpha_k = 0.6; break;\n            }\n\n            // Time factor: be picky at the start, become more lenient towards the end.\n            // Using a quadratic curve to stay picky for longer.\n            double progress = static_cast<double>(i) / (M - 1);\n            double time_factor = 0.7 + 1.1 * progress * progress;\n\n            double expected_alt_cost = 2.0 * min_d_alt;\n            double threshold = alpha_k * time_factor * expected_alt_cost;\n\n            if (l < threshold) {\n                take_edge = true;\n            }\n        }\n        \n        if (take_edge) {\n            std::cout << 1 << std::endl;\n            \n            int old_root_u = dsu_main.leader(u);\n            int old_root_v = dsu_main.leader(v);\n            \n            dsu_main.merge(u, v);\n            int new_root = dsu_main.leader(u);\n\n            // Merge the smaller component's member list into the larger one\n            if (new_root == old_root_u) {\n                component_members[old_root_u].insert(component_members[old_root_u].end(),\n                    std::make_move_iterator(component_members[old_root_v].begin()),\n                    std::make_move_iterator(component_members[old_root_v].end()));\n                component_members[old_root_v].clear();\n            } else {\n                component_members[old_root_v].insert(component_members[old_root_v].end(),\n                    std::make_move_iterator(component_members[old_root_u].begin()),\n                    std::make_move_iterator(component_members[old_root_u].end()));\n                component_members[old_root_u].clear();\n            }\n        } else {\n            std::cout << 0 << std::endl;\n        }\n    }\n\n    return 0;\n}","ahc008":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <queue>\n#include <map>\n#include <chrono>\n#include <tuple>\n#include <numeric>\n\nusing namespace std;\n\n// --- Utilities ---\nstruct Point {\n    int r, c;\n\n    bool operator==(const Point& other) const { return r == other.r && c == other.c; }\n    bool operator!=(const Point& other) const { return !(*this == other); }\n    bool operator<(const Point& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n};\n\nnamespace std {\n    template <> struct hash<Point> {\n        size_t operator()(const Point& p) const { return hash<int>()(p.r * 31 + p.c); }\n    };\n}\n\nconst int H = 30, W = 30;\nconst int DR[] = {-1, 1, 0, 0};\nconst int DC[] = {0, 0, -1, 1};\nconst char MOVE_CH[] = {'U', 'D', 'L', 'R'};\nconst char BUILD_CH[] = {'u', 'd', 'l', 'r'};\n\nint N, M;\nvector<Point> pet_pos;\nvector<int> pet_type;\nvector<Point> human_pos;\nbool is_impassable[H][W];\n\nint dist(Point p1, Point p2) {\n    return abs(p1.r - p2.r) + abs(p1.c - p2.c);\n}\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < H && c >= 0 && c < W;\n}\n\n// --- Game State & Strategy ---\nPoint rendezvous_point;\nbool is_safe[H][W];\nvector<double> danger_map(H * W, 0.0);\nint current_turn = 0;\n\nenum Phase { EXPANSION, SEALING, CONSOLIDATION };\n\n// --- A* Pathfinder ---\nstruct Node {\n    Point p;\n    int g;\n    double h;\n    double cost;\n    bool operator>(const Node& other) const { return cost > other.cost; }\n};\n\nvector<Point> find_path(Point start, Point end, const vector<Point>& temp_impassable) {\n    priority_queue<Node, vector<Node>, greater<Node>> pq;\n    map<Point, Point> parent;\n    map<Point, int> g_score;\n\n    g_score[start] = 0;\n    pq.push({start, 0, (double)dist(start, end), (double)dist(start, end)});\n\n    bool found = false;\n    while (!pq.empty()) {\n        Node current = pq.top();\n        pq.pop();\n\n        if (current.p == end) {\n            found = true;\n            break;\n        }\n\n        if (g_score.count(current.p) && current.g > g_score[current.p]) continue;\n\n        for (int i = 0; i < 4; ++i) {\n            Point next_p = {current.p.r + DR[i], current.p.c + DC[i]};\n\n            if (!is_valid(next_p.r, next_p.c) || is_impassable[next_p.r][next_p.c]) continue;\n            bool is_temp_impassable = false;\n            for(const auto& obs : temp_impassable) if(obs == next_p) is_temp_impassable = true;\n            if(is_temp_impassable) continue;\n\n            int new_g = current.g + 1;\n            if (!g_score.count(next_p) || new_g < g_score[next_p]) {\n                g_score[next_p] = new_g;\n                parent[next_p] = current.p;\n                double h_val = dist(next_p, end);\n                const double DANGER_WEIGHT = 10.0;\n                double cost = new_g + h_val + DANGER_WEIGHT * danger_map[next_p.r * W + next_p.c];\n                pq.push({next_p, new_g, h_val, cost});\n            }\n        }\n    }\n\n    if (!found) return {};\n    vector<Point> path;\n    Point curr = end;\n    while (curr != start) {\n        path.push_back(curr);\n        curr = parent[curr];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nvoid initial_plan() {\n    double pet_com_r = 0, pet_com_c = 0;\n    for (const auto& p : pet_pos) { pet_com_r += p.r; pet_com_c += p.c; }\n    pet_com_r /= N;\n    pet_com_c /= N;\n\n    vector<Point> corners = {{0, 0}, {0, W - 1}, {H - 1, 0}, {H - 1, W - 1}};\n    double max_dist = -1;\n    for (const auto& corner : corners) {\n        double d = pow(corner.r - pet_com_r, 2) + pow(corner.c - pet_com_c, 2);\n        if (d > max_dist) {\n            max_dist = d;\n            rendezvous_point = corner;\n        }\n    }\n    fill(&is_safe[0][0], &is_safe[0][0] + H * W, false);\n}\n\nvoid update_danger_map() {\n    fill(danger_map.begin(), danger_map.end(), 0.0);\n    int pet_moves[] = {0, 1, 2, 3, 2, 2}; \n    for (int i = 0; i < N; ++i) {\n        int radius = pet_moves[pet_type[i]] + 1;\n        for (int r = 0; r < H; ++r) {\n            for (int c = 0; c < W; ++c) {\n                if (dist(pet_pos[i], {r, c}) < radius) {\n                    danger_map[r * W + c] += 1.0;\n                }\n            }\n        }\n    }\n}\n\nvoid update_safe_zone() {\n    bool new_safe[H][W];\n    fill(&new_safe[0][0], &new_safe[0][0] + H * W, false);\n    queue<Point> q;\n    \n    Point start_node = rendezvous_point;\n    if(is_impassable[start_node.r][start_node.c]) {\n        bool found_any_passable = false;\n        for(int r=0; r<H && !found_any_passable; ++r) for(int c=0; c<W; ++c) {\n            if(!is_impassable[r][c]) {\n                start_node = {r,c};\n                found_any_passable = true;\n                break;\n            }\n        }\n        if(!found_any_passable) {\n            copy(&new_safe[0][0], &new_safe[0][0] + H*W, &is_safe[0][0]);\n            return;\n        }\n    }\n    q.push(start_node);\n    new_safe[start_node.r][start_node.c] = true;\n\n    while (!q.empty()) {\n        Point curr = q.front(); q.pop();\n        for (int i = 0; i < 4; ++i) {\n            Point next_p = {curr.r + DR[i], curr.c + DC[i]};\n            if (is_valid(next_p.r, next_p.c) && !is_impassable[next_p.r][next_p.c] && !new_safe[next_p.r][next_p.c]) {\n                new_safe[next_p.r][next_p.c] = true;\n                q.push(next_p);\n            }\n        }\n    }\n    copy(&new_safe[0][0], &new_safe[0][0] + H*W, &is_safe[0][0]);\n}\n\nvoid check_and_reset_plan() {\n    if (current_turn > 50 && current_turn % 20 == 0) {\n        int safe_zone_size = 0;\n        for(int r=0; r<H; ++r) for(int c=0; c<W; ++c) if(is_safe[r][c]) safe_zone_size++;\n\n        bool pet_in_safe_zone = false;\n        for (const auto& p_pos : pet_pos) {\n            if (is_safe[p_pos.r][p_pos.c]) {\n                pet_in_safe_zone = true;\n                break;\n            }\n        }\n        if (pet_in_safe_zone && safe_zone_size > 20) initial_plan();\n    }\n}\n\nstring solve() {\n    const int PHASE1_END = 260;\n    const int PHASE2_END = 290;\n    \n    if (current_turn == 0) initial_plan();\n    else check_and_reset_plan();\n\n    Phase current_phase = EXPANSION;\n    if (current_turn >= PHASE1_END) current_phase = SEALING;\n    if (current_turn >= PHASE2_END) current_phase = CONSOLIDATION;\n\n    update_danger_map();\n    update_safe_zone();\n    \n    vector<bool> can_build(H * W, true);\n    for(int r=0; r<H; ++r) for(int c=0; c<W; ++c) {\n        if (is_impassable[r][c]) can_build[r*W+c] = false;\n    }\n    for (const auto& p : human_pos) can_build[p.r*W+p.c] = false;\n    for (const auto& p : pet_pos) {\n        can_build[p.r*W+p.c] = false;\n        for (int i=0; i<4; ++i) {\n            Point adj = {p.r+DR[i], p.c+DC[i]};\n            if (is_valid(adj.r, adj.c)) can_build[adj.r*W+adj.c] = false;\n        }\n    }\n\n    vector<Point> tasks;\n    if (current_phase == EXPANSION || current_phase == SEALING) {\n        for (int r=0; r<H; ++r) for (int c=0; c<W; ++c) {\n            if (!is_safe[r][c] && !is_impassable[r][c]) {\n                for (int i=0; i<4; ++i) {\n                    Point adj = {r+DR[i], c+DC[i]};\n                    if (is_valid(adj.r, adj.c) && is_safe[adj.r][adj.c]) {\n                        tasks.push_back({r,c});\n                        break;\n                    }\n                }\n            }\n        }\n    } else { // CONSOLIDATION\n        double center_r=0, center_c=0; int count=0;\n        for (int r=0; r<H; ++r) for (int c=0; c<W; ++c) if (is_safe[r][c]) { center_r+=r; center_c+=c; count++; }\n        if (count > 0) tasks.push_back({(int)round(center_r/count), (int)round(center_c/count)});\n        else tasks.push_back(rendezvous_point);\n    }\n    \n    vector<int> human_task(M, -1);\n    using AssignmentCand = tuple<int, int, int>;\n    vector<AssignmentCand> candidates;\n    if (!tasks.empty()){\n        for (int i=0; i<M; ++i) {\n            for (int j=0; j<(int)tasks.size(); ++j) {\n                if (current_phase == CONSOLIDATION) {\n                    candidates.emplace_back(dist(human_pos[i], tasks[j]), i, j);\n                } else {\n                    int min_build_site_dist = 1e9;\n                    for(int k=0; k<4; ++k) {\n                        Point site = {tasks[j].r+DR[k], tasks[j].c+DC[k]};\n                        if(is_valid(site.r, site.c) && is_safe[site.r][site.c])\n                             min_build_site_dist = min(min_build_site_dist, dist(human_pos[i], site));\n                    }\n                    if(min_build_site_dist != 1e9) candidates.emplace_back(min_build_site_dist, i, j);\n                }\n            }\n        }\n    }\n    sort(candidates.begin(), candidates.end());\n    vector<bool> task_assigned(tasks.size(), false); vector<bool> human_assigned(M, false);\n    for(const auto& cand : candidates){\n        int d, h_id, t_id; tie(d, h_id, t_id) = cand;\n        if(!human_assigned[h_id] && !task_assigned[t_id]){\n            human_task[h_id] = t_id; human_assigned[h_id] = true; task_assigned[t_id] = true;\n        }\n    }\n    \n    string actions_str(M, '.'); vector<Point> planned_walls;\n    for (int i=0; i<M; ++i) {\n        Point current_pos = human_pos[i];\n        if (!is_safe[current_pos.r][current_pos.c] && current_phase != CONSOLIDATION) {\n            Point closest_safe_spot = {-1,-1}; int min_dist_to_safe = 1e9;\n            for(int r=0; r<H; ++r) for(int c=0; c<W; ++c) if(is_safe[r][c]) {\n                int d = dist(current_pos, {r,c});\n                if(d < min_dist_to_safe) {min_dist_to_safe = d; closest_safe_spot = {r,c};}\n            }\n            if(closest_safe_spot.r != -1) {\n                vector<Point> path = find_path(current_pos, closest_safe_spot, planned_walls);\n                if (!path.empty()) {\n                    Point next_pos = path[0];\n                    for (int d=0; d<4; ++d) if (current_pos.r+DR[d]==next_pos.r && current_pos.c+DC[d]==next_pos.c) { actions_str[i] = MOVE_CH[d]; break; }\n                }\n            }\n            continue;\n        }\n\n        if (human_task[i] == -1) continue;\n        Point task_pos = tasks[human_task[i]];\n        \n        if (current_phase == CONSOLIDATION) {\n            vector<Point> path = find_path(current_pos, task_pos, planned_walls);\n            if (!path.empty()) {\n                Point next_pos = path[0];\n                for (int d=0; d<4; ++d) if (current_pos.r+DR[d]==next_pos.r && current_pos.c+DC[d]==next_pos.c) { actions_str[i] = MOVE_CH[d]; break;}\n            }\n        } else {\n            Point best_build_site = {-1,-1}; int min_dist = 1e9;\n            for (int d=0; d<4; ++d) {\n                Point site = {task_pos.r+DR[d], task_pos.c+DC[d]};\n                if (is_valid(site.r, site.c) && is_safe[site.r][site.c]) {\n                    if (dist(current_pos, site) < min_dist) { min_dist = dist(current_pos, site); best_build_site = site;}\n                }\n            }\n            if(best_build_site.r == -1) continue;\n            \n            if (current_pos == best_build_site) {\n                if (can_build[task_pos.r*W+task_pos.c]) {\n                    for (int d=0; d<4; ++d) if (current_pos.r+DR[d]==task_pos.r && current_pos.c+DC[d]==task_pos.c) {\n                        actions_str[i] = BUILD_CH[d]; planned_walls.push_back(task_pos); break;\n                    }\n                } else {\n                    double max_flee_score = -1e9; int best_dir = -1;\n                    for (int d=0; d<4; ++d) {\n                        Point next_p = {current_pos.r+DR[d], current_pos.c+DC[d]};\n                        if (is_valid(next_p.r, next_p.c) && !is_impassable[next_p.r][next_p.c] && is_safe[next_p.r][next_p.c]) {\n                            double min_dist_to_pet = 1e9;\n                            for(const auto& p : pet_pos) min_dist_to_pet = min(min_dist_to_pet, (double)dist(p, next_p));\n                            double score = min_dist_to_pet - danger_map[next_p.r * W + next_p.c];\n                            if (score > max_flee_score) { max_flee_score = score; best_dir = d; }\n                        }\n                    }\n                    if (best_dir != -1) actions_str[i] = MOVE_CH[best_dir];\n                }\n            } else {\n                vector<Point> path = find_path(current_pos, best_build_site, planned_walls);\n                if (!path.empty()) {\n                    Point next_pos = path[0];\n                    for (int d=0; d<4; ++d) if (current_pos.r+DR[d]==next_pos.r && current_pos.c+DC[d]==next_pos.c) { actions_str[i] = MOVE_CH[d]; break;}\n                }\n            }\n        }\n    }\n    return actions_str;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false); cin.tie(NULL);\n    cin >> N;\n    pet_pos.resize(N); pet_type.resize(N);\n    for (int i=0; i<N; ++i) { cin >> pet_pos[i].r >> pet_pos[i].c >> pet_type[i]; pet_pos[i].r--; pet_pos[i].c--; }\n    cin >> M;\n    human_pos.resize(M);\n    for (int i=0; i<M; ++i) { cin >> human_pos[i].r >> human_pos[i].c; human_pos[i].r--; human_pos[i].c--; }\n    fill(&is_impassable[0][0], &is_impassable[0][0]+H*W, false);\n\n    for (int t=0; t<300; ++t) {\n        current_turn = t;\n        string actions = solve();\n        cout << actions << endl;\n        \n        vector<Point> planned_walls;\n        for(int i=0; i<M; ++i) {\n            char act = actions[i]; Point p = human_pos[i];\n            if (act == 'u') planned_walls.push_back({p.r-1, p.c}); else if (act == 'd') planned_walls.push_back({p.r+1, p.c});\n            else if (act == 'l') planned_walls.push_back({p.r, p.c-1}); else if (act == 'r') planned_walls.push_back({p.r, p.c+1});\n        }\n        for(int i=0; i<M; ++i) {\n            char act = actions[i]; Point& p = human_pos[i]; Point next_p = p;\n            if (act == 'U') next_p.r--; else if (act == 'D') next_p.r++; else if (act == 'L') next_p.c--; else if (act == 'R') next_p.c++;\n            bool blocked = false; for(const auto& w : planned_walls) if(next_p == w) blocked = true;\n            if (act >= 'A' && act <= 'Z' && !blocked) p = next_p;\n            else if (act >= 'a' && act <= 'z') {\n                if (act == 'u') is_impassable[p.r-1][p.c] = true; else if (act == 'd') is_impassable[p.r+1][p.c] = true;\n                else if (act == 'l') is_impassable[p.r][p.c-1] = true; else if (act == 'r') is_impassable[p.r][p.c+1] = true;\n            }\n        }\n        for (int i=0; i<N; ++i) {\n            string move_str; cin >> move_str;\n            for (char move : move_str) {\n                if (move == 'U') pet_pos[i].r--; else if (move == 'D') pet_pos[i].r++;\n                else if (move == 'L') pet_pos[i].c--; else if (move == 'R') pet_pos[i].c++;\n            }\n        }\n    }\n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <array>\n#include <algorithm>\n#include <cmath>\n#include <utility>\n\nusing namespace std;\n\n// Using long double for better precision\nusing ld = long double;\n\nconstexpr int N = 20;\nconstexpr int MAX_TURNS = 200;\n// BEAM_WIDTH=50 is a balance between search breadth and execution time.\nconstexpr int BEAM_WIDTH = 50; \nconstexpr ld PROB_PRUNING_THRESH = 1e-30L;\nconstexpr ld TOTAL_PROB_THRESH = 1e-20L;\n\nstruct State {\n    int r, c;\n    bool operator==(const State& other) const {\n        return r == other.r && c == other.c;\n    }\n};\n\nState start_pos, target_pos;\nld forget_prob;\narray<array<bool, N - 1>, N> h_walls;\narray<array<bool, N>, N - 1> v_walls;\narray<array<int, N>, N> dist_to_target;\narray<array<array<State, 4>, N>, N> next_pos_cache;\n\nconst int DR[] = {-1, 1, 0, 0}; // U, D, L, R\nconst int DC[] = {0, 0, -1, 1};\nconst char DIRS[] = \"UDLR\";\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N;\n}\n\nState internal_move_state(State s, int dir_idx) {\n    int nr = s.r + DR[dir_idx];\n    int nc = s.c + DC[dir_idx];\n\n    if (!is_valid(nr, nc)) {\n        return s;\n    }\n\n    if (DR[dir_idx] == -1 && v_walls[s.r - 1][s.c]) return s; // U\n    if (DR[dir_idx] == 1 && v_walls[s.r][s.c]) return s;    // D\n    if (DC[dir_idx] == -1 && h_walls[s.r][s.c - 1]) return s; // L\n    if (DC[dir_idx] == 1 && h_walls[s.r][s.c]) return s;    // R\n\n    return {nr, nc};\n}\n\nvoid precompute_moves() {\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            for (int i = 0; i < 4; ++i) {\n                next_pos_cache[r][c][i] = internal_move_state({r, c}, i);\n            }\n        }\n    }\n}\n\nState move_state(State s, int dir_idx) {\n    return next_pos_cache[s.r][s.c][dir_idx];\n}\n\nvoid bfs_from_target() {\n    for (auto& row : dist_to_target) row.fill(-1);\n    \n    queue<State> q;\n    q.push(target_pos);\n    dist_to_target[target_pos.r][target_pos.c] = 0;\n    \n    while (!q.empty()) {\n        State u = q.front();\n        q.pop();\n        \n        for (int i = 0; i < 4; ++i) {\n            // Find predecessors by checking moves from neighbors\n            State predecessor = {u.r - DR[i], u.c - DC[i]};\n            if (!is_valid(predecessor.r, predecessor.c)) continue;\n            \n            State moved_from_predecessor = move_state(predecessor, i);\n            if (moved_from_predecessor.r == u.r && moved_from_predecessor.c == u.c) {\n                 if (dist_to_target[predecessor.r][predecessor.c] == -1) {\n                    dist_to_target[predecessor.r][predecessor.c] = dist_to_target[u.r][u.c] + 1;\n                    q.push(predecessor);\n                }\n            }\n        }\n    }\n}\n\nusing ProbDist = array<array<ld, N>, N>;\n\nstruct Candidate {\n    string moves;\n    ProbDist prob;\n    ld accumulated_score;\n    ld heuristic_score;\n\n    void calculate_heuristic_score(int turn) {\n        ld future_score = 0;\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                if (prob[r][c] > PROB_PRUNING_THRESH) {\n                    int d = dist_to_target[r][c];\n                    if (d <= 0) continue; // d=0 is target, d=-1 is unreachable\n                    ld expected_turns_to_reach = (ld)d / (1.0L - forget_prob);\n                    if (turn + expected_turns_to_reach <= 400) {\n                       future_score += prob[r][c] * (401.0L - (turn + expected_turns_to_reach));\n                    }\n                }\n            }\n        }\n        heuristic_score = accumulated_score + future_score;\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> start_pos.r >> start_pos.c >> target_pos.r >> target_pos.c;\n    double p_double;\n    cin >> p_double;\n    forget_prob = p_double;\n\n    for (int i = 0; i < N; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < N - 1; ++j) {\n            h_walls[i][j] = (row[j] == '1');\n        }\n    }\n    for (int i = 0; i < N - 1; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < N; ++j) {\n            v_walls[i][j] = (row[j] == '1');\n        }\n    }\n    \n    precompute_moves();\n    bfs_from_target();\n\n    vector<Candidate> beam;\n    {\n        Candidate initial_candidate;\n        initial_candidate.moves = \"\";\n        for(auto& row : initial_candidate.prob) row.fill(0.0L);\n        initial_candidate.prob[start_pos.r][start_pos.c] = 1.0L;\n        initial_candidate.accumulated_score = 0.0L;\n        initial_candidate.calculate_heuristic_score(1);\n        beam.push_back(initial_candidate);\n    }\n    \n    for (int t = 1; t <= MAX_TURNS; ++t) {\n        vector<Candidate> next_candidates;\n        next_candidates.reserve(beam.size() * 4);\n\n        for (const auto& cand : beam) {\n            ld total_prob_mass = 0;\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    total_prob_mass += cand.prob[r][c];\n                }\n            }\n            if(total_prob_mass < TOTAL_PROB_THRESH) {\n                next_candidates.push_back(cand);\n                continue;\n            }\n\n            // --- DYNAMIC MOVE ORDERING based on max probability cell ---\n            ld max_p = -1.0L;\n            int max_r = -1, max_c = -1;\n            for(int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    if (cand.prob[r][c] > max_p) {\n                        max_p = cand.prob[r][c];\n                        max_r = r;\n                        max_c = c;\n                    }\n                }\n            }\n            \n            if (max_r == -1) { max_r = start_pos.r; max_c = start_pos.c; }\n\n            ld dr = target_pos.r - max_r;\n            ld dc = target_pos.c - max_c;\n\n            vector<pair<ld, int>> move_scores;\n            move_scores.push_back({-dr, 0}); // U\n            move_scores.push_back({dr, 1});  // D\n            move_scores.push_back({-dc, 2}); // L\n            move_scores.push_back({dc, 3});  // R\n            sort(move_scores.rbegin(), move_scores.rend());\n            \n            array<int, 4> dynamic_dirs_order;\n            for(int i = 0; i < 4; ++i) dynamic_dirs_order[i] = move_scores[i].second;\n            // --- END DYNAMIC MOVE ORDERING ---\n\n            for (int dir_idx : dynamic_dirs_order) {\n                Candidate next_cand;\n                next_cand.moves = cand.moves + DIRS[dir_idx];\n                for(auto& row : next_cand.prob) row.fill(0.0L);\n                \n                ld prob_reaching_this_turn = 0.0L;\n\n                for (int r = 0; r < N; ++r) {\n                    for (int c = 0; c < N; ++c) {\n                        if (cand.prob[r][c] < PROB_PRUNING_THRESH) continue;\n                        \n                        next_cand.prob[r][c] += cand.prob[r][c] * forget_prob;\n\n                        State next_pos = move_state({r, c}, dir_idx);\n                        if (next_pos == target_pos) {\n                            prob_reaching_this_turn += cand.prob[r][c] * (1.0L - forget_prob);\n                        } else {\n                            next_cand.prob[next_pos.r][next_pos.c] += cand.prob[r][c] * (1.0L - forget_prob);\n                        }\n                    }\n                }\n                \n                next_cand.accumulated_score = cand.accumulated_score + prob_reaching_this_turn * (401 - t);\n                next_cand.calculate_heuristic_score(t + 1);\n                \n                next_candidates.push_back(move(next_cand));\n            }\n        }\n\n        sort(next_candidates.begin(), next_candidates.end(), [](const Candidate& a, const Candidate& b) {\n            return a.heuristic_score > b.heuristic_score;\n        });\n\n        if (next_candidates.size() > BEAM_WIDTH) {\n            next_candidates.resize(BEAM_WIDTH);\n        }\n        beam = move(next_candidates);\n    }\n\n    Candidate best_candidate;\n    ld max_score = -1.0;\n    for (const auto& cand : beam) {\n        if (cand.accumulated_score > max_score) {\n            max_score = cand.accumulated_score;\n            best_candidate = cand;\n        }\n    }\n\n    cout << best_candidate.moves << endl;\n\n    return 0;\n}","ahc010":"#include <iostream>\n#include <vector>\n#include <string>\n#include <array>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <cmath>\n#include <tuple>\n\n// --- Utilities ---\n\nclass Timer {\n    std::chrono::time_point<std::chrono::high_resolution_clock> start_time;\npublic:\n    Timer() {\n        start_time = std::chrono::high_resolution_clock::now();\n    }\n    double get_elapsed_sec() {\n        auto now = std::chrono::high_resolution_clock::now();\n        return std::chrono::duration<double>(now - start_time).count();\n    }\n};\n\nstruct Rng {\n    std::mt19937 mt;\n    Rng() : mt(std::chrono::high_resolution_clock::now().time_since_epoch().count()) {}\n    int get_int(int min, int max) {\n        std::uniform_int_distribution<int> dist(min, max);\n        return dist(mt);\n    }\n    double get_double(double min, double max) {\n        std::uniform_real_distribution<double> dist(min, max);\n        return dist(mt);\n    }\n};\n\n// --- Problem Constants & Globals ---\nconstexpr int N = 30;\nconstexpr int di[] = {0, -1, 0, 1}; // L, U, R, D\nconstexpr int dj[] = {-1, 0, 1, 0};\n\nconst int to[8][4] = {\n\t{1, 0, -1, -1}, {3, -1, -1, 0}, {-1, -1, 3, 2}, {-1, 2, 1, -1},\n\t{1, 0, 3, 2},   {3, 2, 1, 0},   {2, -1, 0, -1}, {-1, 3, -1, 1},\n};\n\nint t_rot[8][4];\nstd::array<std::array<int, N>, N> initial_tiles;\n\nvoid precompute_rotations() {\n    for (int i = 0; i < 8; ++i) {\n        t_rot[i][0] = i;\n    }\n    for (int r = 1; r < 4; ++r) {\n        for (int i = 0; i < 8; ++i) {\n            int prev_t = t_rot[i][r - 1];\n            int next_t;\n            if (0 <= prev_t && prev_t <= 3) {\n                next_t = (prev_t + 1) % 4;\n            } else if (prev_t == 4) next_t = 5;\n            else if (prev_t == 5) next_t = 4;\n            else if (prev_t == 6) next_t = 7;\n            else next_t = 6;\n            t_rot[i][r] = next_t;\n        }\n    }\n}\n\n// --- Core Logic ---\n\nusing RotationsGrid = std::array<std::array<int, N>, N>;\n\nstruct ScoreInfo {\n    long long product_score = 0;\n    long long total_path_len_score = 0;\n};\n\nScoreInfo calculate_scores(const RotationsGrid& rotations) {\n    std::array<std::array<int, N>, N> tiles;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            tiles[i][j] = t_rot[initial_tiles[i][j]][rotations[i][j]];\n        }\n    }\n\n    bool visited_edge[N][N][4] = {};\n    std::vector<int> loop_lengths;\n    long long total_path_len = 0;\n\n    for (int si = 0; si < N; ++si) {\n        for (int sj = 0; sj < N; ++sj) {\n            for (int sd = 0; sd < 4; ++sd) {\n                if (visited_edge[si][sj][sd]) continue;\n\n                int ci = si, cj = sj, cd = sd;\n                int length = 0;\n                \n                std::vector<std::tuple<int, int, int>> path_history;\n                bool is_loop = false;\n\n                for(int k=0; k < N*N*2 + 5; ++k) {\n                    if (visited_edge[ci][cj][cd]) break;\n                    path_history.emplace_back(ci, cj, cd);\n                    \n                    int d_out = to[tiles[ci][cj]][cd];\n                    if (d_out == -1) break;\n\n                    int ni = ci + di[d_out];\n                    int nj = cj + dj[d_out];\n                    \n                    if (ni < 0 || ni >= N || nj < 0 || nj >= N) break;\n                    \n                    length++;\n                    ci = ni; cj = nj; cd = (d_out + 2) % 4;\n\n                    if (ci == si && cj == sj && cd == sd) {\n                        is_loop = true;\n                        break;\n                    }\n                }\n                \n                if (is_loop) loop_lengths.push_back(length);\n                total_path_len += length;\n                \n                for (const auto& [pi, pj, pd] : path_history) {\n                    visited_edge[pi][pj][pd] = true;\n                }\n            }\n        }\n    }\n    \n    ScoreInfo info;\n    info.total_path_len_score = total_path_len;\n    if (loop_lengths.size() >= 2) {\n        std::sort(loop_lengths.rbegin(), loop_lengths.rend());\n        info.product_score = static_cast<long long>(loop_lengths[0]) * loop_lengths[1];\n    }\n\n    return info;\n}\n\nvoid solve() {\n    Timer timer;\n    Rng rng;\n    \n    for (int i = 0; i < N; ++i) {\n        std::string row;\n        std::cin >> row;\n        for (int j = 0; j < N; ++j) {\n            initial_tiles[i][j] = row[j] - '0';\n        }\n    }\n\n    precompute_rotations();\n\n    RotationsGrid current_rotations;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            current_rotations[i][j] = rng.get_int(0, 3);\n        }\n    }\n\n    RotationsGrid best_rotations_ever = current_rotations;\n    ScoreInfo current_scores = calculate_scores(current_rotations);\n    long long best_prod_score_ever = current_scores.product_score;\n\n    const double time_limit = 1.95;\n    const double phase1_time_limit = 0.8;\n\n    // --- Phase 1: Optimize for total path length ---\n    double T_start1 = 50, T_end1 = 1;\n    long long current_eval_score = current_scores.total_path_len_score;\n\n    while (timer.get_elapsed_sec() < phase1_time_limit) {\n        double progress = timer.get_elapsed_sec() / phase1_time_limit;\n        double T = T_start1 * std::pow(T_end1 / T_start1, progress);\n\n        RotationsGrid next_rotations = current_rotations;\n        \n        if (rng.get_double(0.0, 1.0) < 0.2) { // 20% 2x2 move\n            int r = rng.get_int(0, N - 2);\n            int c = rng.get_int(0, N - 2);\n            for(int i=0; i<2; ++i) for(int j=0; j<2; ++j) {\n                 next_rotations[r+i][c+j] = rng.get_int(0,3);\n            }\n        } else { // 80% single move\n            int r = rng.get_int(0, N - 1);\n            int c = rng.get_int(0, N - 1);\n            int old_rot = next_rotations[r][c];\n            int new_rot;\n            do { new_rot = rng.get_int(0, 3); } while (new_rot == old_rot);\n            next_rotations[r][c] = new_rot;\n        }\n\n        ScoreInfo new_scores = calculate_scores(next_rotations);\n        long long new_eval_score = new_scores.total_path_len_score;\n        double delta = static_cast<double>(new_eval_score - current_eval_score);\n        \n        if (delta >= 0 || rng.get_double(0.0, 1.0) < std::exp(delta / T)) {\n            current_rotations = next_rotations;\n            current_eval_score = new_eval_score;\n        }\n        \n        if (new_scores.product_score > best_prod_score_ever) {\n            best_prod_score_ever = new_scores.product_score;\n            best_rotations_ever = next_rotations;\n        }\n    }\n    \n    // --- Phase 2: Optimize for product of two largest loops ---\n    current_rotations = best_rotations_ever;\n    current_scores = calculate_scores(current_rotations);\n    long long current_prod_score = current_scores.product_score;\n    \n    double T_start2 = 5000, T_end2 = 10;\n\n    while (timer.get_elapsed_sec() < time_limit) {\n        double elapsed_in_phase2 = timer.get_elapsed_sec() - phase1_time_limit;\n        double phase2_duration = time_limit - phase1_time_limit;\n        double progress = elapsed_in_phase2 / phase2_duration;\n        double T = T_start2 * std::pow(T_end2 / T_start2, progress);\n\n        RotationsGrid next_rotations = current_rotations;\n        \n        if (rng.get_double(0.0, 1.0) < 0.05) { // 5% 2x2 move\n            int r = rng.get_int(0, N - 2);\n            int c = rng.get_int(0, N - 2);\n            for(int i=0; i<2; ++i) for(int j=0; j<2; ++j) {\n                 next_rotations[r+i][c+j] = rng.get_int(0,3);\n            }\n        } else { // 95% single move\n            int r = rng.get_int(0, N - 1);\n            int c = rng.get_int(0, N - 1);\n            int old_rot = next_rotations[r][c];\n            int new_rot;\n            do { new_rot = rng.get_int(0, 3); } while (new_rot == old_rot);\n            next_rotations[r][c] = new_rot;\n        }\n        \n        ScoreInfo new_scores = calculate_scores(next_rotations);\n        long long new_prod_score = new_scores.product_score;\n        double delta = static_cast<double>(new_prod_score - current_prod_score);\n        \n        if (delta >= 0 || rng.get_double(0.0, 1.0) < std::exp(delta / T)) {\n            current_rotations = next_rotations;\n            current_prod_score = new_prod_score;\n            if (current_prod_score > best_prod_score_ever) {\n                best_prod_score_ever = current_prod_score;\n                best_rotations_ever = current_rotations;\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            std::cout << best_rotations_ever[i][j];\n        }\n    }\n    std::cout << std::endl;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc011":"#include <iostream>\n#include <vector>\n#include <string>\n#include <array>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <cmath>\n#include <map>\n#include <queue>\n#include <unordered_map>\n#include <functional>\n\n#include <atcoder/mincostflow>\n\nusing namespace std;\n\n// --- Timer ---\nusing namespace std::chrono;\nauto start_time = high_resolution_clock::now();\ndouble time_limit = 2.85; // More conservative time limit\n\nbool is_time_over() {\n    auto current_time = high_resolution_clock::now();\n    duration<double> elapsed = current_time - start_time;\n    return elapsed.count() > time_limit;\n}\n\n// --- Random Number Generator ---\nmt19937 rng(time(0));\n\n// --- Constants and Type Definitions ---\nconstexpr int MAX_N = 10;\nconstexpr int MAX_N2 = MAX_N * MAX_N;\n\nint N, T;\narray<int, 4> dr = {-1, 1, 0, 0}; // U, D, L, R\narray<int, 4> dc = {0, 0, -1, 1};\nstring move_chars = \"UDLR\";\narray<int, 4> opposite_move_idx = {1, 0, 3, 2}; // U->D, D->U, L->R, R->L\n\nstruct Board {\n    array<int, MAX_N2> grid;\n    int empty_pos = -1;\n    void find_empty() {\n        for (int i = 0; i < N * N; ++i) {\n            if (grid[i] == 0) {\n                empty_pos = i;\n                return;\n            }\n        }\n    }\n};\n\nint char_to_hex(char c) {\n    if (c >= '0' && c <= '9') return c - '0';\n    return c - 'a' + 10;\n}\n\nstruct DSU {\n    vector<int> parent;\n    vector<int> sz;\n    DSU(int n) {\n        parent.resize(n);\n        sz.resize(n);\n        for (int i = 0; i < n; i++) {\n            parent[i] = i;\n            sz[i] = 1;\n        }\n    }\n    int find(int i) {\n        if (parent[i] == i) return i;\n        return parent[i] = find(parent[i]);\n    }\n    void unite(int i, int j) {\n        int root_i = find(i);\n        int root_j = find(j);\n        if (root_i != root_j) {\n            if (sz[root_i] < sz[root_j]) swap(root_i, root_j);\n            parent[root_j] = root_i;\n            sz[root_i] += sz[root_j];\n        }\n    }\n};\n\n// --- Global State for Solver ---\nBoard initial_board;\narray<int, 16> initial_tile_counts{};\nvector<pair<int, int>> initial_pos_by_type[16];\narray<int, MAX_N2> best_target_grid;\nlong long best_dist_score = -1;\narray<int, MAX_N2> dest_of_tile_id;\nstring ida_solution;\nconst int IDA_FOUND = -1;\nconst int IDA_TIMEOUT = -2;\n\nvoid evaluate_target(const array<int, MAX_N2>& target_grid, long long& connectivity_score, long long& dist_score) {\n    DSU dsu(N * N);\n    int edges = 0;\n    connectivity_score = 0;\n\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int pos = r * N + c;\n            if (target_grid[pos] == 0) continue;\n            if (r + 1 < N && target_grid[(r+1)*N+c] != 0 && (target_grid[pos] & 8) && (target_grid[(r+1)*N+c] & 2)) {\n                if (dsu.find(pos) == dsu.find((r+1)*N+c)) connectivity_score -= 10000000;\n                else { dsu.unite(pos, (r+1)*N+c); edges++; }\n            }\n            if (c + 1 < N && target_grid[r*N+c+1] != 0 && (target_grid[pos] & 4) && (target_grid[r*N+c+1] & 1)) {\n                if (dsu.find(pos) == dsu.find(r*N+c+1)) connectivity_score -= 10000000;\n                else { dsu.unite(pos, r*N+c+1); edges++; }\n            }\n        }\n    }\n    \n    int non_empty_cells = N * N - 1;\n    int max_comp_size = 0;\n    for(int i = 0; i < N * N; ++i) {\n        if(target_grid[i] != 0 && dsu.parent[i] == i) max_comp_size = max(max_comp_size, dsu.sz[i]);\n    }\n    \n    connectivity_score += (long long)max_comp_size * 100000;\n    if (max_comp_size == non_empty_cells && edges == non_empty_cells - 1) connectivity_score += 100000000;\n\n    vector<int> target_pos_by_type[16];\n    for(int i=0; i<N*N; ++i) if(target_grid[i] != 0) target_pos_by_type[target_grid[i]].push_back(i);\n    \n    dist_score = 0;\n    for (int type = 1; type <= 15; ++type) {\n        if (initial_tile_counts[type] == 0) continue;\n        vector<pair<int, int>> s_coords, d_coords;\n        for (auto p : initial_pos_by_type[type]) s_coords.push_back(p);\n        for (auto pos : target_pos_by_type[type]) d_coords.push_back({pos / N, pos % N});\n        sort(s_coords.begin(), s_coords.end());\n        sort(d_coords.begin(), d_coords.end());\n        for (size_t i = 0; i < s_coords.size(); ++i) dist_score += abs(s_coords[i].first - d_coords[i].first) + abs(s_coords[i].second - d_coords[i].second);\n    }\n}\n\n\n// --- IDA* Solver ---\nint calculate_h(const array<uint8_t, MAX_N2>& board_ids) {\n    int h = 0;\n    for (int i = 0; i < N * N; ++i) {\n        if (board_ids[i] != 255) { // 255 represents empty\n            int tile_id = board_ids[i];\n            int dest_pos = dest_of_tile_id[tile_id];\n            h += abs(i / N - dest_pos / N) + abs(i % N - dest_pos % N);\n        }\n    }\n    return h;\n}\n\nint ida_dfs(array<uint8_t, MAX_N2>& board_ids, int empty_pos, int g, int f_limit, int last_move_idx, string& path) {\n    int h = calculate_h(board_ids);\n    int f = g + h;\n    if (f > f_limit) return f;\n    if (h == 0) {\n        ida_solution = path;\n        return IDA_FOUND;\n    }\n    if (is_time_over()) return IDA_TIMEOUT;\n\n    int r = empty_pos / N, c = empty_pos % N;\n    int next_min_f = 1e9;\n\n    for (int i = 0; i < 4; ++i) {\n        if (g > 0 && i == opposite_move_idx[last_move_idx]) continue;\n        int nr = r + dr[i], nc = c + dc[i];\n        if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n        \n        int next_empty_pos = nr * N + nc;\n        swap(board_ids[empty_pos], board_ids[next_empty_pos]);\n        path.push_back(move_chars[i]);\n\n        int res = ida_dfs(board_ids, next_empty_pos, g + 1, f_limit, i, path);\n        \n        swap(board_ids[empty_pos], board_ids[next_empty_pos]);\n        path.pop_back();\n\n        if (res == IDA_FOUND || res == IDA_TIMEOUT) return res;\n        next_min_f = min(next_min_f, res);\n    }\n    return next_min_f;\n}\n\nstring solve_puzzle_ida() {\n    array<uint8_t, MAX_N2> initial_board_ids; // maps pos -> tile_id\n    array<int, MAX_N2> initial_pos_of_id;   // maps tile_id -> initial_pos\n    int current_id = 0;\n    for(int i = 0; i < N * N; ++i) {\n        if (initial_board.grid[i] != 0) {\n            initial_board_ids[i] = current_id;\n            initial_pos_of_id[current_id] = i;\n            current_id++;\n        } else {\n            initial_board_ids[i] = 255; // empty\n        }\n    }\n\n    for (int type = 1; type <= 15; ++type) {\n        int count = initial_tile_counts[type];\n        if (count == 0) continue;\n        \n        vector<int> type_initial_ids;\n        for(int id = 0; id < N*N-1; ++id) {\n            if (initial_board.grid[initial_pos_of_id[id]] == type) {\n                type_initial_ids.push_back(id);\n            }\n        }\n\n        vector<int> target_pos_for_type;\n        for (int i = 0; i < N * N; ++i) if (best_target_grid[i] == type) target_pos_for_type.push_back(i);\n\n        atcoder::mcf_graph<int, int> graph(2 * count + 2);\n        int s = 2 * count, t = 2 * count + 1;\n\n        for (int i = 0; i < count; ++i) {\n            graph.add_edge(s, i, 1, 0);\n            graph.add_edge(i + count, t, 1, 0);\n            for (int j = 0; j < count; ++j) {\n                int start_pos = initial_pos_of_id[type_initial_ids[i]];\n                int target_pos = target_pos_for_type[j];\n                int dist = abs(start_pos / N - target_pos / N) + abs(start_pos % N - target_pos % N);\n                graph.add_edge(i, j + count, 1, dist);\n            }\n        }\n        graph.flow(s, t, count);\n        for (auto edge : graph.edges()) {\n            if (edge.from < count && edge.to >= count && edge.to < 2 * count && edge.flow > 0) {\n                dest_of_tile_id[type_initial_ids[edge.from]] = target_pos_for_type[edge.to - count];\n            }\n        }\n    }\n    \n    int f_limit = calculate_h(initial_board_ids);\n    string path = \"\";\n    while (f_limit <= T) {\n        if (is_time_over()) break;\n        int res = ida_dfs(initial_board_ids, initial_board.empty_pos, 0, f_limit, -1, path);\n        if (res == IDA_FOUND) return ida_solution;\n        if (res == IDA_TIMEOUT) break;\n        if (res > T) break;\n        f_limit = res;\n    }\n    \n    return \"\";\n}\n\n\nint main() {\n    ios_base::sync_with_stdio(false); cin.tie(NULL);\n    cin >> N >> T;\n    for (int i = 0; i < N; ++i) {\n        string row; cin >> row;\n        for (int j = 0; j < N; ++j) {\n            int type = char_to_hex(row[j]);\n            initial_board.grid[i * N + j] = type;\n            if (type != 0) { initial_tile_counts[type]++; initial_pos_by_type[type].push_back({i, j}); }\n        }\n    }\n    initial_board.find_empty();\n\n    double sa_time_allowed = time_limit * 0.90;\n    auto sa_start_time = high_resolution_clock::now();\n\n    array<int, MAX_N2> current_grid;\n    vector<int> tiles;\n    for (int type = 1; type <= 15; ++type) for (int i = 0; i < initial_tile_counts[type]; ++i) tiles.push_back(type);\n    shuffle(tiles.begin(), tiles.end(), rng);\n    int tile_idx = 0;\n    for(int i=0; i<N*N; ++i) current_grid[i] = (i == N*N-1) ? 0 : tiles[tile_idx++];\n\n    long long current_conn_score=0, current_dist_score=0;\n    evaluate_target(current_grid, current_conn_score, current_dist_score);\n    long long best_conn_score = -1e18;\n    double start_temp = 5000, end_temp = 0.1;\n    \n    while(true) {\n        auto now = high_resolution_clock::now();\n        duration<double> elapsed = now - sa_start_time;\n        if(elapsed.count() > sa_time_allowed) break;\n        double time_progress = elapsed.count() / sa_time_allowed;\n        double temp = start_temp * pow(end_temp / start_temp, time_progress);\n        \n        for (int k=0; k<200; ++k) {\n            int p1 = rng() % (N * N), p2 = rng() % (N * N);\n            if (p1 == p2 || current_grid[p1] == 0 || current_grid[p2] == 0) continue;\n            swap(current_grid[p1], current_grid[p2]);\n            long long new_conn_score=0, new_dist_score=0;\n            evaluate_target(current_grid, new_conn_score, new_dist_score);\n            long long current_score = current_conn_score - current_dist_score * (N > 8 ? 3 : 2);\n            long long new_score = new_conn_score - new_dist_score * (N > 8 ? 3 : 2);\n\n            if (new_score > current_score || (temp > 1e-9 && uniform_real_distribution<>(0.0, 1.0)(rng) < exp((new_score - current_score) / temp))) {\n                current_conn_score = new_conn_score; current_dist_score = new_dist_score;\n                if (current_conn_score > best_conn_score || (current_conn_score == best_conn_score && current_dist_score < best_dist_score)) {\n                    best_conn_score = current_conn_score; best_dist_score = current_dist_score; best_target_grid = current_grid;\n                }\n            } else { swap(current_grid[p1], current_grid[p2]); }\n        }\n    }\n    \n    if (best_conn_score < 100000000) { cout << \"\" << endl; return 0; }\n    cout << solve_puzzle_ida() << endl;\n\n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <map>\n#include <unordered_map>\n\n// --- Utilities ---\nstruct XorShift {\n    unsigned int x, y, z, w;\n\n    XorShift() {\n        std::random_device rd;\n        x = rd();\n        y = rd();\n        z = rd();\n        w = rd();\n    }\n\n    unsigned int next() {\n        unsigned int t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));\n    }\n\n    double next_double() {\n        return next() / 4294967295.0;\n    }\n\n    int next_int(int max_val) { // [0, max_val-1]\n        return next() % max_val;\n    }\n};\n\nXorShift rnd;\nauto start_time = std::chrono::high_resolution_clock::now();\ndouble TIME_LIMIT = 2.95;\n\ndouble get_time() {\n    auto now = std::chrono::high_resolution_clock::now();\n    return std::chrono::duration_cast<std::chrono::duration<double>>(now - start_time).count();\n}\n\n// --- Data Structures ---\nconst long long INF_COORD = 1000000000;\nconst double PI = acos(-1.0L);\n\nstruct Point {\n    long long x, y;\n};\n\nstruct Line {\n    long double a, b, c; // ax+by+c=0\n};\n\nstruct LinePolar {\n    double theta, rho; // rho = x*cos(theta) + y*sin(theta)\n};\n\nstruct VectorHasher {\n    std::size_t operator()(const std::vector<int>& v) const {\n        std::size_t seed = v.size();\n        for (int i : v) {\n            seed ^= (std::size_t)i + 0x9e3779b9 + (seed << 6) + (seed >> 2);\n        }\n        return seed;\n    }\n};\n\n// --- Problem Data ---\nint N, K;\nstd::vector<int> target_a;\nstd::vector<Point> strawberries;\nstd::vector<std::vector<int>> clusters;\n\n// --- Geometry ---\nLine points_to_line(Point p1, Point p2) {\n    long double a = (long double)p1.y - p2.y;\n    long double b = (long double)p2.x - p1.x;\n    long double c = -a * p1.x - b * p1.y;\n    return {a, b, c};\n}\n\nLine perturb_line(Line l, double amount) {\n    l.c += amount;\n    return l;\n}\n\nint get_side(const Line& l, const Point& p) {\n    long double val = l.a * p.x + l.b * p.y + l.c;\n    if (std::abs(val) < 1e-9) return 0;\n    return val > 0 ? 1 : -1;\n}\n\nLine to_cartesian(LinePolar lp) {\n    return {std::cos((long double)lp.theta), std::sin((long double)lp.theta), (long double)-lp.rho};\n}\n\nLinePolar to_polar(Line l) {\n    if (std::abs(l.a) < 1e-12 && std::abs(l.b) < 1e-12) return {0,0};\n    long double norm = std::sqrt(l.a * l.a + l.b * l.b);\n    long double a_ = l.a / norm;\n    long double b_ = l.b / norm;\n    long double c_ = l.c / norm;\n    \n    double rho = -c_;\n    double theta = std::atan2((double)b_, (double)a_);\n\n    if (theta < 0) theta += 2 * PI;\n    theta = fmod(theta, 2*PI);\n    if (theta >= PI) {\n        theta -= PI;\n        rho = -rho;\n    }\n    return {(double)theta, (double)rho};\n}\n\n// --- Candidate Generation ---\nPoint get_centroid(const std::vector<int>& strawberry_indices) {\n    if (strawberry_indices.empty()) return {0, 0};\n    long long sum_x = 0, sum_y = 0;\n    for (int idx : strawberry_indices) {\n        sum_x += strawberries[idx].x;\n        sum_y += strawberries[idx].y;\n    }\n    return {sum_x / (long long)strawberry_indices.size(), sum_y / (long long)strawberry_indices.size()};\n}\n\nLine gen_candidate_p2p() {\n    int c1_idx = rnd.next_int(clusters.size());\n    int c2_idx = rnd.next_int(clusters.size());\n    if (clusters.size() > 1 && c1_idx == c2_idx) {\n        c2_idx = (c1_idx + 1) % clusters.size();\n    }\n    \n    if (clusters[c1_idx].empty() || clusters[c2_idx].empty()) {\n        Point p1 = {(long long)rnd.next_int(20001) - 10000, (long long)rnd.next_int(20001) - 10000};\n        Point p2 = {(long long)rnd.next_int(20001) - 10000, (long long)rnd.next_int(20001) - 10000};\n        if (p1.x == p2.x && p1.y == p2.y) p2.x++;\n        return points_to_line(p1, p2);\n    }\n    \n    int s1_idx = clusters[c1_idx][rnd.next_int(clusters[c1_idx].size())];\n    int s2_idx = clusters[c2_idx][rnd.next_int(clusters[c2_idx].size())];\n    Line l = points_to_line(strawberries[s1_idx], strawberries[s2_idx]);\n    return perturb_line(l, (rnd.next_double() * 2 - 1) * 0.1);\n}\n\nLine gen_candidate_centroid() {\n    int c1_idx = rnd.next_int(clusters.size());\n    int c2_idx = rnd.next_int(clusters.size());\n    if (clusters.size() > 1 && c1_idx == c2_idx) {\n        c2_idx = (c1_idx + 1) % clusters.size();\n    }\n\n    Point centroid1 = get_centroid(clusters[c1_idx]);\n    Point centroid2 = get_centroid(clusters[c2_idx]);\n    \n    if (centroid1.x == centroid2.x && centroid1.y == centroid2.y) {\n        return gen_candidate_p2p();\n    }\n\n    Point mid_point = {(centroid1.x + centroid2.x) / 2, (centroid1.y + centroid2.y) / 2};\n    Point p_on_perp = {mid_point.x - (centroid2.y - centroid1.y), mid_point.y + (centroid2.x - centroid1.x)};\n\n    Line l = points_to_line(mid_point, p_on_perp);\n    double angle = (rnd.next_double() * 2 - 1) * PI / 12.0;\n    long double cosa = cos(angle), sina = sin(angle);\n    long double new_a = l.a * cosa - l.b * sina;\n    long double new_b = l.a * sina + l.b * cosa;\n    long double new_c = -new_a * mid_point.x - new_b * mid_point.y;\n    return {new_a, new_b, new_c};\n}\n\nLine generate_candidate_line() {\n    if (clusters.size() < 2) {\n        Point p1 = {(long long)rnd.next_int(20001) - 10000, (long long)rnd.next_int(20001) - 10000};\n        Point p2 = {(long long)rnd.next_int(20001) - 10000, (long long)rnd.next_int(20001) - 10000};\n        if (p1.x == p2.x && p1.y == p2.y) p2.x++;\n        return points_to_line(p1, p2);\n    }\n    if (rnd.next_double() < 0.5) {\n        return gen_candidate_p2p();\n    } else {\n        return gen_candidate_centroid();\n    }\n}\n\n// --- Clustering ---\nvoid perform_clustering() {\n    std::vector<int> target_sizes;\n    for (int d = 1; d <= 10; ++d) {\n        for (int i = 0; i < target_a[d]; ++i) {\n            target_sizes.push_back(d);\n        }\n    }\n    std::shuffle(target_sizes.begin(), target_sizes.end(), std::mt19937(rnd.next()));\n\n    std::vector<bool> assigned(N, false);\n    int assigned_count = 0;\n\n    for (int d : target_sizes) {\n        if (assigned_count + d > N) continue;\n\n        int seed_idx = -1;\n        int start_node = rnd.next_int(N);\n        for (int i = 0; i < N; ++i) {\n            int current_node = (start_node + i) % N;\n            if (!assigned[current_node]) {\n                seed_idx = current_node;\n                break;\n            }\n        }\n        if (seed_idx == -1) break;\n\n        std::vector<std::pair<long long, int>> dists;\n        for (int i = 0; i < N; ++i) {\n            if (!assigned[i]) {\n                long long dx = strawberries[seed_idx].x - strawberries[i].x;\n                long long dy = strawberries[seed_idx].y - strawberries[i].y;\n                dists.push_back({dx * dx + dy * dy, i});\n            }\n        }\n        \n        if (dists.size() > (size_t)d) {\n            std::nth_element(dists.begin(), dists.begin() + d, dists.end());\n        }\n\n        std::vector<int> new_cluster;\n        for (int i = 0; i < std::min((int)dists.size(), d); ++i) {\n            int strawberry_idx = dists[i].second;\n            new_cluster.push_back(strawberry_idx);\n            assigned[strawberry_idx] = true;\n        }\n        clusters.push_back(new_cluster);\n        assigned_count += d;\n    }\n}\n\n\n// --- Score Calculation ---\nint calculate_score_val(const std::vector<Line>& lines) {\n    if (lines.empty()) return 0;\n    \n    std::unordered_map<std::vector<int>, int, VectorHasher> piece_counts;\n    for (int i = 0; i < N; ++i) {\n        std::vector<int> signature;\n        signature.reserve(lines.size());\n        bool on_line = false;\n        for (const auto& line : lines) {\n            int side = get_side(line, strawberries[i]);\n            if (side == 0) {\n                on_line = true;\n                break;\n            }\n            signature.push_back(side);\n        }\n        if (!on_line) {\n            piece_counts[signature]++;\n        }\n    }\n\n    std::vector<int> b(11, 0);\n    for (const auto& pair : piece_counts) {\n        if (pair.second >= 1 && pair.second <= 10) {\n            b[pair.second]++;\n        }\n    }\n\n    int score = 0;\n    for (int d = 1; d <= 10; ++d) {\n        score += std::min(target_a[d], b[d]);\n    }\n    return score;\n}\n\nstd::unordered_map<std::vector<int>, std::vector<int>, VectorHasher> current_partition;\nstd::vector<int> current_b_dist;\n\nint get_score_from_b(const std::vector<int>& b) {\n    int score = 0;\n    for (int d = 1; d <= 10; ++d) {\n        score += std::min(target_a[d], b[d]);\n    }\n    return score;\n}\n\nint calculate_score_with_new_line(const Line& new_line) {\n    std::vector<int> next_b_dist = current_b_dist;\n    for (auto const& [sig, strawberry_indices] : current_partition) {\n        int old_count = strawberry_indices.size();\n        if (old_count >= 1 && old_count <= 10) {\n            next_b_dist[old_count]--;\n        }\n        \n        int count1 = 0, count2 = 0;\n        for (int idx : strawberry_indices) {\n            int side = get_side(new_line, strawberries[idx]);\n            if (side == 1) count1++;\n            else if (side == -1) count2++;\n        }\n\n        if (count1 >= 1 && count1 <= 10) next_b_dist[count1]++;\n        if (count2 >= 1 && count2 <= 10) next_b_dist[count2]++;\n    }\n    return get_score_from_b(next_b_dist);\n}\n\nvoid add_line_to_state(const Line& new_line) {\n    auto old_partition = current_partition;\n    current_partition.clear();\n    std::vector<int> next_b_dist(11, 0);\n\n    for (auto const& [sig, strawberry_indices] : old_partition) {\n        std::vector<int> group1, group2;\n        for (int idx : strawberry_indices) {\n            int side = get_side(new_line, strawberries[idx]);\n            if (side == 1) group1.push_back(idx);\n            else if (side == -1) group2.push_back(idx);\n        }\n        if (!group1.empty()) {\n            std::vector<int> new_sig = sig; new_sig.push_back(1);\n            current_partition[new_sig] = group1;\n            int new_count = group1.size();\n            if (new_count >= 1 && new_count <= 10) next_b_dist[new_count]++;\n        }\n        if (!group2.empty()) {\n            std::vector<int> new_sig = sig; new_sig.push_back(-1);\n            current_partition[new_sig] = group2;\n            int new_count = group2.size();\n            if (new_count >= 1 && new_count <= 10) next_b_dist[new_count]++;\n        }\n    }\n    current_b_dist = next_b_dist;\n}\n\n// --- Main ---\nvoid output_solution(const std::vector<Line>& lines) {\n    std::cout << lines.size() << std::endl;\n    for (const auto& l : lines) {\n        long long p1x, p1y, p2x, p2y;\n        if (std::abs(l.b) > 1e-9 && (std::abs(l.a / l.b) < 1)) {\n            p1x = -INF_COORD; p1y = std::round(- (l.c + l.a * p1x) / l.b);\n            p2x = INF_COORD; p2y = std::round(- (l.c + l.a * p2x) / l.b);\n        } else if (std::abs(l.a) > 1e-9) {\n            p1y = -INF_COORD; p1x = std::round(- (l.c + l.b * p1y) / l.a);\n            p2y = INF_COORD; p2x = std::round(- (l.c + l.b * p2y) / l.a);\n        } else { // Should not happen with valid lines\n            p1x = 0; p1y = 0; p2x = 1; p2y = 1;\n        }\n        std::cout << p1x << \" \" << p1y << \" \" << p2x << \" \" << p2y << std::endl;\n    }\n}\n\nvoid solve() {\n    std::cin >> N >> K;\n    target_a.resize(11);\n    for (int d = 1; d <= 10; ++d) std::cin >> target_a[d];\n    strawberries.resize(N);\n    for (int i = 0; i < N; ++i) std::cin >> strawberries[i].x >> strawberries[i].y;\n    \n    perform_clustering();\n    \n    // Fast Greedy Construction\n    std::vector<Line> current_lines;\n    current_b_dist.assign(11, 0);\n    std::vector<int> initial_indices(N);\n    std::iota(initial_indices.begin(), initial_indices.end(), 0);\n    current_partition[{}] = initial_indices;\n    if (N >= 1 && N <= 10) current_b_dist[N] = 1;\n    \n    double greedy_time_limit = 1.6;\n    const int T_SEARCH = 40;\n    for (int k = 0; k < K; ++k) {\n        if (get_time() > greedy_time_limit) break;\n        Line best_line = {};\n        int best_score = -1;\n        for (int i = 0; i < T_SEARCH; ++i) {\n            Line candidate_line = generate_candidate_line();\n            int score = calculate_score_with_new_line(candidate_line);\n            if (score > best_score) {\n                best_score = score;\n                best_line = candidate_line;\n            }\n        }\n        if (best_score != -1) {\n            current_lines.push_back(best_line);\n            add_line_to_state(best_line);\n        } else break;\n    }\n    \n    while (current_lines.size() < (size_t)K) {\n        current_lines.push_back(generate_candidate_line());\n    }\n\n    // Simulated Annealing\n    std::vector<LinePolar> polar_lines;\n    polar_lines.reserve(current_lines.size());\n    for(const auto& l : current_lines) polar_lines.push_back(to_polar(l));\n    \n    int current_score = calculate_score_val(current_lines);\n    std::vector<Line> best_lines = current_lines;\n    int best_score = current_score;\n\n    double T_start = 10.0, T_end = 0.01;\n    double time_start_sa = get_time(), time_end_sa = TIME_LIMIT;\n    const double P_REPLACE = 0.1;\n\n    while(true) {\n        double current_time = get_time();\n        if (current_time >= time_end_sa) break;\n\n        double progress = (current_time - time_start_sa) / (time_end_sa - time_start_sa + 1e-9);\n        double T = T_start * std::pow(T_end / T_start, progress);\n\n        if (polar_lines.empty()) break;\n        int line_idx = rnd.next_int(polar_lines.size());\n        \n        std::vector<Line> new_lines = current_lines;\n        \n        if (rnd.next_double() < P_REPLACE) {\n            new_lines[line_idx] = generate_candidate_line();\n        } else {\n            LinePolar new_polar = polar_lines[line_idx];\n            double move_range = (1.0 - progress) * 0.5;\n            new_polar.theta += (rnd.next_double() * 2 - 1) * PI * move_range;\n            new_polar.rho += (rnd.next_double() * 2 - 1) * 10000 * move_range;\n\n            if (new_polar.theta < 0) new_polar.theta += 2*PI;\n            new_polar.theta = fmod(new_polar.theta, 2*PI);\n            if (new_polar.theta >= PI) {\n                new_polar.theta -= PI; new_polar.rho *= -1;\n            }\n            new_lines[line_idx] = to_cartesian(new_polar);\n        }\n        \n        int new_score = calculate_score_val(new_lines);\n        double delta = new_score - current_score;\n\n        if (delta > 0 || std::exp(delta / T) > rnd.next_double()) {\n            current_score = new_score;\n            current_lines = new_lines;\n            polar_lines[line_idx] = to_polar(current_lines[line_idx]);\n            if (new_score > best_score) {\n                best_score = new_score;\n                best_lines = new_lines;\n            }\n        }\n    }\n    output_solution(best_lines);\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <tuple>\n#include <chrono>\n#include <map>\n#include <queue>\n#include <set>\n\nusing namespace std;\n\n// Timer\nauto start_time = chrono::steady_clock::now();\ndouble time_limit = 4.9;\n\nbool is_time_over() {\n    auto now = chrono::steady_clock::now();\n    double elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count() / 1000.0;\n    return elapsed > time_limit;\n}\n\nint N;\nlong long M_initial;\nlong long C;\n\nstruct Point {\n    int x, y;\n\n    bool operator==(const Point& other) const {\n        return x == other.x && y == other.y;\n    }\n    bool operator<(const Point& other) const {\n        if (x != other.x) return x < other.x;\n        return y < other.y;\n    }\n    Point operator+(const Point& other) const {\n        return {x + other.x, y + other.y};\n    }\n    Point operator-(const Point& other) const {\n        return {x - other.x, y - other.y};\n    }\n};\n\nlong long dot_product(const Point& a, const Point& b) {\n    return (long long)a.x * b.x + (long long)a.y * b.y;\n}\n\nlong long get_weight(const Point& p) {\n    long long dx = p.x - C;\n    long long dy = p.y - C;\n    return dx * dx + dy * dy + 1;\n}\n\nstruct Candidate {\n    long long weight;\n    Point p_new, p_adj1, p_corner, p_adj2;\n\n    bool operator>(const Candidate& other) const {\n        return weight < other.weight;\n    }\n};\n\nbool has_dot[62][62];\nvector<Point> dots;\nvector<tuple<Point, Point, Point, Point>> solution_moves;\npriority_queue<Candidate, vector<Candidate>, greater<Candidate>> pq;\n\nmap<int, set<pair<int, int>>> H_segs, V_segs, D1_segs, D2_segs;\n\nbool is_in_bounds(const Point& p) {\n    return p.x >= 0 && p.x < N && p.y >= 0 && p.y < N;\n}\n\nbool check_perimeter_clean(const Point& p_new, const Point& p_adj1, const Point& p_corner, const Point& p_adj2) {\n    auto check_segment = [&](const Point& a, const Point& b) {\n        int dx = b.x - a.x;\n        int dy = b.y - a.y;\n        int common_divisor = std::gcd(abs(dx), abs(dy));\n        if (common_divisor <= 1) return true;\n        int step_x = dx / common_divisor;\n        int step_y = dy / common_divisor;\n        for (int i = 1; i < common_divisor; ++i) {\n            Point p = {a.x + i * step_x, a.y + i * step_y};\n            if (has_dot[p.x][p.y]) return false;\n        }\n        return true;\n    };\n    \n    if (!check_segment(p_corner, p_adj1)) return false;\n    if (!check_segment(p_adj1, p_new)) return false;\n    if (!check_segment(p_new, p_adj2)) return false;\n    if (!check_segment(p_adj2, p_corner)) return false;\n    return true;\n}\n\nbool check_segment_overlap(map<int, set<pair<int, int>>>& seg_map, int line_idx, int c1, int c2) {\n    if (c1 == c2) return false;\n    int min_c = min(c1, c2);\n    int max_c = max(c1, c2);\n\n    if (seg_map.find(line_idx) == seg_map.end()) return false;\n\n    const auto& intervals = seg_map.at(line_idx);\n    auto it = intervals.lower_bound({min_c, 0});\n\n    if (it != intervals.begin()) {\n        auto prev_it = prev(it);\n        if (max(min_c, prev_it->first) < min(max_c, prev_it->second)) return true;\n    }\n    if (it != intervals.end()) {\n        if (max(min_c, it->first) < min(max_c, it->second)) return true;\n    }\n    return false;\n}\n\nvoid add_segment(map<int, set<pair<int, int>>>& seg_map, int line_idx, int c1, int c2) {\n    if (c1 == c2) return;\n    int min_c = min(c1, c2);\n    int max_c = max(c1, c2);\n    seg_map[line_idx].insert({min_c, max_c});\n}\n\nvoid find_and_push_candidates(const Point& p_adj1, const Point& p_corner, const Point& p_adj2) {\n    Point v1 = p_adj1 - p_corner;\n    Point v2 = p_adj2 - p_corner;\n    \n    if ((v1.x == 0 && v1.y == 0) || (v2.x == 0 && v2.y == 0)) return;\n\n    bool is_axis_aligned = (v1.x == 0 || v1.y == 0);\n    bool is_45_tilted = (abs(v1.x) == abs(v1.y));\n    if (!is_axis_aligned && !is_45_tilted) {\n        return;\n    }\n\n    Point p_new = p_adj1 + p_adj2 - p_corner;\n    if (is_in_bounds(p_new) && !has_dot[p_new.x][p_new.y]) {\n        if (check_perimeter_clean(p_new, p_adj1, p_corner, p_adj2)) {\n            pq.push({get_weight(p_new), p_new, p_adj1, p_corner, p_adj2});\n        }\n    }\n}\n\nvoid find_new_candidates(const Point& p_added) {\n    for (size_t i = 0; i < dots.size() - 1; ++i) {\n        for (size_t j = i + 1; j < dots.size() - 1; ++j) {\n            const Point& p_i = dots[i];\n            const Point& p_j = dots[j];\n            \n            if (dot_product(p_i - p_added, p_j - p_added) == 0) find_and_push_candidates(p_i, p_added, p_j);\n            if (dot_product(p_added - p_i, p_j - p_i) == 0) find_and_push_candidates(p_added, p_i, p_j);\n            if (dot_product(p_added - p_j, p_i - p_j) == 0) find_and_push_candidates(p_added, p_j, p_i);\n        }\n    }\n}\n\nvoid find_initial_candidates() {\n    for (size_t i = 0; i < dots.size(); ++i) {\n        for (size_t j = i + 1; j < dots.size(); ++j) {\n            for (size_t k = j + 1; k < dots.size(); ++k) {\n                Point p_i = dots[i], p_j = dots[j], p_k = dots[k];\n                if (dot_product(p_j - p_i, p_k - p_i) == 0) find_and_push_candidates(p_j, p_i, p_k);\n                if (dot_product(p_i - p_j, p_k - p_j) == 0) find_and_push_candidates(p_i, p_j, p_k);\n                if (dot_product(p_i - p_k, p_j - p_k) == 0) find_and_push_candidates(p_i, p_k, p_j);\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N >> M_initial;\n    C = (N - 1) / 2;\n\n    for (int i = 0; i < M_initial; ++i) {\n        int x, y;\n        cin >> x >> y;\n        dots.push_back({x, y});\n        has_dot[x][y] = true;\n    }\n\n    find_initial_candidates();\n\n    while (!pq.empty() && !is_time_over()) {\n        Candidate c = pq.top();\n        pq.pop();\n\n        if (has_dot[c.p_new.x][c.p_new.y]) continue;\n\n        Point p_new = c.p_new, p_corner = c.p_corner, p_adj1 = c.p_adj1, p_adj2 = c.p_adj2;\n        if (!check_perimeter_clean(p_new, p_adj1, p_corner, p_adj2)) continue;\n\n        auto check_s = [&](const Point& u, const Point& v) {\n            if (u.y == v.y) return !check_segment_overlap(H_segs, u.y, u.x, v.x);\n            if (u.x == v.x) return !check_segment_overlap(V_segs, u.x, u.y, v.y);\n            if (u.x + u.y == v.x + v.y) return !check_segment_overlap(D1_segs, u.x + u.y, u.x, v.x);\n            return !check_segment_overlap(D2_segs, u.x - u.y, u.x, v.x);\n        };\n\n        if (!check_s(p_corner, p_adj1)) continue;\n        if (!check_s(p_adj1, p_new)) continue;\n        if (!check_s(p_new, p_adj2)) continue;\n        if (!check_s(p_adj2, p_corner)) continue;\n        \n        auto add_s = [&](const Point& u, const Point& v){\n            if (u.y == v.y) add_segment(H_segs, u.y, u.x, v.x);\n            else if (u.x == v.x) add_segment(V_segs, u.x, u.y, v.y);\n            else if (u.x + u.y == v.x + v.y) add_segment(D1_segs, u.x + u.y, u.x, v.x);\n            else add_segment(D2_segs, u.x - u.y, u.x, v.x);\n        };\n\n        add_s(p_corner, p_adj1);\n        add_s(p_adj1, p_new);\n        add_s(p_new, p_adj2);\n        add_s(p_adj2, p_corner);\n\n        solution_moves.emplace_back(p_new, p_adj1, p_corner, p_adj2);\n        dots.push_back(p_new);\n        has_dot[p_new.x][p_new.y] = true;\n        \n        find_new_candidates(p_new);\n    }\n\n    cout << solution_moves.size() << endl;\n    for (const auto& move : solution_moves) {\n        cout << get<0>(move).x << \" \" << get<0>(move).y << \" \"\n             << get<1>(move).x << \" \" << get<1>(move).y << \" \"\n             << get<2>(move).x << \" \" << get<2>(move).y << \" \"\n             << get<3>(move).x << \" \" << get<3>(move).y << endl;\n    }\n\n    return 0;\n}","ahc015":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <algorithm>\n#include <map>\n#include <cmath>\n\nconst int GRID_SIZE = 10;\n\n// Represents the state of the 10x10 grid.\nstruct Grid {\n    std::vector<std::vector<int>> board;\n\n    Grid() : board(GRID_SIZE, std::vector<int>(GRID_SIZE, 0)) {}\n\n    // Places a candy of a given flavor at the p-th empty cell (1-indexed).\n    void place(int p, int flavor) {\n        int empty_count = 0;\n        for (int i = 0; i < GRID_SIZE; ++i) {\n            for (int j = 0; j < GRID_SIZE; ++j) {\n                if (board[i][j] == 0) {\n                    empty_count++;\n                    if (empty_count == p) {\n                        board[i][j] = flavor;\n                        return;\n                    }\n                }\n            }\n        }\n    }\n};\n\n// Simulates a tilt operation on the grid and returns the new grid state.\nGrid simulate_tilt(const Grid& current_grid, char dir) {\n    Grid next_grid; // Initializes to an empty board.\n    \n    if (dir == 'F') { // Move Up\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            int current_row = 0;\n            for (int i = 0; i < GRID_SIZE; ++i) {\n                if (current_grid.board[i][j] != 0) {\n                    next_grid.board[current_row++][j] = current_grid.board[i][j];\n                }\n            }\n        }\n    } else if (dir == 'B') { // Move Down\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            int current_row = GRID_SIZE - 1;\n            for (int i = GRID_SIZE - 1; i >= 0; --i) {\n                if (current_grid.board[i][j] != 0) {\n                    next_grid.board[current_row--][j] = current_grid.board[i][j];\n                }\n            }\n        }\n    } else if (dir == 'L') { // Move Left\n        for (int i = 0; i < GRID_SIZE; ++i) {\n            int current_col = 0;\n            for (int j = 0; j < GRID_SIZE; ++j) {\n                if (current_grid.board[i][j] != 0) {\n                    next_grid.board[i][current_col++] = current_grid.board[i][j];\n                }\n            }\n        }\n    } else if (dir == 'R') { // Move Right\n        for (int i = 0; i < GRID_SIZE; ++i) {\n            int current_col = GRID_SIZE - 1;\n            for (int j = GRID_SIZE - 1; j >= 0; --j) {\n                if (current_grid.board[i][j] != 0) {\n                    next_grid.board[i][current_col--] = current_grid.board[i][j];\n                }\n            }\n        }\n    }\n    return next_grid;\n}\n\n// Calculates the sum of squares of connected component sizes using BFS.\nlong long calculate_conn_score(const Grid& grid) {\n    long long total_score = 0;\n    std::vector<std::vector<bool>> visited(GRID_SIZE, std::vector<bool>(GRID_SIZE, false));\n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            if (grid.board[i][j] != 0 && !visited[i][j]) {\n                int flavor = grid.board[i][j];\n                long long component_size = 0;\n                std::vector<std::pair<int, int>> q;\n                q.push_back({i, j});\n                visited[i][j] = true;\n                \n                int head = 0;\n                while(head < q.size()){\n                    auto [r, c] = q[head++];\n                    component_size++;\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 < GRID_SIZE && nc >= 0 && nc < GRID_SIZE &&\n                            !visited[nr][nc] && grid.board[nr][nc] == flavor) {\n                            visited[nr][nc] = true;\n                            q.push_back({nr, nc});\n                        }\n                    }\n                }\n                total_score += component_size * component_size;\n            }\n        }\n    }\n    return total_score;\n}\n\n// Global map from flavor to its target side.\nstd::map<int, int> target_side_map; // 0: Top, 1: Left, 3: Bottom\n\n// Calculates the proximity score (negative sum of distances to target sides).\nlong long calculate_prox_score(const Grid& grid) {\n    long long total_dist = 0;\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            if (grid.board[i][j] != 0) {\n                int flavor = grid.board[i][j];\n                int target_side = target_side_map.at(flavor);\n                if (target_side == 0) { // Top\n                    total_dist += i;\n                } else if (target_side == 1) { // Left\n                    total_dist += j;\n                } else { // Bottom (target_side == 3)\n                    total_dist += (GRID_SIZE - 1 - i);\n                }\n            }\n        }\n    }\n    return -total_dist;\n}\n\n// Calculates a penalty for adjacent (orthogonal and diagonal) different-flavor candies.\nlong long calculate_adj_penalty_score(const Grid& grid) {\n    long long penalty = 0;\n    for (int r = 0; r < GRID_SIZE; ++r) {\n        for (int c = 0; c < GRID_SIZE; ++c) {\n            if (grid.board[r][c] == 0) continue;\n            int current_flavor = grid.board[r][c];\n            \n            // Check neighbors to the right, down, and bottom-diagonals to avoid double counting.\n            if (c + 1 < GRID_SIZE && grid.board[r][c+1] != 0 && grid.board[r][c+1] != current_flavor) {\n                penalty--;\n            }\n            if (r + 1 < GRID_SIZE) {\n                if (grid.board[r+1][c] != 0 && grid.board[r+1][c] != current_flavor) {\n                    penalty--;\n                }\n                if (c + 1 < GRID_SIZE && grid.board[r+1][c+1] != 0 && grid.board[r+1][c+1] != current_flavor) {\n                    penalty--;\n                }\n                if (c - 1 >= 0 && grid.board[r+1][c-1] != 0 && grid.board[r+1][c-1] != current_flavor) {\n                    penalty--;\n                }\n            }\n        }\n    }\n    return penalty;\n}\n\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    std::vector<int> f(100);\n    std::map<int, int> flavor_counts;\n    for (int i = 0; i < 100; ++i) {\n        std::cin >> f[i];\n        flavor_counts[f[i]]++;\n    }\n    \n    std::vector<std::pair<int, int>> sorted_flavors;\n    for (int i = 1; i <= 3; ++i) {\n        sorted_flavors.push_back({flavor_counts.count(i) ? flavor_counts[i] : 0, i});\n    }\n    std::sort(sorted_flavors.rbegin(), sorted_flavors.rend());\n\n    // New target assignment: Top, Left, Bottom\n    // 0: Top, 1: Left, 3: Bottom\n    std::vector<int> target_sides = {0, 1, 3}; \n    for (size_t i = 0; i < 3; ++i) {\n        target_side_map[sorted_flavors[i].second] = target_sides[i];\n    }\n\n    Grid current_grid;\n\n    for (int t = 1; t <= 100; ++t) {\n        int p;\n        std::cin >> p;\n        current_grid.place(p, f[t - 1]);\n\n        if (t == 100) {\n            break;\n        }\n\n        char best_dir = 'F';\n        double best_score = -1e18;\n\n        const char dirs[] = {'F', 'B', 'L', 'R'};\n        for (char dir : dirs) {\n            Grid next_grid = simulate_tilt(current_grid, dir);\n            \n            long long conn_score = calculate_conn_score(next_grid);\n            long long prox_score = calculate_prox_score(next_grid);\n            long long adj_penalty_score = calculate_adj_penalty_score(next_grid);\n\n            double t_double = static_cast<double>(t);\n            double w_conn = t_double * t_double;\n            double w_prox = 2.0 * (101.0 - t_double) * (101.0 - t_double);\n            double w_adj = 10.0 * t_double * t_double;\n            \n            double current_total_score = w_conn * conn_score + w_prox * prox_score + w_adj * adj_penalty_score;\n            \n            if (current_total_score > best_score) {\n                best_score = current_total_score;\n                best_dir = dir;\n            }\n        }\n        \n        std::cout << best_dir << std::endl;\n        current_grid = simulate_tilt(current_grid, best_dir);\n    }\n\n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <set>\n\n// Globals\nint M;\ndouble EPS;\nint N;\nstd::vector<int> clique_sizes;\nstd::vector<std::vector<bool>> H_adj;\n\n// --- Helper Functions ---\n\n// Creates the 0/1 string representation of a graph with a clique.\nstd::string clique_graph_to_string(int n, int clique_size) {\n    std::string s(n * (n - 1) / 2, '0');\n    int k = 0;\n    for (int i = 0; i < n; ++i) {\n        for (int j = i + 1; j < n; ++j) {\n            if (i < clique_size && j < clique_size) {\n                s[k] = '1';\n            }\n            k++;\n        }\n    }\n    return s;\n}\n\n// Calculates binary entropy for channel capacity calculation.\ndouble binary_entropy(double p) {\n    if (p <= 0.0 || p >= 1.0) return 0.0;\n    return -p * std::log2(p) - (1.0 - p) * std::log2(1.0 - p);\n}\n\n// A simpler, more robust heuristic for finding the dense core: sort vertices by degree.\n// This replaces the more complex and potentially buggy degeneracy ordering implementation.\nstd::vector<int> get_degree_order(int n, const std::vector<int>& initial_degrees) {\n    std::vector<int> order(n);\n    std::iota(order.begin(), order.end(), 0);\n    std::sort(order.begin(), order.end(), [&](int a, int b) {\n        return initial_degrees[a] > initial_degrees[b];\n    });\n    return order;\n}\n\n// --- Main Logic ---\n\n// Determines the number of vertices, N, based on M and epsilon.\nvoid determine_N() {\n    double alpha = 2.0 + 10.0 * EPS;\n    double capacity = std::max(0.01, 1.0 - binary_entropy(EPS));\n    double bits_needed = std::log2(M) * alpha;\n    double edges_needed = bits_needed / capacity;\n    double n_theory = (1.0 + std::sqrt(std::max(0.0, 1.0 + 8.0 * edges_needed))) / 2.0;\n    \n    N = static_cast<int>(lround(n_theory));\n    N = std::max(N, M);\n    N = std::min(100, std::max(4, N));\n}\n\n// Generates M distinct, well-spaced base graphs (cliques).\nvoid generate_base_graphs() {\n    std::set<int> st_clique_sizes;\n    if (M <= 1) {\n        st_clique_sizes.insert(0);\n    } else {\n        for (int i = 0; i < M; ++i) {\n            st_clique_sizes.insert(lround((double)i * N / (M - 1.0)));\n        }\n    }\n    \n    // A 1-clique is just an isolated vertex, indistinguishable from a 0-clique's components.\n    if (st_clique_sizes.count(1)) {\n        st_clique_sizes.erase(1);\n    }\n    \n    // Ensure we have exactly M distinct sizes.\n    for (int i = 0; i <= N && st_clique_sizes.size() < M; ++i) {\n        if (i == 1) continue;\n        st_clique_sizes.insert(i);\n    }\n    \n    clique_sizes.assign(st_clique_sizes.begin(), st_clique_sizes.end());\n    \n    std::cout << N << std::endl;\n    for (int k = 0; k < M; ++k) {\n        std::cout << clique_graph_to_string(N, clique_sizes[k]) << std::endl;\n    }\n}\n\n\nvoid solve() {\n    determine_N();\n    generate_base_graphs();\n    std::cout.flush();\n\n    H_adj.resize(N, std::vector<bool>(N));\n\n    for (int q = 0; q < 100; ++q) {\n        std::string H_str;\n        std::cin >> H_str;\n\n        int H_edges = 0;\n        int k_str_idx = 0;\n        std::vector<int> initial_degrees(N, 0);\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) {\n                H_adj[i][j] = H_adj[j][i] = (H_str[k_str_idx] == '1');\n                if (H_adj[i][j]) {\n                    H_edges++;\n                    initial_degrees[i]++;\n                    initial_degrees[j]++;\n                }\n                k_str_idx++;\n            }\n        }\n        \n        // Use the simpler degree-sort heuristic for the initial guess.\n        std::vector<int> initial_guess_order = get_degree_order(N, initial_degrees);\n\n        int best_idx = -1;\n        double min_flips = 1e18;\n\n        for (int i = 0; i < M; ++i) {\n            int C = clique_sizes[i];\n            \n            if (C <= 1) {\n                double flips = H_edges; // Flips to get an empty graph\n                if (flips < min_flips) {\n                    min_flips = flips;\n                    best_idx = i;\n                }\n                continue;\n            }\n\n            std::vector<int> S_nodes; S_nodes.reserve(C);\n            std::vector<bool> in_S(N, false);\n            for (int j = 0; j < C; ++j) {\n                S_nodes.push_back(initial_guess_order[j]);\n                in_S[initial_guess_order[j]] = true;\n            }\n\n            // Local search to refine the clique candidate set\n            const int MAX_ITERS = (EPS < 0.2) ? 5 : 10;\n            for (int iter = 0; iter < MAX_ITERS; ++iter) {\n                std::vector<int> d_S(N, 0);\n                for (int u = 0; u < N; ++u) {\n                    for (int v_node : S_nodes) {\n                        if (H_adj[u][v_node]) d_S[u]++;\n                    }\n                }\n\n                int u_to_swap = -1, min_d_in = N + 1;\n                for (int u_node : S_nodes) {\n                    if (d_S[u_node] < min_d_in) {\n                        min_d_in = d_S[u_node];\n                        u_to_swap = u_node;\n                    }\n                }\n                \n                int v_to_swap = -1, max_d_out = -1;\n                for (int v = 0; v < N; ++v) {\n                    if (!in_S[v]) {\n                        if (d_S[v] > max_d_out) {\n                            max_d_out = d_S[v];\n                            v_to_swap = v;\n                        }\n                    }\n                }\n\n                if (u_to_swap == -1 || v_to_swap == -1) break;\n                \n                int gain = max_d_out - min_d_in - (H_adj[u_to_swap][v_to_swap] ? 1 : 0);\n\n                if (gain > 0) {\n                    in_S[u_to_swap] = false;\n                    in_S[v_to_swap] = true;\n                    S_nodes.erase(std::remove(S_nodes.begin(), S_nodes.end(), u_to_swap), S_nodes.end());\n                    S_nodes.push_back(v_to_swap);\n                } else {\n                    break;\n                }\n            }\n\n            long long E_star = 0;\n            for(size_t u_idx = 0; u_idx < S_nodes.size(); ++u_idx) {\n                for(size_t v_idx = u_idx + 1; v_idx < S_nodes.size(); ++v_idx) {\n                    if(H_adj[S_nodes[u_idx]][S_nodes[v_idx]]) E_star++;\n                }\n            }\n            \n            long long E_clique = (long long)C * (C - 1) / 2;\n            double estimated_flips = (double)(E_clique - E_star) + (H_edges - E_star);\n\n            if (estimated_flips < min_flips) {\n                min_flips = estimated_flips;\n                best_idx = i;\n            }\n        }\n        \n        if (best_idx == -1) best_idx = 0; // Defensive coding, should not be needed.\n        std::cout << best_idx << std::endl;\n        std::cout.flush();\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    std::cin >> M >> EPS;\n    solve();\n    return 0;\n}","ahc017":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <iomanip>\n#include <functional>\n#include <queue>\n#include <tuple>\n\nusing namespace std;\n\n// Constants and Typedefs\nconst long long INF = 1e18;\n\n// Structs\nstruct Edge {\n    int id;\n    int u, v, w;\n};\n\nstruct Point {\n    int x, y;\n};\n\n// Utilities\nauto start_time = chrono::high_resolution_clock::now();\ndouble get_time() {\n    auto now = chrono::high_resolution_clock::now();\n    return chrono::duration_cast<chrono::duration<double>>(now - start_time).count();\n}\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// Bridge Finder for detecting 2-edge-cuts\nnamespace BridgeFinder {\n    vector<int> tin, low;\n    int timer;\n    vector<bool> visited;\n    const vector<vector<tuple<int, int, int>>>* adj_ptr;\n    vector<pair<int, int>> critical_pairs_buffer;\n    int current_ignored_edge;\n\n    void dfs(int u, int p_edge_id) {\n        visited[u] = true;\n        tin[u] = low[u] = timer++;\n        for (const auto& edge_tuple : (*adj_ptr)[u]) {\n            int v = get<0>(edge_tuple);\n            int edge_id = get<2>(edge_tuple);\n\n            if (edge_id == p_edge_id || edge_id == current_ignored_edge) continue;\n\n            if (visited[v]) {\n                low[u] = min(low[u], tin[v]);\n            } else {\n                dfs(v, edge_id);\n                low[u] = min(low[u], low[v]);\n                if (low[v] > tin[u]) {\n                    critical_pairs_buffer.emplace_back(current_ignored_edge, edge_id);\n                }\n            }\n        }\n    }\n\n    void find_bridges_in_subgraph(int ignored_edge, int N) {\n        current_ignored_edge = ignored_edge;\n        timer = 0;\n        visited.assign(N, false);\n        tin.assign(N, -1);\n        low.assign(N, -1);\n        for (int i = 0; i < N; ++i) {\n            if (!visited[i]) {\n                dfs(i, -1);\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // --- Input Reading ---\n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n\n    vector<Edge> edges(M);\n    vector<vector<tuple<int, int, int>>> adj(N);\n    for (int i = 0; i < M; ++i) {\n        edges[i].id = i;\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\n        edges[i].u--; \n        edges[i].v--;\n        adj[edges[i].u].emplace_back(edges[i].v, edges[i].w, i);\n        adj[edges[i].v].emplace_back(edges[i].u, edges[i].w, i);\n    }\n\n    vector<Point> coords(N);\n    for (int i = 0; i < N; ++i) cin >> coords[i].x >> coords[i].y;\n    \n    // --- Phase 1: Precomputation and Heuristics (Time Budget: ~2.0s) ---\n    \n    // 1a. Path Centrality\n    vector<long long> edge_path_counts(M, 0);\n    int SAMPLES = 50;\n    vector<int> sample_nodes(N);\n    iota(sample_nodes.begin(), sample_nodes.end(), 0);\n    shuffle(sample_nodes.begin(), sample_nodes.end(), rng);\n    for (int i = 0; i < min((int)sample_nodes.size(), SAMPLES); ++i) {\n        int start_node = sample_nodes[i];\n        vector<long long> dist(N, INF); vector<int> parent_edge(N, -1); dist[start_node] = 0;\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<>> pq; pq.push({0, start_node});\n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop(); if (d > dist[u]) continue;\n            for (const auto& edge_tuple : adj[u]) {\n                auto [v, w, edge_id] = edge_tuple;\n                if (dist[u] != INF && dist[u] + w < dist[v]) {\n                    dist[v] = dist[u] + w; parent_edge[v] = edge_id; pq.push({dist[v], v});\n                }\n            }\n        }\n        vector<vector<int>> tree_adj(N);\n        for(int j=0; j<N; ++j) if (parent_edge[j] != -1) {int u = (edges[parent_edge[j]].u == j) ? edges[parent_edge[j]].v : edges[parent_edge[j]].u; tree_adj[u].push_back(j);}\n        vector<int> subtree_size(N, 0); function<void(int)> dfs_size = [&](int u) {subtree_size[u] = 1; for(int v : tree_adj[u]) {dfs_size(v); subtree_size[u] += subtree_size[v];}}; dfs_size(start_node);\n        for(int j=0; j<N; ++j) if(parent_edge[j] != -1) edge_path_counts[parent_edge[j]] += (long long)subtree_size[j] * (N - subtree_size[j]);\n    }\n\n    // 1b. Edge Importance Score\n    vector<double> edge_importance(M);\n    for(int i = 0; i < M; ++i) {\n        edge_importance[i] = (double)edges[i].w * edge_path_counts[i];\n    }\n\n    // 1c. Limited Structural Analysis (Find some 2-edge-cuts)\n    vector<int> sorted_by_importance(M);\n    iota(sorted_by_importance.begin(), sorted_by_importance.end(), 0);\n    sort(sorted_by_importance.begin(), sorted_by_importance.end(), [&](int a, int b){\n        return edge_importance[a] > edge_importance[b];\n    });\n\n    BridgeFinder::adj_ptr = &adj;\n    vector<pair<int, int>> critical_pairs;\n    int C = 30; // Number of important edges to check\n    for (int i = 0; i < min(M, C); ++i) {\n        int edge_to_ignore = sorted_by_importance[i];\n        BridgeFinder::find_bridges_in_subgraph(edge_to_ignore, N);\n        for(auto& p : BridgeFinder::critical_pairs_buffer) {\n            if (p.first > p.second) swap(p.first, p.second);\n            critical_pairs.push_back(p);\n        }\n        BridgeFinder::critical_pairs_buffer.clear();\n    }\n    sort(critical_pairs.begin(), critical_pairs.end());\n    critical_pairs.erase(unique(critical_pairs.begin(), critical_pairs.end()), critical_pairs.end());\n    \n    // 1d. Interaction Matrix\n    vector<vector<float>> interactions(M, vector<float>(M));\n    vector<pair<double, double>> midpoints(M);\n    for(int i=0; i<M; ++i) midpoints[i] = {(coords[edges[i].u].x + coords[edges[i].v].x)/2.0, (coords[edges[i].u].y + coords[edges[i].v].y)/2.0};\n    const float ADJ_PENALTY = 50.0f;\n    const float CRITICAL_PENALTY = 5000.0f;\n    for(int i=0; i<M; ++i) {\n        for(int j=i+1; j<M; ++j) {\n            double dx = midpoints[i].first - midpoints[j].first;\n            double dy = midpoints[i].second - midpoints[j].second;\n            float val = 10000.0f / (dx*dx + dy*dy + 100.0f);\n            if (edges[i].u == edges[j].u || edges[i].u == edges[j].v || edges[i].v == edges[j].u || edges[i].v == edges[j].v) {\n                val += ADJ_PENALTY;\n            }\n            interactions[i][j] = interactions[j][i] = val;\n        }\n    }\n    for(const auto& p : critical_pairs) {\n        interactions[p.first][p.second] += CRITICAL_PENALTY;\n        interactions[p.second][p.first] += CRITICAL_PENALTY;\n    }\n\n    // --- Phase 2: Greedy Initial Solution ---\n    vector<vector<int>> days(D);\n    vector<int> edge_to_day(M);\n    for (int edge_idx : sorted_by_importance) {\n        int best_day = -1; float min_cost_increase = 1e18;\n        for (int d = 0; d < D; ++d) {\n            if (days[d].size() >= K) continue;\n            float cost_increase = 0;\n            for (int other_edge_idx : days[d]) cost_increase += interactions[edge_idx][other_edge_idx];\n            if (cost_increase < min_cost_increase) {\n                min_cost_increase = cost_increase; best_day = d;\n            } else if (abs(cost_increase - min_cost_increase) < 1e-6) {\n                if (best_day == -1 || days[d].size() < days[best_day].size()) best_day = d;\n            }\n        }\n        days[best_day].push_back(edge_idx); edge_to_day[edge_idx] = best_day;\n    }\n    \n    // --- Phase 3: Simulated Annealing Optimization ---\n    double start_temp = 50.0, end_temp = 0.1;\n    long long iter_count = 0;\n    double time_limit = 5.9;\n    double temp = start_temp;\n    double precompute_time = get_time();\n\n    while (true) {\n        iter_count++;\n        if ((iter_count & 255) == 0) {\n            double elapsed = get_time();\n            if (elapsed > time_limit) break;\n            double sa_progress = (elapsed - precompute_time) / (time_limit - precompute_time);\n            if (sa_progress >= 1.0) break;\n            temp = start_temp * pow(end_temp / start_temp, sa_progress);\n        }\n\n        if (uniform_int_distribution<>(0, 1)(rng) == 0) { // Move\n            int e_idx = uniform_int_distribution<>(0, M - 1)(rng);\n            int d1 = edge_to_day[e_idx]; int d2 = uniform_int_distribution<>(0, D - 1)(rng);\n            if (d1 == d2 || days[d2].size() >= K) continue;\n            \n            float cost_d1_old = 0; for(int other_e : days[d1]) if(other_e != e_idx) cost_d1_old += interactions[e_idx][other_e];\n            float cost_d2_new = 0; for(int other_e : days[d2]) cost_d2_new += interactions[e_idx][other_e];\n            double delta = cost_d2_new - cost_d1_old;\n\n            if (delta < 0 || (temp > 1e-9 && uniform_real_distribution<>(0.0, 1.0)(rng) < exp(-delta / temp))) {\n                auto& d1_edges = days[d1]; d1_edges.erase(remove(d1_edges.begin(), d1_edges.end(), e_idx), d1_edges.end());\n                days[d2].push_back(e_idx); edge_to_day[e_idx] = d2;\n            }\n        } else { // Swap\n            int e1_idx = uniform_int_distribution<>(0, M - 1)(rng);\n            int e2_idx = uniform_int_distribution<>(0, M - 1)(rng);\n            if (e1_idx == e2_idx) continue;\n            int d1 = edge_to_day[e1_idx], d2 = edge_to_day[e2_idx];\n            if (d1 == d2) continue;\n\n            float cost1_in_d1 = 0, cost2_in_d2 = 0, cost1_in_d2 = 0, cost2_in_d1 = 0;\n            for(int e : days[d1]) if (e != e1_idx) { cost1_in_d1 += interactions[e1_idx][e]; cost2_in_d1 += interactions[e2_idx][e]; }\n            for(int e : days[d2]) if (e != e2_idx) { cost2_in_d2 += interactions[e2_idx][e]; cost1_in_d2 += interactions[e1_idx][e]; }\n            double delta = (cost2_in_d1 + cost1_in_d2) - (cost1_in_d1 + cost2_in_d2);\n            \n            if (delta < 0 || (temp > 1e-9 && uniform_real_distribution<>(0.0, 1.0)(rng) < exp(-delta / temp))) {\n                auto& d1_edges = days[d1]; auto& d2_edges = days[d2];\n                *find(d1_edges.begin(), d1_edges.end(), e1_idx) = e2_idx;\n                *find(d2_edges.begin(), d2_edges.end(), e2_idx) = e1_idx;\n                edge_to_day[e1_idx] = d2; edge_to_day[e2_idx] = d1;\n            }\n        }\n    }\n\n    // --- Output ---\n    vector<int> result(M);\n    for (int i = 0; i < M; ++i) {\n        // edges[i] is the i-th edge in my internal list\n        // edges[i].id is its original ID from the input\n        // edge_to_day[i] is the day for my internal edge i\n        result[edges[i].id] = edge_to_day[i] + 1;\n    }\n    for (int i = 0; i < M; ++i) {\n        cout << result[i] << (i == M - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n\n    return 0;\n}","ahc019":"#include <iostream>\n#include <vector>\n#include <string>\n#include <tuple>\n#include <numeric>\n#include <algorithm>\n#include <set>\n#include <map>\n#include <chrono>\n\nusing namespace std;\n\nint D;\n\nstruct Point3D {\n    int x, y, z;\n    bool operator<(const Point3D& other) const {\n        if (x != other.x) return x < other.x;\n        if (y != other.y) return y < other.y;\n        return z < other.z;\n    }\n    bool operator==(const Point3D& other) const {\n        return x == other.x && y == other.y && z == other.z;\n    }\n};\n\nPoint3D operator+(const Point3D& a, const Point3D& b) {\n    return {a.x + b.x, a.y + b.y, a.z + b.z};\n}\n\nPoint3D operator-(const Point3D& a, const Point3D& b) {\n    return {a.x - b.x, a.y - b.y, a.z - b.z};\n}\n\nusing Shape = vector<Point3D>;\n\n// All 24 rotations of a cube\nconst vector<vector<int>> ROTS = {\n    {1,0,0,0,1,0,0,0,1}, {1,0,0,0,0,-1,0,1,0}, {1,0,0,0,-1,0,0,0,-1}, {1,0,0,0,0,1,0,-1,0},\n    {-1,0,0,0,-1,0,0,0,1}, {-1,0,0,0,0,1,0,1,0}, {-1,0,0,0,1,0,0,0,-1}, {-1,0,0,0,0,-1,0,-1,0},\n    {0,1,0,1,0,0,0,0,-1}, {0,1,0,0,0,1,1,0,0}, {0,1,0,-1,0,0,0,0,1}, {0,1,0,0,0,-1,-1,0,0},\n    {0,-1,0,-1,0,0,0,0,-1}, {0,-1,0,0,0,-1,1,0,0}, {0,-1,0,1,0,0,0,0,1}, {0,-1,0,0,0,1,-1,0,0},\n    {0,0,1,0,1,0,-1,0,0}, {0,0,1,1,0,0,0,1,0}, {0,0,1,0,-1,0,1,0,0}, {0,0,1,-1,0,0,0,-1,0},\n    {0,0,-1,0,-1,0,-1,0,0}, {0,0,-1,-1,0,0,0,1,0}, {0,0,-1,0,1,0,1,0,0}, {0,0,-1,1,0,0,0,-1,0}\n};\n\nPoint3D rotate(const Point3D& p, const vector<int>& R) {\n    return {\n        R[0]*p.x + R[1]*p.y + R[2]*p.z,\n        R[3]*p.x + R[4]*p.y + R[5]*p.z,\n        R[6]*p.x + R[7]*p.y + R[8]*p.z\n    };\n}\n\nShape normalize_shape(Shape s) {\n    if (s.empty()) return {};\n    Point3D min_p = s[0];\n    for (size_t i = 1; i < s.size(); ++i) {\n        min_p.x = min(min_p.x, s[i].x);\n        min_p.y = min(min_p.y, s[i].y);\n        min_p.z = min(min_p.z, s[i].z);\n    }\n    for (auto& p : s) {\n        p = p - min_p;\n    }\n    sort(s.begin(), s.end());\n    return s;\n}\n\nShape get_canonical_shape(const Shape& s) {\n    if (s.empty()) return {};\n    Shape canonical = normalize_shape(s);\n    for (const auto& R : ROTS) {\n        Shape rotated_s;\n        for (const auto& p : s) {\n            rotated_s.push_back(rotate(p, R));\n        }\n        Shape normalized_rotated = normalize_shape(rotated_s);\n        if (normalized_rotated < canonical) {\n            canonical = normalized_rotated;\n        }\n    }\n    return canonical;\n}\n\nstruct ProtoBlock {\n    Shape points;\n    int id = 0;\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\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    auto is_valid_coord = [&](int x, int y, int z) {\n        return x >= 0 && x < D && y >= 0 && y < D && z >= 0 && z < D;\n    };\n\n    vector<vector<vector<bool>>> C1(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    vector<vector<vector<bool>>> C2(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    vector<vector<vector<bool>>> C_common(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    \n    for (int x = 0; x < D; ++x) for (int y = 0; y < D; ++y) for (int z = 0; z < D; ++z) {\n        if (f1[z][x] == '1' && r1[z][y] == '1') C1[x][y][z] = true;\n        if (f2[z][x] == '1' && r2[z][y] == '1') C2[x][y][z] = true;\n        if (C1[x][y][z] && C2[x][y][z]) C_common[x][y][z] = true;\n    }\n\n    vector<ProtoBlock> common_blocks;\n    vector<vector<vector<bool>>> visited_common = C_common;\n    for (int x = 0; x < D; ++x) for (int y = 0; y < D; ++y) for (int z = 0; z < D; ++z) {\n        if (visited_common[x][y][z]) {\n            Shape current_block_points;\n            vector<Point3D> q;\n            q.push_back({x, y, z});\n            visited_common[x][y][z] = false;\n            size_t head = 0;\n            while(head < q.size()){\n                Point3D curr = q[head++];\n                current_block_points.push_back(curr);\n                int dx[] = {-1, 1, 0, 0, 0, 0};\n                int dy[] = {0, 0, -1, 1, 0, 0};\n                int dz[] = {0, 0, 0, 0, -1, 1};\n                for (int i = 0; i < 6; ++i) {\n                    Point3D next = {curr.x + dx[i], curr.y + dy[i], curr.z + dz[i]};\n                    if (is_valid_coord(next.x, next.y, next.z) && visited_common[next.x][next.y][next.z]) {\n                        visited_common[next.x][next.y][next.z] = false;\n                        q.push_back(next);\n                    }\n                }\n            }\n            common_blocks.push_back({current_block_points, 0});\n        }\n    }\n\n    vector<bool> f1_req_met(D*D, false), r1_req_met(D*D, false);\n    for (const auto& block : common_blocks) {\n        for (const auto& p : block.points) {\n            f1_req_met[p.z * D + p.x] = true;\n            r1_req_met[p.z * D + p.y] = true;\n        }\n    }\n\n    vector<ProtoBlock> filler1_blocks;\n    {\n        vector<Point3D> c1_only_cells;\n        for (int x=0; x<D; ++x) for (int y=0; y<D; ++y) for (int z=0; z<D; ++z) {\n             if (C1[x][y][z] && !C_common[x][y][z]) c1_only_cells.push_back({x,y,z});\n        }\n        vector<Point3D> filler1_cells;\n        while(true) {\n            int best_score = 0; int best_idx = -1;\n            for(size_t i=0; i<c1_only_cells.size(); ++i){\n                const auto& p = c1_only_cells[i];\n                int score = (f1[p.z][p.x]=='1' && !f1_req_met[p.z*D+p.x]) + (r1[p.z][p.y]=='1' && !r1_req_met[p.z*D+p.y]);\n                if(score > best_score) { best_score = score; best_idx = i; }\n            }\n            if (best_score == 0) break;\n            Point3D p = c1_only_cells[best_idx];\n            filler1_cells.push_back(p);\n            f1_req_met[p.z*D+p.x] = true; r1_req_met[p.z*D+p.y] = true;\n            swap(c1_only_cells[best_idx], c1_only_cells.back()); c1_only_cells.pop_back();\n        }\n        vector<vector<vector<bool>>> filler1_grid(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n        for(const auto& p : filler1_cells) filler1_grid[p.x][p.y][p.z] = true;\n        for(const auto& p_start : filler1_cells) {\n            if (filler1_grid[p_start.x][p_start.y][p_start.z]) {\n                Shape current_block_points; vector<Point3D> q; q.push_back(p_start);\n                filler1_grid[p_start.x][p_start.y][p_start.z] = false;\n                size_t head = 0;\n                while(head < q.size()){\n                    Point3D curr = q[head++]; current_block_points.push_back(curr);\n                    int dx[]={-1,1,0,0,0,0}, dy[]={0,0,-1,1,0,0}, dz[]={0,0,0,0,-1,1};\n                    for (int i=0; i<6; ++i) {\n                        Point3D next = {curr.x+dx[i], curr.y+dy[i], curr.z+dz[i]};\n                        if (is_valid_coord(next.x, next.y, next.z) && filler1_grid[next.x][next.y][next.z]) {\n                            filler1_grid[next.x][next.y][next.z] = false; q.push_back(next);\n                        }\n                    }\n                }\n                filler1_blocks.push_back({current_block_points, 0});\n            }\n        }\n    }\n    \n    vector<pair<int, ProtoBlock>> placed_common_blocks;\n    for(size_t i=0; i<common_blocks.size(); ++i) {\n        placed_common_blocks.push_back({(int)i, common_blocks[i]});\n    }\n    vector<ProtoBlock> filler2_blocks;\n    {\n        vector<vector<vector<bool>>> occupied2(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n        vector<bool> f2_req_met(D*D, false), r2_req_met(D*D, false);\n\n        sort(placed_common_blocks.begin(), placed_common_blocks.end(), [](const auto& a, const auto& b){\n            return a.second.points.size() > b.second.points.size();\n        });\n\n        for (auto& [idx, block] : placed_common_blocks) {\n            Shape s_rel = normalize_shape(block.points);\n            int best_block_score = -1; Shape best_block_placed_shape;\n            for (const auto& R : ROTS) {\n                Shape s_rot; for(const auto& p : s_rel) s_rot.push_back(rotate(p, R));\n                Point3D min_p = s_rot[0];\n                for(size_t i=1; i<s_rot.size(); ++i) { min_p.x=min(min_p.x,s_rot[i].x); min_p.y=min(min_p.y,s_rot[i].y); min_p.z=min(min_p.z,s_rot[i].z); }\n                for (int x=0; x<D; ++x) for(int y=0; y<D; ++y) for(int z=0; z<D; ++z) {\n                    Point3D trans = {x - min_p.x, y - min_p.y, z - min_p.z};\n                    bool possible = true; Shape placed_shape;\n                    set<pair<int,int>> f_covered, r_covered;\n                    for (const auto& p_rot : s_rot) {\n                        Point3D p_final = p_rot + trans;\n                        if (!is_valid_coord(p_final.x, p_final.y, p_final.z) || !C2[p_final.x][p_final.y][p_final.z] || occupied2[p_final.x][p_final.y][p_final.z]) {\n                            possible = false; break;\n                        }\n                        placed_shape.push_back(p_final);\n                        if (f2[p_final.z][p_final.x]=='1' && !f2_req_met[p_final.z*D+p_final.x]) f_covered.insert({p_final.z, p_final.x});\n                        if (r2[p_final.z][p_final.y]=='1' && !r2_req_met[p_final.z*D+p_final.y]) r_covered.insert({p_final.z, p_final.y});\n                    }\n                    if (possible) {\n                        int current_score = f_covered.size() + r_covered.size();\n                        if (current_score > best_block_score) {\n                            best_block_score = current_score; best_block_placed_shape = placed_shape;\n                        }\n                    }\n                }\n            }\n            if(best_block_score > -1){\n                block.points = best_block_placed_shape;\n                for (const auto& p : block.points) {\n                    occupied2[p.x][p.y][p.z] = true;\n                    f2_req_met[p.z*D+p.x] = true; r2_req_met[p.z*D+p.y] = true;\n                }\n            } else { block.points.clear(); }\n        }\n        \n        vector<Point3D> c2_rem_cells;\n        for (int x=0; x<D; ++x) for (int y=0; y<D; ++y) for (int z=0; z<D; ++z) {\n             if (C2[x][y][z] && !occupied2[x][y][z]) c2_rem_cells.push_back({x,y,z});\n        }\n        vector<Point3D> filler2_cells;\n        while(true) {\n            int best_score=0; int best_idx=-1;\n            for(size_t i=0; i<c2_rem_cells.size(); ++i){\n                const auto& p = c2_rem_cells[i];\n                int score = (f2[p.z][p.x]=='1' && !f2_req_met[p.z*D+p.x]) + (r2[p.z][p.y]=='1' && !r2_req_met[p.z*D+p.y]);\n                if(score > best_score) { best_score = score; best_idx = i; }\n            }\n            if(best_score == 0) break;\n            Point3D p = c2_rem_cells[best_idx];\n            filler2_cells.push_back(p);\n            f2_req_met[p.z*D+p.x] = true; r2_req_met[p.z*D+p.y] = true;\n            swap(c2_rem_cells[best_idx], c2_rem_cells.back()); c2_rem_cells.pop_back();\n        }\n        \n        vector<vector<vector<bool>>> filler2_grid(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n        for(const auto& p : filler2_cells) filler2_grid[p.x][p.y][p.z] = true;\n        for(const auto& p_start : filler2_cells) {\n            if (filler2_grid[p_start.x][p_start.y][p_start.z]) {\n                Shape current_block_points; vector<Point3D> q; q.push_back(p_start);\n                filler2_grid[p_start.x][p_start.y][p_start.z] = false;\n                size_t head = 0;\n                while(head < q.size()){\n                    Point3D curr = q[head++]; current_block_points.push_back(curr);\n                    int dx[]={-1,1,0,0,0,0}, dy[]={0,0,-1,1,0,0}, dz[]={0,0,0,0,-1,1};\n                    for (int i=0; i<6; ++i) {\n                        Point3D next = {curr.x+dx[i], curr.y+dy[i], curr.z+dz[i]};\n                        if (is_valid_coord(next.x, next.y, next.z) && filler2_grid[next.x][next.y][next.z]) {\n                            filler2_grid[next.x][next.y][next.z] = false; q.push_back(next);\n                        }\n                    }\n                }\n                filler2_blocks.push_back({current_block_points, 0});\n            }\n        }\n    }\n    \n    int next_id = 1;\n    for (auto& block : common_blocks) {\n        if (!block.points.empty()) {\n            block.id = next_id++;\n        }\n    }\n\n    map<Shape, vector<ProtoBlock*>> f1_by_canon, f2_by_canon;\n    set<Shape> all_filler_canons;\n\n    for (auto& block : filler1_blocks) {\n        if (block.points.empty()) continue;\n        Shape canon = get_canonical_shape(normalize_shape(block.points));\n        f1_by_canon[canon].push_back(&block);\n        all_filler_canons.insert(canon);\n    }\n    for (auto& block : filler2_blocks) {\n        if (block.points.empty()) continue;\n        Shape canon = get_canonical_shape(normalize_shape(block.points));\n        f2_by_canon[canon].push_back(&block);\n        all_filler_canons.insert(canon);\n    }\n\n    for (const auto& canon : all_filler_canons) {\n        auto it1 = f1_by_canon.find(canon);\n        auto it2 = f2_by_canon.find(canon);\n        vector<ProtoBlock*> v1 = (it1 == f1_by_canon.end()) ? vector<ProtoBlock*>() : it1->second;\n        vector<ProtoBlock*> v2 = (it2 == f2_by_canon.end()) ? vector<ProtoBlock*>() : it2->second;\n        \n        size_t matches = min(v1.size(), v2.size());\n        for (size_t i = 0; i < matches; ++i) {\n            int id = next_id++;\n            v1[i]->id = id;\n            v2[i]->id = id;\n        }\n        for (size_t i = matches; i < v1.size(); ++i) {\n            v1[i]->id = next_id++;\n        }\n        for (size_t i = matches; i < v2.size(); ++i) {\n            v2[i]->id = next_id++;\n        }\n    }\n\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    for (const auto& block : common_blocks) for (const auto& p : block.points) b1[p.x][p.y][p.z] = block.id;\n    for (const auto& block : filler1_blocks) for (const auto& p : block.points) b1[p.x][p.y][p.z] = block.id;\n\n    for (const auto& [idx, block] : placed_common_blocks) {\n        if (!block.points.empty()) {\n            int id = common_blocks[idx].id;\n            for (const auto& p : block.points) b2[p.x][p.y][p.z] = id;\n        }\n    }\n    for (const auto& block : filler2_blocks) for (const auto& p : block.points) b2[p.x][p.y][p.z] = block.id;\n    \n    cout << next_id - 1 << endl;\n    for (int x=0; x<D; ++x) for (int y=0; y<D; ++y) for (int z=0; z<D; ++z) cout << b1[x][y][z] << (x==D-1 && y==D-1 && z==D-1 ? \"\" : \" \"); cout << endl;\n    for (int x=0; x<D; ++x) for (int y=0; y<D; ++y) for (int z=0; z<D; ++z) cout << b2[x][y][z] << (x==D-1 && y==D-1 && z==D-1 ? \"\" : \" \"); cout << endl;\n\n    return 0;\n}","ahc020":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <queue>\n\nusing namespace std;\n\nconst long long INF = 1e18;\n\nstruct Point {\n    long long x, y;\n};\n\nstruct Edge {\n    int u, v;\n    long long w;\n    int id;\n};\n\nstruct GraphEdge {\n    int to;\n    long long weight;\n    int id;\n};\n\nlong long distSq(const Point& p1, const Point& p2) {\n    return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y);\n}\n\n// Global timer\nchrono::steady_clock::time_point start_time;\n\nbool is_time_up(double time_limit) {\n    auto now = chrono::steady_clock::now();\n    double elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n    return elapsed > time_limit;\n}\n\n// --- Precomputed data ---\nint N, M, K;\nvector<Point> stations;\nvector<Point> residents;\nvector<Edge> edges;\nvector<vector<GraphEdge>> adj;\nvector<vector<long long>> dist_G;\nvector<vector<int>> parent_G;\nvector<vector<pair<long long, int>>> dists_to_resident;\n\n// --- Randomness ---\nmt19937 rng;\n\nlong long integer_ceil_sqrt(long long n) {\n    if (n < 0) return 0;\n    if (n == 0) return 0;\n    long long root = sqrtl((long double)n);\n    while (root * root > n) {\n        root--;\n    }\n    while ((root + 1) * (root + 1) <= n) {\n        root++;\n    }\n    if (root * root < n) {\n        return root + 1;\n    }\n    return root;\n}\n\nlong long calculate_connection_cost(const vector<int>& V_list) {\n    if (V_list.size() <= 1) return 0;\n\n    long long cost = 0;\n    vector<long long> min_cost(N + 1, INF);\n    vector<bool> in_mst(N + 1, false);\n\n    min_cost[V_list[0]] = 0;\n    \n    for (size_t i = 0; i < V_list.size(); ++i) {\n        int u = -1;\n        for (int station_id : V_list) {\n            if (!in_mst[station_id] && (u == -1 || min_cost[station_id] < min_cost[u])) {\n                u = station_id;\n            }\n        }\n\n        if (u == -1) break;\n        in_mst[u] = true;\n        cost += min_cost[u];\n\n        for (int v : V_list) {\n            if (!in_mst[v]) {\n                min_cost[v] = min(min_cost[v], dist_G[u - 1][v - 1]);\n            }\n        }\n    }\n    return cost;\n}\n\nbool check_coverage(const vector<bool>& active) {\n    for (int k = 0; k < K; ++k) {\n        bool covered = false;\n        for (const auto& p : dists_to_resident[k]) {\n            if (active[p.second]) {\n                covered = true;\n                break;\n            }\n        }\n        if (!covered) return false;\n    }\n    return true;\n}\n\nlong long calculate_total_cost(const vector<bool>& active, vector<long long>& required_power_sq_out) {\n    vector<int> V_list;\n    for (int i = 1; i <= N; ++i) {\n        if (active[i]) V_list.push_back(i);\n    }\n    if (V_list.empty() || !active[1]) {\n        return INF;\n    }\n\n    long long connection_cost = calculate_connection_cost(V_list);\n\n    long long power_cost = 0;\n    required_power_sq_out.assign(N + 1, 0);\n\n    for (int k = 0; k < K; ++k) {\n        for (const auto& p : dists_to_resident[k]) {\n            int station_id = p.second;\n            if (active[station_id]) {\n                required_power_sq_out[station_id] = max(required_power_sq_out[station_id], p.first);\n                break;\n            }\n        }\n    }\n\n    for (int i = 1; i <= N; ++i) {\n        if (required_power_sq_out[i] > 0) {\n            long long p = integer_ceil_sqrt(required_power_sq_out[i]);\n            if (p > 5000) return INF;\n            power_cost += p * p;\n        }\n    }\n    \n    return connection_cost + power_cost;\n}\n\nlong long calculate_total_cost(const vector<bool>& active) {\n    vector<long long> dummy;\n    return calculate_total_cost(active, dummy);\n}\n\nvoid solve() {\n    start_time = chrono::steady_clock::now();\n    \n    cin >> N >> M >> K;\n    stations.resize(N);\n    for (int i = 0; i < N; ++i) cin >> stations[i].x >> stations[i].y;\n    edges.resize(M);\n    adj.resize(N + 1);\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\n        edges[i].id = i + 1;\n        adj[edges[i].u].push_back({edges[i].v, edges[i].w, edges[i].id});\n        adj[edges[i].v].push_back({edges[i].u, edges[i].w, edges[i].id});\n    }\n    residents.resize(K);\n    for (int i = 0; i < K; ++i) cin >> residents[i].x >> residents[i].y;\n\n    // Precomputation\n    dist_G.assign(N, vector<long long>(N, INF));\n    parent_G.assign(N, vector<int>(N, -1));\n\n    for (int i = 0; i < N; ++i) {\n        dist_G[i][i] = 0;\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n        pq.push({0, i + 1});\n\n        vector<long long> d(N + 1, INF);\n        vector<int> p(N + 1, -1);\n        d[i + 1] = 0;\n\n        while (!pq.empty()) {\n            auto [cost, u] = pq.top();\n            pq.pop();\n\n            if (cost > d[u]) continue;\n\n            for (const auto& edge : adj[u]) {\n                int v = edge.to;\n                if (d[u] + edge.weight < d[v]) {\n                    d[v] = d[u] + edge.weight;\n                    p[v] = u;\n                    pq.push({d[v], v});\n                }\n            }\n        }\n        for (int j = 0; j < N; ++j) {\n            dist_G[i][j] = d[j + 1];\n            parent_G[i][j] = p[j + 1];\n        }\n    }\n    \n    dists_to_resident.resize(K);\n    for (int k = 0; k < K; ++k) {\n        for (int i = 0; i < N; ++i) {\n            dists_to_resident[k].push_back({distSq(residents[k], stations[i]), i + 1});\n        }\n        sort(dists_to_resident[k].begin(), dists_to_resident[k].end());\n    }\n\n    // --- Robust Initial Solution with Fixup Loop ---\n    vector<bool> current_V(N + 1, false);\n    current_V[1] = true;\n    for (int iter = 0; iter < N + 5; ++iter) { // Safety break\n        // Phase 1: Ensure coverage\n        while (true) {\n            int uncovered_k = -1;\n            for (int k = 0; k < K; ++k) {\n                bool covered = false;\n                for (const auto& p : dists_to_resident[k]) {\n                    if (current_V[p.second]) {\n                        covered = true;\n                        break;\n                    }\n                }\n                if (!covered) {\n                    uncovered_k = k;\n                    break;\n                }\n            }\n            if (uncovered_k == -1) break;\n\n            for (const auto& p : dists_to_resident[uncovered_k]) {\n                if (p.first <= 5000LL * 5000LL) {\n                    if (!current_V[p.second]) {\n                        current_V[p.second] = true;\n                        break;\n                    }\n                }\n            }\n        }\n\n        // Phase 2: Check validity and fix power violations\n        vector<long long> req_p_sq;\n        calculate_total_cost(current_V, req_p_sq);\n\n        int problematic_resident = -1;\n        for (int i = 1; i <= N; ++i) {\n            if (req_p_sq[i] > 5000LL * 5000LL) {\n                for (int k = 0; k < K; ++k) {\n                    bool is_assigned = false;\n                    long long dist_to_i = -1;\n                    for (const auto& p : dists_to_resident[k]) {\n                        if (current_V[p.second]) {\n                            if (p.second == i) {\n                                is_assigned = true;\n                                dist_to_i = p.first;\n                            }\n                            break;\n                        }\n                    }\n                    if (is_assigned && dist_to_i == req_p_sq[i]) {\n                        problematic_resident = k;\n                        break;\n                    }\n                }\n            }\n            if (problematic_resident != -1) break;\n        }\n\n        if (problematic_resident == -1) break; // Valid solution found\n\n        for (const auto& p : dists_to_resident[problematic_resident]) {\n            if (p.first <= 5000LL * 5000LL) {\n                if (!current_V[p.second]) {\n                    current_V[p.second] = true;\n                    break;\n                }\n            }\n        }\n    }\n    \n    // --- Greedy Refinement ---\n    bool changed = true;\n    while(changed) {\n        changed = false;\n        vector<int> active_nodes;\n        for(int i=2; i<=N; ++i) if(current_V[i]) active_nodes.push_back(i);\n        shuffle(active_nodes.begin(), active_nodes.end(), rng);\n        \n        long long base_cost = calculate_total_cost(current_V);\n\n        for(int v : active_nodes) {\n            current_V[v] = false;\n            if (check_coverage(current_V)) {\n                long long new_cost = calculate_total_cost(current_V);\n                if (new_cost != INF && new_cost < base_cost) {\n                    base_cost = new_cost;\n                    changed = true;\n                } else {\n                    current_V[v] = true;\n                }\n            } else {\n                current_V[v] = true;\n            }\n        }\n    }\n\n\n    vector<bool> best_V = current_V;\n    vector<long long> current_req_p_sq;\n    long long current_cost = calculate_total_cost(current_V, current_req_p_sq);\n    long long best_cost = current_cost;\n\n    // --- Simulated Annealing ---\n    double time_limit = 1980;\n    double T_start = best_cost > 0 ? best_cost / 10.0 : 1000.0;\n    double T_end = 1.0;\n    \n    uniform_int_distribution<> dist_N(1, N);\n    uniform_real_distribution<> dist_real(0.0, 1.0);\n\n    while (!is_time_up(time_limit)) {\n        double elapsed = chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count();\n        double progress = elapsed / time_limit;\n        if (progress > 1.0) progress = 1.0;\n        double T = T_start * pow(T_end / T_start, progress);\n\n        vector<bool> next_V = current_V;\n        \n        double p = dist_real(rng);\n        if (p < 0.45) { // ADD\n            int u;\n            int attempts = 0;\n            do { u = dist_N(rng); attempts++; } while (next_V[u] && attempts < 2*N);\n            if (!next_V[u]) next_V[u] = true; else continue;\n        } else if (p < 0.9) { // REMOVE\n            vector<int> active_nodes;\n            for (int i=2; i<=N; ++i) if(next_V[i]) active_nodes.push_back(i);\n            if (active_nodes.empty()) continue;\n            uniform_int_distribution<> dist_rem(0, active_nodes.size() - 1);\n            int v = active_nodes[dist_rem(rng)];\n            next_V[v] = false;\n            if (!check_coverage(next_V)) continue;\n        } else { // SWAP\n            int u;\n            int attempts_u = 0;\n            do { u = dist_N(rng); attempts_u++; } while(next_V[u] && attempts_u < 2*N);\n            if(next_V[u]) continue;\n            vector<int> active_nodes;\n            for(int i=2; i<=N; ++i) if(next_V[i]) active_nodes.push_back(i);\n            if (active_nodes.empty()) continue;\n            uniform_int_distribution<> dist_rem(0, active_nodes.size() - 1);\n            int v = active_nodes[dist_rem(rng)];\n            next_V[u] = true;\n            next_V[v] = false;\n            if (!check_coverage(next_V)) continue;\n        }\n        \n        vector<long long> next_req_p_sq;\n        long long next_cost = calculate_total_cost(next_V, next_req_p_sq);\n        if(next_cost == INF) continue;\n\n        long long delta = next_cost - current_cost;\n        if (delta < 0 || (T > 0 && dist_real(rng) < exp(-(double)delta / T))) {\n            current_V = next_V;\n            current_cost = next_cost;\n            current_req_p_sq = next_req_p_sq;\n            if (current_cost < best_cost) {\n                best_cost = current_cost;\n                best_V = current_V;\n            }\n        }\n    }\n\n    // --- Output ---\n    vector<long long> P(N + 1, 0);\n    vector<long long> required_power_sq(N + 1, 0);\n    for (int k = 0; k < K; ++k) {\n        for (const auto& p : dists_to_resident[k]) {\n            int station_id = p.second;\n            if (best_V[station_id]) {\n                required_power_sq[station_id] = max(required_power_sq[station_id], p.first);\n                break;\n            }\n        }\n    }\n    for (int i = 1; i <= N; ++i) {\n        if (best_V[i] && required_power_sq[i] > 0) {\n            P[i] = integer_ceil_sqrt(required_power_sq[i]);\n        }\n    }\n\n    vector<bool> B(M + 1, false);\n    vector<int> V_list;\n    for (int i = 1; i <= N; ++i) if (best_V[i]) V_list.push_back(i);\n\n    if (V_list.size() > 1) {\n        vector<long long> min_cost(N + 1, INF);\n        vector<int> edge_from(N + 1, -1);\n        vector<bool> in_mst(N + 1, false);\n        min_cost[V_list[0]] = 0;\n\n        for (size_t i = 0; i < V_list.size(); ++i) {\n            int u = -1;\n            for (int station_id : V_list) {\n                if (!in_mst[station_id] && (u == -1 || min_cost[station_id] < min_cost[u])) {\n                    u = station_id;\n                }\n            }\n            if (u == -1) break;\n            in_mst[u] = true;\n            if (edge_from[u] != -1) {\n                int v = edge_from[u];\n                int start_node_idx = v - 1;\n                int curr_node_idx = u - 1;\n                while(curr_node_idx != start_node_idx) {\n                    int prev_node = parent_G[start_node_idx][curr_node_idx];\n                    if (prev_node == -1) break;\n                    for(const auto& edge : adj[curr_node_idx + 1]) {\n                        if (edge.to == prev_node) { B[edge.id] = true; break; }\n                    }\n                    curr_node_idx = prev_node - 1;\n                }\n            }\n            for (int v_idx : V_list) {\n                if (!in_mst[v_idx] && dist_G[u - 1][v_idx - 1] < min_cost[v_idx]) {\n                    min_cost[v_idx] = dist_G[u - 1][v_idx - 1];\n                    edge_from[v_idx] = u;\n                }\n            }\n        }\n    }\n\n    for (int i = 1; i <= N; ++i) cout << P[i] << (i == N ? \"\" : \" \");\n    cout << endl;\n    for (int i = 1; i <= M; ++i) cout << B[i] << (i == M ? \"\" : \" \");\n    cout << endl;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    unsigned int seed = chrono::high_resolution_clock::now().time_since_epoch().count();\n    rng.seed(seed);\n    solve();\n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <tuple>\n\nconst int N = 30;\nconst int TOTAL_BALLS = N * (N + 1) / 2;\nconst int MAX_OPS = 10000;\n\nstd::vector<std::vector<int>> b;\nstd::vector<std::pair<int, int>> pos;\nstd::vector<std::tuple<int, int, int, int>> ops;\n\nvoid do_swap(int r1, int c1, int r2, int c2) {\n    if (ops.size() >= MAX_OPS) return;\n\n    int val1 = b[r1][c1];\n    int val2 = b[r2][c2];\n\n    std::swap(b[r1][c1], b[r2][c2]);\n    std::swap(pos[val1], pos[val2]);\n    \n    ops.emplace_back(r1, c1, r2, c2);\n}\n\n// Moves small values up as far as they can go.\nvoid small_up_climb_pass() {\n    for (int v = 0; v < TOTAL_BALLS; ++v) {\n        while (ops.size() < MAX_OPS) {\n            auto [r, c] = pos[v];\n            if (r == 0) break;\n\n            bool has_p_left = (c > 0);\n            bool has_p_right = (c < r);\n\n            int p_left_val = -1, p_right_val = -1;\n            if (has_p_left) p_left_val = b[r - 1][c - 1];\n            if (has_p_right) p_right_val = b[r - 1][c];\n            \n            bool swap_left = has_p_left && v < p_left_val;\n            bool swap_right = has_p_right && v < p_right_val;\n\n            if (!swap_left && !swap_right) break;\n\n            if (swap_left && swap_right) {\n                if (p_left_val > p_right_val) {\n                    do_swap(r, c, r - 1, c - 1);\n                } else {\n                    do_swap(r, c, r - 1, c);\n                }\n            } else if (swap_left) {\n                do_swap(r, c, r - 1, c - 1);\n            } else { // swap_right\n                do_swap(r, c, r - 1, c);\n            }\n        }\n    }\n}\n\n// Moves large values down as far as they can go.\nvoid large_down_sink_pass() {\n    for (int v = TOTAL_BALLS - 1; v >= 0; --v) {\n        while (ops.size() < MAX_OPS) {\n            auto [r, c] = pos[v];\n            if (r == N - 1) break;\n            \n            int child_left_val = b[r + 1][c];\n            int child_right_val = b[r + 1][c + 1];\n\n            bool swap_left = v > child_left_val;\n            bool swap_right = v > child_right_val;\n\n            if (!swap_left && !swap_right) break;\n\n            if (swap_left && swap_right) {\n                if (child_left_val < child_right_val) {\n                    do_swap(r, c, r + 1, c);\n                } else {\n                    do_swap(r, c, r + 1, c + 1);\n                }\n            } else if (swap_left) {\n                do_swap(r, c, r + 1, c);\n            } else { // swap_right\n                do_swap(r, c, r + 1, c + 1);\n            }\n        }\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    b.resize(N);\n    pos.resize(TOTAL_BALLS);\n    for (int i = 0; i < N; ++i) {\n        b[i].resize(i + 1);\n        for (int j = 0; j <= i; ++j) {\n            std::cin >> b[i][j];\n            pos[b[i][j]] = {i, j};\n        }\n    }\n\n    int iter = 0;\n    while(ops.size() < MAX_OPS) {\n        size_t ops_before_iter = ops.size();\n        \n        if (iter % 2 == 0) {\n            small_up_climb_pass();\n            if (ops.size() >= MAX_OPS) break;\n            large_down_sink_pass();\n        } else {\n            large_down_sink_pass();\n            if (ops.size() >= MAX_OPS) break;\n            small_up_climb_pass();\n        }\n\n        if (ops.size() == ops_before_iter) break;\n        iter++;\n    }\n\n    std::cout << ops.size() << \"\\n\";\n    for (const auto& op : ops) {\n        std::cout << std::get<0>(op) << \" \" << std::get<1>(op) << \" \" << std::get<2>(op) << \" \" << std::get<3>(op) << \"\\n\";\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n#include <map>\n#include <tuple>\n#include <set>\n#include <cassert>\n\nusing namespace std;\n\n// Constants and global state\nconst int D_CONST = 9;\nconst int ENTRANCE_R = 0;\nconst int ENTRANCE_C = (D_CONST - 1) / 2;\nconst int DR[] = {-1, 1, 0, 0};\nconst int DC[] = {0, 0, -1, 1};\n\nint D_input, N;\nint C; // Total number of containers\nvector<vector<int>> grid; // Grid state: -3=Empty, -2=Entrance, -1=Obstacle, >=0=Container ID\nmap<int, pair<int, int>> container_locs; // Maps container ID to its location\n\n// Candidate struct for dynamic placement decision\nstruct Candidate {\n    int r, c;\n    int dist;\n    int dynamic_block_count;\n};\n\n// Utility to check if coordinates are within the grid\nbool is_valid(int r, int c) {\n    return r >= 0 && r < D_CONST && c >= 0 && c < D_CONST;\n}\n\n// Phase 1: Just read inputs and set up the initial grid\nvoid precompute() {\n    C = D_CONST * D_CONST - 1 - N;\n    grid.assign(D_CONST, vector<int>(D_CONST, -3));\n    grid[ENTRANCE_R][ENTRANCE_C] = -2;\n    \n    for (int i = 0; i < N; ++i) {\n        int r, c;\n        cin >> r >> c;\n        grid[r][c] = -1;\n    }\n}\n\n// Phase 2: Place containers using the dynamic, robust strategy\nvoid solve_placement() {\n    for (int d = 0; d < C; ++d) {\n        int t_d;\n        cin >> t_d;\n\n        // 1. Find all currently reachable empty squares and their distances from the entrance.\n        vector<pair<int, int>> reachable_empty_squares;\n        vector<vector<int>> dist_grid(D_CONST, vector<int>(D_CONST, -1));\n        queue<pair<int, int>> q;\n        \n        q.push({ENTRANCE_R, ENTRANCE_C});\n        dist_grid[ENTRANCE_R][ENTRANCE_C] = 0;\n\n        queue<pair<int, int>> q_bfs = q; // Use a copy for traversal\n        while(!q_bfs.empty()){\n            auto [r, c] = q_bfs.front();\n            q_bfs.pop();\n\n            if(grid[r][c] == -3) {\n                reachable_empty_squares.push_back({r, c});\n            }\n\n            for(int i = 0; i < 4; ++i){\n                int nr = r + DR[i];\n                int nc = c + DC[i];\n                if(is_valid(nr, nc) && dist_grid[nr][nc] == -1 && (grid[nr][nc] == -3 || grid[nr][nc] == -2)) {\n                    dist_grid[nr][nc] = dist_grid[r][c] + 1;\n                    q_bfs.push({nr, nc});\n                }\n            }\n        }\n        \n        // This assertion catches the case where the warehouse becomes fully blocked off.\n        // The dynamic strategy should prevent this from ever happening.\n        assert(!reachable_empty_squares.empty());\n\n        // 2. Evaluate each reachable empty square as a candidate for placement.\n        vector<Candidate> candidates;\n        for (const auto& square : reachable_empty_squares) {\n            int r = square.first;\n            int c = square.second;\n\n            grid[r][c] = -1; // Temporarily block the square to assess impact.\n\n            // Run a new BFS to find how many other empty squares remain reachable.\n            vector<vector<char>> visited_after(D_CONST, vector<char>(D_CONST, 0));\n            queue<pair<int, int>> q_check;\n            q_check.push({ENTRANCE_R, ENTRANCE_C});\n            visited_after[ENTRANCE_R][ENTRANCE_C] = 1;\n            \n            while(!q_check.empty()){\n                 auto [curr_r, curr_c] = q_check.front();\n                 q_check.pop();\n                 for(int i = 0; i < 4; ++i){\n                     int nr = curr_r + DR[i];\n                     int nc = curr_c + DC[i];\n                     if(is_valid(nr, nc) && !visited_after[nr][nc] && (grid[nr][nc] == -3 || grid[nr][nc] == -2)){\n                         visited_after[nr][nc] = 1;\n                         q_check.push({nr, nc});\n                     }\n                 }\n            }\n            \n            int reachable_count_after = 0;\n            for(const auto& other_square : reachable_empty_squares) {\n                if (square != other_square && visited_after[other_square.first][other_square.second]) {\n                    reachable_count_after++;\n                }\n            }\n\n            int dynamic_block_count = (int)(reachable_empty_squares.size() - 1) - reachable_count_after;\n            \n            grid[r][c] = -3; // Restore the square.\n            \n            candidates.push_back({r, c, dist_grid[r][c], dynamic_block_count});\n        }\n        \n        // 3. Select the best candidate based on the evaluation.\n        vector<Candidate> safe_candidates;\n        vector<Candidate> bottleneck_candidates;\n        for(const auto& cand : candidates) {\n            if(cand.dynamic_block_count == 0) {\n                safe_candidates.push_back(cand);\n            } else {\n                bottleneck_candidates.push_back(cand);\n            }\n        }\n        \n        Candidate best_cand;\n\n        if (!safe_candidates.empty()) {\n            if (t_d < C / 2) { // Low number container: place it close for easy access.\n                sort(safe_candidates.begin(), safe_candidates.end(), [](const Candidate& a, const Candidate& b){\n                    if(a.dist != b.dist) return a.dist < b.dist;\n                    if(a.r != b.r) return a.r < b.r;\n                    return a.c < b.c;\n                });\n            } else { // High number container: place it far away to keep paths clear.\n                sort(safe_candidates.begin(), safe_candidates.end(), [](const Candidate& a, const Candidate& b){\n                    if(a.dist != b.dist) return a.dist > b.dist;\n                    if(a.r != b.r) return a.r > b.r;\n                    return a.c > b.c;\n                });\n            }\n            best_cand = safe_candidates[0];\n        } else { // No safe spots, must use a bottleneck.\n            assert(!bottleneck_candidates.empty());\n            // Choose the bottleneck that does the least damage.\n            sort(bottleneck_candidates.begin(), bottleneck_candidates.end(), [](const Candidate& a, const Candidate& b){\n                if(a.dynamic_block_count != b.dynamic_block_count) return a.dynamic_block_count < b.dynamic_block_count;\n                if(a.dist != b.dist) return a.dist > b.dist; // Tie-break: place farther away.\n                if(a.r != b.r) return a.r > b.r;\n                return a.c > b.c;\n            });\n            best_cand = bottleneck_candidates[0];\n        }\n\n        grid[best_cand.r][best_cand.c] = t_d;\n        container_locs[t_d] = {best_cand.r, best_cand.c};\n        cout << best_cand.r << \" \" << best_cand.c << endl;\n    }\n}\n\n\n// Phase 3: Retrieve all containers in a greedy fashion\nvoid solve_retrieval() {\n    for (int k = 0; k < C; ++k) {\n        set<int> accessible_containers;\n        queue<pair<int, int>> q;\n        vector<vector<char>> visited_empty(D_CONST, vector<char>(D_CONST, 0));\n\n        q.push({ENTRANCE_R, ENTRANCE_C});\n        visited_empty[ENTRANCE_R][ENTRANCE_C] = 1;\n\n        while(!q.empty()){\n            auto [r, c] = q.front();\n            q.pop();\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + DR[i];\n                int nc = c + DC[i];\n                if (!is_valid(nr, nc)) continue;\n                \n                if (grid[nr][nc] >= 0) {\n                    accessible_containers.insert(grid[nr][nc]);\n                } else if ((grid[nr][nc] == -3 || grid[nr][nc] == -2) && !visited_empty[nr][nc]) {\n                    visited_empty[nr][nc] = 1;\n                    q.push({nr, nc});\n                }\n            }\n        }\n        \n        if (accessible_containers.empty()) {\n            break;\n        }\n\n        int min_t = *accessible_containers.begin();\n\n        auto [qr, qc] = container_locs[min_t];\n        cout << qr << \" \" << qc << endl;\n        grid[qr][qc] = -3;\n    }\n}\n\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> D_input >> N;\n    \n    precompute();\n    solve_placement();\n    solve_retrieval();\n\n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <set>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <queue>\n#include <tuple>\n\n// Constants\nconstexpr int N = 50;\nconstexpr int M = 100;\n\n// Randomness\nstruct Xoroshiro128 {\n    uint64_t s[2];\n\n    Xoroshiro128() {\n        std::random_device rd;\n        s[0] = ((uint64_t)rd() << 32) | rd();\n        s[1] = ((uint64_t)rd() << 32) | rd();\n    }\n\n    static inline uint64_t rotl(const uint64_t x, int k) {\n        return (x << k) | (x >> (64 - k));\n    }\n\n    uint64_t next() {\n        const uint64_t s0 = s[0];\n        uint64_t s1 = s[1];\n        const uint64_t result = s0 + s1;\n\n        s1 ^= s0;\n        s[0] = rotl(s0, 24) ^ s1 ^ (s1 << 16);\n        s[1] = rotl(s1, 37);\n\n        return result;\n    }\n\n    double next_double() {\n        return (double)(next() >> 11) * (1.0 / (1LL << 53));\n    }\n};\n\nXoroshiro128 rng;\n\n// Timer\nclass Timer {\npublic:\n    Timer() : start_time(std::chrono::high_resolution_clock::now()) {}\n\n    double get_elapsed_sec() {\n        auto now = std::chrono::high_resolution_clock::now();\n        return std::chrono::duration_cast<std::chrono::duration<double>>(now - start_time).count();\n    }\nprivate:\n    std::chrono::time_point<std::chrono::high_resolution_clock> start_time;\n};\n\n// Data structures\nstruct Point {\n    int r, c;\n};\n\nstruct Vec2d {\n    double x, y;\n};\n\n// Globals for problem data\nstd::vector<std::vector<bool>> adj;\nstd::vector<std::vector<int>> initial_grid;\n\nvoid read_input() {\n    int n_dummy, m_dummy;\n    std::cin >> n_dummy >> m_dummy;\n    initial_grid.assign(N, std::vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            std::cin >> initial_grid[i][j];\n        }\n    }\n}\n\nvoid build_adj() {\n    adj.assign(M + 1, std::vector<bool>(M + 1, false));\n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            if (r == 0 || r == N - 1 || c == 0 || c == N - 1) {\n                adj[initial_grid[r][c]][0] = adj[0][initial_grid[r][c]] = true;\n            }\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + dr[i];\n                int nc = c + dc[i];\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                    int c1 = initial_grid[r][c];\n                    int c2 = initial_grid[nr][nc];\n                    if (c1 != c2) {\n                        adj[c1][c2] = adj[c2][c1] = true;\n                    }\n                }\n            }\n        }\n    }\n}\n\nstruct Solution {\n    std::vector<std::vector<int>> grid;\n    int score;\n\n    Solution() : grid(N, std::vector<int>(N, 0)), score(0) {}\n\n    void calculate_score() {\n        int empty_count = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (grid[i][j] == 0) {\n                    empty_count++;\n                }\n            }\n        }\n        score = empty_count + 1;\n    }\n\n    void print() {\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                std::cout << grid[i][j] << (j == N - 1 ? \"\" : \" \");\n            }\n            std::cout << std::endl;\n        }\n    }\n};\n\nclass Solver {\npublic:\n    Solver(const Timer& timer) : timer(timer) {}\n\n    Solution solve() {\n        Solution best_solution;\n        best_solution.score = -1;\n\n        while(timer.get_elapsed_sec() < 1.95) {\n            Solution current_solution = generate_solution();\n            if (current_solution.score > best_solution.score) {\n                best_solution = current_solution;\n            }\n        }\n        return best_solution;\n    }\n\nprivate:\n    const Timer& timer;\n    std::vector<std::vector<int>> grid;\n    std::vector<Point> seed_pos;\n\n    Solution generate_solution() {\n        std::vector<Vec2d> positions = force_directed_layout();\n        grid.assign(N, std::vector<int>(N, 0));\n        seed_pos.assign(M + 1, {-1, -1});\n        place_seeds(positions);\n        connect_regions();\n        \n        Solution sol;\n        sol.grid = grid;\n        sol.calculate_score();\n        return sol;\n    }\n\n    std::vector<Vec2d> force_directed_layout() {\n        std::vector<Vec2d> pos(M + 1);\n        for (int i = 1; i <= M; ++i) {\n            pos[i] = {rng.next_double() * N, rng.next_double() * N};\n        }\n\n        double temp = N / 4.0;\n        const int iterations = 150;\n        const double k_attr = 0.1, k_rep = 150.0;\n        const double border_rep = 200.0;\n\n        for (int iter = 0; iter < iterations; ++iter) {\n            if (timer.get_elapsed_sec() > 1.95) break;\n\n            std::vector<Vec2d> forces(M + 1, {0.0, 0.0});\n            for (int i = 1; i <= M; ++i) {\n                for (int j = i + 1; j <= M; ++j) {\n                    Vec2d diff = {pos[j].x - pos[i].x, pos[j].y - pos[i].y};\n                    double dist_sq = diff.x * diff.x + diff.y * diff.y + 1e-6;\n                    double dist = std::sqrt(dist_sq);\n                    \n                    if (adj[i][j]) {\n                        double f = k_attr * (dist - N/10.0);\n                        forces[i].x += f * diff.x / dist;\n                        forces[i].y += f * diff.y / dist;\n                        forces[j].x -= f * diff.x / dist;\n                        forces[j].y -= f * diff.y / dist;\n                    } else {\n                        double f = k_rep / dist_sq;\n                        forces[i].x -= f * diff.x / dist;\n                        forces[i].y -= f * diff.y / dist;\n                        forces[j].x += f * diff.x / dist;\n                        forces[j].y += f * diff.y / dist;\n                    }\n                }\n            }\n\n            for (int i = 1; i <= M; ++i) {\n                 if (!adj[i][0]) {\n                    forces[i].x += border_rep / (pos[i].x * pos[i].x + 1e-6);\n                    forces[i].y += border_rep / (pos[i].y * pos[i].y + 1e-6);\n                    forces[i].x -= border_rep / ((N-1 - pos[i].x) * (N-1 - pos[i].x) + 1e-6);\n                    forces[i].y -= border_rep / ((N-1 - pos[i].y) * (N-1 - pos[i].y) + 1e-6);\n                }\n            }\n\n            for (int i = 1; i <= M; ++i) {\n                double force_mag = std::sqrt(forces[i].x * forces[i].x + forces[i].y * forces[i].y) + 1e-6;\n                pos[i].x += temp * forces[i].x / force_mag;\n                pos[i].y += temp * forces[i].y / force_mag;\n                pos[i].x = std::max(1.0, std::min((double)N - 2, pos[i].x));\n                pos[i].y = std::max(1.0, std::min((double)N - 2, pos[i].y));\n            }\n            temp *= 0.98;\n        }\n        return pos;\n    }\n\n    void place_seeds(const std::vector<Vec2d>& pos) {\n        std::vector<int> p(M);\n        std::iota(p.begin(), p.end(), 1);\n        auto mt = std::mt19937(rng.next());\n        std::shuffle(p.begin(), p.end(), mt);\n\n        for (int color : p) {\n            int target_r = std::round(pos[color].y);\n            int target_c = std::round(pos[color].x);\n\n            int best_r = -1, best_c = -1;\n            for (int d = 0; d < N; ++d) {\n                for(int i = -d; i <= d; ++i) {\n                    int j = d - std::abs(i);\n                    int r_offsets[] = {i, i};\n                    int c_offsets[] = {j, -j};\n                    for (int k = 0; k < 2; ++k) {\n                        int r = target_r + r_offsets[k];\n                        int c = target_c + c_offsets[k];\n                        if (r < 0 || r >= N || c < 0 || c >= N) continue;\n                        if (is_valid_placement(color, r, c)) {\n                            best_r = r; best_c = c; goto found_pos;\n                        }\n                    }\n                }\n            }\n            found_pos:;\n            if (best_r != -1) {\n                grid[best_r][best_c] = color;\n                seed_pos[color] = {best_r, best_c};\n            }\n        }\n    }\n\n    bool is_valid_placement(int color, int r, int c) {\n        if (grid[r][c] != 0) return false;\n        if (!adj[color][0] && (r == 0 || r == N - 1 || c == 0 || c == N - 1)) return false;\n        \n        int dr[] = {-1, 1, 0, 0};\n        int dc[] = {0, 0, -1, 1};\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i], nc = c + dc[i];\n            if (nr >= 0 && nr < N && nc >= 0 && nc < N && grid[nr][nc] != 0) {\n                if (!adj[color][grid[nr][nc]]) return false;\n            }\n        }\n        return true;\n    }\n\n    void connect_regions() {\n        std::vector<std::pair<int, int>> reqs;\n        for (int i = 1; i <= M; ++i) for (int j = i + 1; j <= M; ++j) if (adj[i][j]) reqs.push_back({i, j});\n        auto mt = std::mt19937(rng.next());\n        std::shuffle(reqs.begin(), reqs.end(), mt);\n        \n        std::vector<std::vector<bool>> satisfied_adj(M + 1, std::vector<bool>(M + 1, false));\n\n        for (const auto& p : reqs) {\n            if (timer.get_elapsed_sec() > 1.95) break;\n            \n            bool is_adj = false;\n            int c1 = p.first, c2 = p.second;\n            if(seed_pos[c1].r == -1 || seed_pos[c2].r == -1) continue;\n            for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) {\n                if(grid[r][c]==c1) {\n                    int dr[]={-1,1,0,0}, dc[]={0,0,-1,1};\n                    for(int i=0;i<4;++i) {\n                        int nr=r+dr[i], nc=c+dc[i];\n                        if(nr>=0 && nr<N && nc>=0 && nc<N && grid[nr][nc]==c2) { is_adj=true; goto end_check; }\n                    }\n                }\n            }\n            end_check:;\n\n            if (!is_adj) connect_pair(p.first, p.second);\n        }\n        \n        for (int i = 1; i <= M; ++i) {\n            if (timer.get_elapsed_sec() > 1.95) break;\n            if (adj[i][0]) {\n                 bool is_adj_to_0 = false;\n                 for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) {\n                    if (grid[r][c] == i && (r==0 || r==N-1 || c==0 || c==N-1)) {\n                        is_adj_to_0 = true; break;\n                    }\n                 }\n                 if(!is_adj_to_0) connect_to_border(i);\n            }\n        }\n    }\n\n    void connect_pair(int c1, int c2) {\n        using State = std::tuple<int, int, int>;\n        std::priority_queue<State, std::vector<State>, std::greater<State>> pq;\n        std::vector<std::vector<int>> dist(N, std::vector<int>(N, 1e9));\n        std::vector<std::vector<Point>> parent(N, std::vector<Point>(N, {-1, -1}));\n\n        for (int r = 0; r < N; ++r) for (int c = 0; c < N; ++c) {\n            if (grid[r][c] == c1) { pq.emplace(0, r, c); dist[r][c] = 0; }\n        }\n\n        const int PENALTY = N*N;\n        int dr[] = {-1, 1, 0, 0}; int dc[] = {0, 0, -1, 1};\n        Point end_pos = {-1, -1};\n\n        while (!pq.empty()) {\n            auto [d, r, c] = pq.top(); pq.pop();\n            if (d > dist[r][c]) continue;\n\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + dr[i], nc = c + dc[i];\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N && grid[nr][nc] == c2) {\n                    end_pos = {r, c}; goto path_found;\n                }\n            }\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + dr[i], nc = c + dc[i];\n                if (nr < 0 || nr >= N || nc < 0 || nc >= N || (grid[nr][nc] != 0 && grid[nr][nc] != c1)) continue;\n                int cost = 1, penalty = 0;\n                for (int j = 0; j < 4; ++j) {\n                    int nnr = nr + dr[j], nnc = nc + dc[j];\n                    if (nnr < 0 || nnr >= N || nnc < 0 || nnc >= N) continue;\n                    int neighbor_color = grid[nnr][nnc];\n                    if (neighbor_color != 0 && neighbor_color != c1 && !adj[c1][neighbor_color]) penalty += PENALTY;\n                }\n                if (dist[nr][nc] > d + cost + penalty) {\n                    dist[nr][nc] = d + cost + penalty; parent[nr][nc] = {r, c}; pq.emplace(dist[nr][nc], nr, nc);\n                }\n            }\n        }\n    path_found:\n        if (end_pos.r != -1) {\n            Point curr = end_pos;\n            while (grid[curr.r][curr.c] == 0) {\n                grid[curr.r][curr.c] = c1; curr = parent[curr.r][curr.c];\n            }\n        }\n    }\n\n    void connect_to_border(int c1) {\n        if (seed_pos[c1].r == -1) return;\n        using State = std::tuple<int, int, int>;\n        std::priority_queue<State, std::vector<State>, std::greater<State>> pq;\n        std::vector<std::vector<int>> dist(N, std::vector<int>(N, 1e9));\n        std::vector<std::vector<Point>> parent(N, std::vector<Point>(N, {-1, -1}));\n\n        for (int r = 0; r < N; ++r) for (int c = 0; c < N; ++c) {\n            if (grid[r][c] == c1) { pq.emplace(0, r, c); dist[r][c] = 0; }\n        }\n        \n        const int PENALTY = N*N;\n        int dr[] = {-1, 1, 0, 0}; int dc[] = {0, 0, -1, 1};\n        Point end_pos = {-1, -1};\n\n        while (!pq.empty()) {\n            auto [d, r, c] = pq.top(); pq.pop();\n            if (d > dist[r][c]) continue;\n            if (r == 0 || r == N - 1 || c == 0 || c == N - 1) { end_pos = {r, c}; break; }\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + dr[i], nc = c + dc[i];\n                if (nr < 0 || nr >= N || nc < 0 || nc >= N || (grid[nr][nc] != 0 && grid[nr][nc] != c1)) continue;\n                int cost = 1, penalty = 0;\n                for (int j = 0; j < 4; ++j) {\n                    int nnr = nr + dr[j], nnc = nc + dc[j];\n                    if (nnr < 0 || nnr >= N || nnc < 0 || nnc >= N) continue;\n                    int neighbor_color = grid[nnr][nnc];\n                    if (neighbor_color != 0 && neighbor_color != c1 && !adj[c1][neighbor_color]) penalty += PENALTY;\n                }\n                if (!adj[c1][0] && (nr==0 || nr==N-1 || nc==0 || nc==N-1)) penalty += PENALTY;\n                if (dist[nr][nc] > d + cost + penalty) {\n                    dist[nr][nc] = d + cost + penalty; parent[nr][nc] = {r, c}; pq.emplace(dist[nr][nc], nr, nc);\n                }\n            }\n        }\n        if (end_pos.r != -1) {\n            Point curr = end_pos;\n            while (grid[curr.r][curr.c] == 0) {\n                grid[curr.r][curr.c] = c1; curr = parent[curr.r][curr.c];\n            }\n        }\n    }\n};\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    Timer timer;\n\n    read_input();\n    build_adj();\n\n    Solver solver(timer);\n    Solution best_solution = solver.solve();\n    \n    best_solution.print();\n\n    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n\n// --- Utilities ---\nstruct Timer {\n    std::chrono::high_resolution_clock::time_point start_time;\n    Timer() {\n        start_time = std::chrono::high_resolution_clock::now();\n    }\n    long long get_elapsed_ms() const {\n        auto now = std::chrono::high_resolution_clock::now();\n        return std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time).count();\n    }\n};\n\nstd::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// --- Problem specific globals ---\nint N, D, Q;\nconst int NUM_PARTICLES = 2500; // Compromise between 2000 and 4000\nstd::vector<std::vector<long long>> particles;\ndouble W_CAP;\n\n// --- Query interaction ---\nchar query(const std::vector<int>& L, const std::vector<int>& R) {\n    std::cout << L.size() << \" \" << R.size();\n    for (int x : L) std::cout << \" \" << x;\n    for (int x : R) std::cout << \" \" << x;\n    std::cout << std::endl;\n    char res;\n    std::cin >> res;\n    return res;\n}\n\n// --- Particle management ---\nvoid generate_particles() {\n    particles.clear();\n    std::uniform_real_distribution<double> unif(0.0, 1.0);\n    const double lambda = 1e-5;\n\n    particles.reserve(NUM_PARTICLES);\n    for (int i = 0; i < NUM_PARTICLES; ++i) {\n        std::vector<long long> weights(N);\n        for (int j = 0; j < N; ++j) {\n            double w_prime;\n            do {\n                double u = std::max(1e-9, unif(rng)); // Avoid log(0)\n                w_prime = -log(u) / lambda;\n            } while (w_prime > W_CAP);\n            weights[j] = std::max(1LL, (long long)round(w_prime));\n        }\n        particles.push_back(weights);\n    }\n}\n\nvoid filter_particles(const std::vector<int>& L, const std::vector<int>& R, char result) {\n    std::vector<std::vector<long long>> next_particles;\n    next_particles.reserve(particles.size());\n    for (const auto& p : particles) {\n        long long sum_L = 0, sum_R = 0;\n        for (int i : L) sum_L += p[i];\n        for (int i : R) sum_R += p[i];\n        \n        bool consistent = false;\n        if (result == '<' && sum_L < sum_R) consistent = true;\n        else if (result == '>' && sum_L > sum_R) consistent = true;\n        else if (result == '=' && sum_L == sum_R) consistent = true;\n        \n        if (consistent) {\n            next_particles.push_back(p);\n        }\n    }\n    if (!next_particles.empty()) {\n        particles = std::move(next_particles);\n    }\n}\n\nstd::vector<double> get_estimated_weights() {\n    std::vector<double> avg_weights(N, 0.0);\n    if (particles.empty()) {\n        for(int i=0; i<N; ++i) avg_weights[i] = 1.0;\n        return avg_weights;\n    }\n    for (int i = 0; i < N; ++i) {\n        double total = 0;\n        for (const auto& p : particles) {\n            total += p[i];\n        }\n        avg_weights[i] = total / particles.size();\n    }\n    return avg_weights;\n}\n\n// --- Main logic ---\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    Timer timer;\n\n    std::cin >> N >> D >> Q;\n    W_CAP = 1e5 * N / D;\n\n    generate_particles();\n\n    int queries_made = 0;\n\n    // Phase 1: Sorting queries\n    int num_sort_queries = Q / 2;\n    \n    std::vector<std::pair<int, int>> pairs;\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            pairs.push_back({i, j});\n        }\n    }\n    std::shuffle(pairs.begin(), pairs.end(), rng);\n\n    for (int i = 0; i < num_sort_queries && i < (int)pairs.size() && queries_made < Q; ++i) {\n        auto [u, v] = pairs[i];\n        char res = query({u}, {v});\n        filter_particles({u}, {v}, res);\n        queries_made++;\n    }\n\n    // Phase 2: Hybrid magnitude queries\n    int magnitude_queries_count = 0;\n    int one_vs_many_cycle = 0;\n    while (queries_made < Q) {\n        auto estimated_weights = get_estimated_weights();\n        std::vector<int> p(N);\n        std::iota(p.begin(), p.end(), 0);\n        std::sort(p.begin(), p.end(), [&](int i, int j) {\n            return estimated_weights[i] < estimated_weights[j];\n        });\n\n        if (magnitude_queries_count % 4 == 0 && N > 1) {\n            // Query type: Balanced groups of all items\n            std::vector<int> L, R;\n            double sum_L = 0, sum_R = 0;\n            // Iterate from heaviest to lightest to form balanced groups\n            for (int i = N - 1; i >= 0; --i) {\n                int item_idx = p[i];\n                if (sum_L <= sum_R) {\n                    L.push_back(item_idx);\n                    sum_L += estimated_weights[item_idx];\n                } else {\n                    R.push_back(item_idx);\n                    sum_R += estimated_weights[item_idx];\n                }\n            }\n             if (L.empty() || R.empty()) { // Fallback, should not happen with N>=2\n                 char res = query({p[0]}, {p[1]});\n                 filter_particles({p[0]}, {p[1]}, res);\n            } else {\n                 char res = query(L, R);\n                 filter_particles(L, R, res);\n            }\n        } else {\n            // Query type: One heavy item vs a sum of light items\n            int k_idx = (N - 1) - (one_vs_many_cycle % (N - 1));\n            if (k_idx <= 0) k_idx = 1;\n            int item_k = p[k_idx];\n\n            std::vector<double> prefix_sum_w(k_idx, 0.0);\n            if (k_idx > 0) {\n                prefix_sum_w[0] = estimated_weights[p[0]];\n                for (int i = 1; i < k_idx; ++i) {\n                    prefix_sum_w[i] = prefix_sum_w[i-1] + estimated_weights[p[i]];\n                }\n            }\n            \n            auto it = std::upper_bound(prefix_sum_w.begin(), prefix_sum_w.end(), estimated_weights[item_k]);\n            int j_idx = std::distance(prefix_sum_w.begin(), it);\n            if (j_idx > 0 && j_idx < k_idx) {\n                if (std::abs(prefix_sum_w[j_idx] - estimated_weights[item_k]) > std::abs(prefix_sum_w[j_idx-1] - estimated_weights[item_k])) {\n                    j_idx--;\n                }\n            }\n            j_idx = std::max(0, std::min(k_idx - 1, j_idx));\n            \n            std::vector<int> L = {item_k};\n            std::vector<int> R;\n            for (int i = 0; i <= j_idx; ++i) {\n                R.push_back(p[i]);\n            }\n\n            char res = query(L, R);\n            filter_particles(L, R, res);\n            one_vs_many_cycle++;\n        }\n        queries_made++;\n        magnitude_queries_count++;\n    }\n\n    // Partitioning phase\n    auto final_weights = get_estimated_weights();\n    std::vector<long long> scaled_weights(N);\n    double scale_factor = 10000.0;\n    for(int i=0; i<N; ++i) {\n        scaled_weights[i] = round(final_weights[i] * scale_factor);\n    }\n\n    // Initial solution using LPT greedy algorithm\n    std::vector<int> p_part(N);\n    std::iota(p_part.begin(), p_part.end(), 0);\n    std::sort(p_part.begin(), p_part.end(), [&](int i, int j) {\n        return scaled_weights[i] > scaled_weights[j];\n    });\n\n    std::vector<int> assignment(N);\n    using int128 = __int128_t;\n    std::vector<int128> set_sums(D, 0);\n    \n    for (int item_idx : p_part) {\n        if (D > 0) {\n            auto min_it = std::min_element(set_sums.begin(), set_sums.end());\n            int best_set = std::distance(set_sums.begin(), min_it);\n            assignment[item_idx] = best_set;\n            set_sums[best_set] += scaled_weights[item_idx];\n        }\n    }\n    \n    // Simulated Annealing\n    std::vector<int128> current_set_sums = set_sums;\n    std::vector<int> current_assignment = assignment;\n    \n    int128 current_score = 0;\n    for(auto s : current_set_sums) current_score += s*s;\n\n    auto best_assignment = current_assignment;\n    int128 best_score = current_score;\n\n    long double start_temp = 1.0;\n    if (N > 0 && D > 1) {\n        long double total_worsening_delta = 0;\n        int worsening_moves = 0;\n        for (int i = 0; i < 100; ++i) {\n            int item_idx = rng() % N;\n            int d1 = current_assignment[item_idx];\n            int d2;\n            do { d2 = rng() % D; } while (d1 == d2);\n            \n            int128 w = scaled_weights[item_idx];\n            int128 s1 = current_set_sums[d1];\n            int128 s2 = current_set_sums[d2];\n            int128 delta = (s1-w)*(s1-w) + (s2+w)*(s2+w) - s1*s1 - s2*s2;\n            if (delta > 0) {\n                total_worsening_delta += (long double)delta;\n                worsening_moves++;\n            }\n        }\n        if (worsening_moves > 0) {\n            long double avg_worsening_delta = total_worsening_delta / worsening_moves;\n            long double initial_accept_prob = 0.5;\n            start_temp = -avg_worsening_delta / log(initial_accept_prob);\n        }\n    }\n\n    long long time_limit = 1950;\n    \n    while(D > 1) {\n        long long elapsed_ms = timer.get_elapsed_ms();\n        if (elapsed_ms >= time_limit) break;\n\n        long double elapsed_ratio = (long double)elapsed_ms / time_limit;\n        long double temp = start_temp * (1.0 - elapsed_ratio);\n        if (temp < 1e-9) temp = 1e-9;\n        \n        if (rng() % 4 != 0) { // Move\n            int item_idx = rng() % N;\n            int d1 = current_assignment[item_idx];\n            int d2;\n            do { d2 = rng() % D; } while (d1 == d2);\n\n            int128 w = scaled_weights[item_idx];\n            int128 s1 = current_set_sums[d1];\n            int128 s2 = current_set_sums[d2];\n\n            int128 new_score = current_score - s1*s1 - s2*s2 + (s1 - w)*(s1 - w) + (s2 + w)*(s2 + w);\n            \n            if (new_score < current_score || std::uniform_real_distribution<long double>(0,1)(rng) < expl((long double)(current_score - new_score) / temp)) {\n                current_assignment[item_idx] = d2;\n                current_set_sums[d1] -= w;\n                current_set_sums[d2] += w;\n                current_score = new_score;\n\n                if (current_score < best_score) {\n                    best_score = current_score;\n                    best_assignment = current_assignment;\n                }\n            }\n        } else { // Swap\n            if (N < 2) continue;\n            int item1_idx = rng() % N;\n            int item2_idx;\n            do { item2_idx = rng() % N; } while (item1_idx == item2_idx);\n\n            int d1 = current_assignment[item1_idx];\n            int d2 = current_assignment[item2_idx];\n\n            if (d1 == d2) continue;\n\n            int128 w1 = scaled_weights[item1_idx];\n            int128 w2 = scaled_weights[item2_idx];\n            int128 s1 = current_set_sums[d1];\n            int128 s2 = current_set_sums[d2];\n\n            int128 new_score = current_score - s1*s1 - s2*s2 + (s1 - w1 + w2)*(s1 - w1 + w2) + (s2 - w2 + w1)*(s2 - w2 + w1);\n\n            if (new_score < current_score || std::uniform_real_distribution<long double>(0,1)(rng) < expl((long double)(current_score - new_score) / temp)) {\n                std::swap(current_assignment[item1_idx], current_assignment[item2_idx]);\n                current_set_sums[d1] = s1 - w1 + w2;\n                current_set_sums[d2] = s2 - w2 + w1;\n                current_score = new_score;\n\n                if (current_score < best_score) {\n                    best_score = current_score;\n                    best_assignment = current_assignment;\n                }\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        std::cout << best_assignment[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    std::cout << std::endl;\n\n    return 0;\n}","ahc026":"#include <iostream>\n#include <vector>\n#include <deque>\n#include <array>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n\nusing namespace std;\n\n// Constants for the problem\nconst int N = 200;\nconst int M = 10;\nconst double TIME_LIMIT_MS = 1950.0;\n\n// Beam width parameters for a smoother linear decay.\n// Increased width due to reduced branching factor.\nconst int INITIAL_BEAM_WIDTH = 150;\nconst int FINAL_BEAM_WIDTH = 10;\n\nstruct State {\n    array<deque<int>, M> stacks;\n    array<pair<int, int>, N + 1> box_pos; // {stack_idx, height_from_bottom}\n    long long cost = 0;\n    double eval_score = 0.0;\n    vector<pair<int, int>> history;\n\n    State() {\n        for(int i=0; i<=N; ++i) box_pos[i] = {-1, -1};\n    }\n    \n    // The evaluation function to guide the beam search.\n    // Reverted to the simpler, more effective heuristic from V1.\n    void evaluate(int v_start) {\n        // h1: Heuristic for future unblocking cost (admissible part).\n        // This is the most direct estimate of future costs.\n        double h1 = 0;\n        for (int v = v_start; v <= N; ++v) {\n            if (box_pos[v].first != -1) { // if not carried out\n                int stack_idx = box_pos[v].first;\n                int height = box_pos[v].second;\n                int boxes_on_top = stacks[stack_idx].size() - height - 1;\n                if (boxes_on_top > 0) {\n                    h1 += boxes_on_top + 1;\n                }\n            }\n        }\n        \n        eval_score = cost + h1;\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    auto start_time = chrono::high_resolution_clock::now();\n\n    int n_in, m_in;\n    cin >> n_in >> m_in;\n\n    State initial_state;\n    for (int i = 0; i < M; ++i) {\n        initial_state.stacks[i].resize(N / M);\n        for (int j = 0; j < N / M; ++j) {\n            int b;\n            cin >> b;\n            initial_state.stacks[i][j] = b;\n            initial_state.box_pos[b] = {i, j};\n        }\n    }\n\n    vector<State> beam;\n    beam.push_back(initial_state);\n\n    for (int v_to_carry = 1; v_to_carry <= N; ++v_to_carry) {\n        double elapsed_ms = chrono::duration<double, milli>(chrono::high_resolution_clock::now() - start_time).count();\n        \n        int current_beam_width;\n        if (elapsed_ms >= TIME_LIMIT_MS) {\n            current_beam_width = 1;\n        } else {\n            double time_ratio = elapsed_ms / TIME_LIMIT_MS;\n            current_beam_width = static_cast<int>(INITIAL_BEAM_WIDTH - (INITIAL_BEAM_WIDTH - FINAL_BEAM_WIDTH) * time_ratio);\n            current_beam_width = max(1, current_beam_width);\n        }\n        \n        vector<State> candidates;\n        candidates.reserve(beam.size() * 3); // Reserve space for pruned candidates\n        \n        for (const auto& s : beam) {\n            int stack_idx = s.box_pos[v_to_carry].first;\n            int height = s.box_pos[v_to_carry].second;\n            \n            if (s.stacks[stack_idx].size() - 1 == height) { // is on top\n                State next_s = s;\n                int box_v = next_s.stacks[stack_idx].back();\n                next_s.stacks[stack_idx].pop_back();\n                next_s.box_pos[box_v] = {-1, -1};\n                next_s.history.push_back({box_v, 0});\n                next_s.evaluate(v_to_carry + 1);\n                candidates.push_back(move(next_s));\n            } else { // not on top, must move\n                int move_v = s.stacks[stack_idx][height + 1];\n                \n                vector<int> dest_options;\n                // Pruning Move Destinations: select a few promising options\n                {\n                    // 1. Find an empty stack\n                    int empty_idx = -1;\n                    for (int i = 0; i < M; ++i) {\n                        if (s.stacks[i].empty()) {\n                            empty_idx = i;\n                            break;\n                        }\n                    }\n                    if (empty_idx != -1) dest_options.push_back(empty_idx);\n\n                    // 2. Find the shortest non-empty stack (excluding src)\n                    int shortest_idx = -1;\n                    int min_size = N + 1;\n                    for (int i = 0; i < M; ++i) {\n                        if (i == stack_idx || s.stacks[i].empty()) continue;\n                        if ((int)s.stacks[i].size() < min_size) {\n                            min_size = s.stacks[i].size();\n                            shortest_idx = i;\n                        }\n                    }\n                    if (shortest_idx != -1) dest_options.push_back(shortest_idx);\n\n                    // 3. Find stack with largest top element (excluding src)\n                    int largest_top_idx = -1;\n                    int max_top = -1;\n                    for (int i = 0; i < M; ++i) {\n                        if (i == stack_idx || s.stacks[i].empty()) continue;\n                        if (s.stacks[i].back() > max_top) {\n                            max_top = s.stacks[i].back();\n                            largest_top_idx = i;\n                        }\n                    }\n                    if (largest_top_idx != -1) dest_options.push_back(largest_top_idx);\n                    \n                    if (dest_options.empty()) {\n                        for (int i = 0; i < M; ++i) {\n                            if (i != stack_idx) {\n                                dest_options.push_back(i);\n                                break;\n                            }\n                        }\n                    }\n\n                    sort(dest_options.begin(), dest_options.end());\n                    dest_options.erase(unique(dest_options.begin(), dest_options.end()), dest_options.end());\n                }\n\n                for (int dest_idx : dest_options) {\n                    State next_s = s;\n                    \n                    auto& src_stack = next_s.stacks[stack_idx];\n                    vector<int> moved_boxes;\n                    moved_boxes.assign(src_stack.begin() + height + 1, src_stack.end());\n                    src_stack.resize(height + 1);\n                    \n                    next_s.cost += moved_boxes.size() + 1;\n                    next_s.history.push_back({move_v, dest_idx + 1});\n                    \n                    auto& dest_stack = next_s.stacks[dest_idx];\n                    int old_dest_size = dest_stack.size();\n                    dest_stack.insert(dest_stack.end(), moved_boxes.begin(), moved_boxes.end());\n\n                    for (size_t i = 0; i < moved_boxes.size(); ++i) {\n                        next_s.box_pos[moved_boxes[i]] = {dest_idx, (int)(old_dest_size + i)};\n                    }\n                    \n                    int box_v = next_s.stacks[stack_idx].back();\n                    next_s.stacks[stack_idx].pop_back();\n                    next_s.box_pos[box_v] = {-1, -1};\n                    next_s.history.push_back({box_v, 0});\n\n                    next_s.evaluate(v_to_carry + 1);\n                    candidates.push_back(move(next_s));\n                }\n            }\n        }\n\n        sort(candidates.begin(), candidates.end(), [](const auto& a, const auto& b) {\n            return a.eval_score < b.eval_score;\n        });\n\n        beam.clear();\n        for (size_t i = 0; i < min((size_t)candidates.size(), (size_t)current_beam_width); ++i) {\n            beam.push_back(move(candidates[i]));\n        }\n        if (beam.empty() && !candidates.empty()) {\n            beam.push_back(move(candidates[0]));\n        }\n    }\n    \n    const State* best_state = &beam[0];\n    for(size_t i = 1; i < beam.size(); ++i) {\n        if(beam[i].cost < best_state->cost) {\n            best_state = &beam[i];\n        }\n    }\n\n    for (const auto& op : best_state->history) {\n        cout << op.first << \" \" << op.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc027":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <functional>\n#include <list>\n#include <set>\n#include <chrono>\n#include <map>\n\n// Timer\nauto start_time = std::chrono::high_resolution_clock::now();\n\nstruct Pos {\n    short r, c;\n    bool operator<(const Pos& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n    bool operator==(const Pos& other) const {\n        return r == other.r && c == other.c;\n    }\n};\n\nint N;\nstd::vector<std::string> h_walls, v_walls;\nstd::vector<std::vector<int>> d;\nstd::vector<std::vector<std::vector<Pos>>> adj;\nstd::vector<std::vector<long long>> k;\nstd::vector<std::vector<double>> g;\n\n// Randomness\nstd::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\nvoid build_adj() {\n    adj.assign(N, std::vector<std::vector<Pos>>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (i > 0 && h_walls[i - 1][j] == '0') adj[i][j].push_back({(short)(i - 1), (short)j});\n            if (i < N - 1 && h_walls[i][j] == '0') adj[i][j].push_back({(short)(i + 1), (short)j});\n            if (j > 0 && v_walls[i][j - 1] == '0') adj[i][j].push_back({(short)i, (short)(j - 1)});\n            if (j < N - 1 && v_walls[i][j] == '0') adj[i][j].push_back({(short)i, (short)(j + 1)});\n        }\n    }\n}\n\n// Generate initial path via randomized DFS\nstd::list<Pos> tour;\nstd::vector<std::vector<bool>> visited;\n\nvoid generate_initial_path_dfs(Pos p) {\n    visited[p.r][p.c] = true;\n    tour.push_back(p);\n    \n    std::vector<Pos> neighbors = adj[p.r][p.c];\n    std::shuffle(neighbors.begin(), neighbors.end(), rng);\n    \n    for (const auto& next_p : neighbors) {\n        if (!visited[next_p.r][next_p.c]) {\n            generate_initial_path_dfs(next_p);\n            tour.push_back(p);\n        }\n    }\n}\n\nstd::string pos_to_moves(const std::list<Pos>& pos_path) {\n    std::string moves;\n    moves.reserve(pos_path.size());\n    auto it = pos_path.begin();\n    Pos current = *it;\n    ++it;\n    while (it != pos_path.end()) {\n        Pos next = *it;\n        if (next.r == current.r - 1) moves.push_back('U');\n        else if (next.r == current.r + 1) moves.push_back('D');\n        else if (next.c == current.c - 1) moves.push_back('L');\n        else moves.push_back('R');\n        current = next;\n        ++it;\n    }\n    return moves;\n}\n\ndouble calculate_g(const Pos& p) {\n    if (k[p.r][p.c] == 0) return 1e18; // Should not happen after initial path\n    return (double)d[p.r][p.c] / (k[p.r][p.c] * (k[p.r][p.c] + 1.0));\n}\n\nstruct PQ_Elem {\n    double score;\n    Pos p;\n    bool operator<(const PQ_Elem& other) const {\n        if (std::abs(score - other.score) > 1e-9) return score < other.score;\n        return p < other.p;\n    }\n};\n\nvoid solve() {\n    build_adj();\n    \n    visited.assign(N, std::vector<bool>(N, false));\n    generate_initial_path_dfs({0,0});\n    \n    k.assign(N, std::vector<long long>(N, 0));\n    std::vector<std::vector<std::list<Pos>::iterator>> pos_iters(N, std::vector<std::list<Pos>::iterator>(N));\n\n    for(auto it = tour.begin(); it != tour.end(); ++it) {\n        k[it->r][it->c]++;\n        pos_iters[it->r][it->c] = it;\n    }\n\n    g.assign(N, std::vector<double>(N));\n    std::vector<std::vector<Pos>> best_neighbor(N, std::vector<Pos>(N));\n    std::set<PQ_Elem> pq;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            g[i][j] = calculate_g({(short)i, (short)j});\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            Pos p = {(short)i, (short)j};\n            double max_g = -1.0;\n            Pos bn = {-1, -1};\n            for (const auto& neighbor : adj[i][j]) {\n                if (g[neighbor.r][neighbor.c] > max_g) {\n                    max_g = g[neighbor.r][neighbor.c];\n                    bn = neighbor;\n                }\n            }\n            best_neighbor[i][j] = bn;\n            if (bn.r != -1) {\n                pq.insert({g[i][j] + max_g, p});\n            }\n        }\n    }\n\n    int MAX_L = 100000;\n    \n    while (tour.size() + 2 <= MAX_L) {\n        auto now = std::chrono::high_resolution_clock::now();\n        if (std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time).count() > 1980) {\n            break;\n        }\n\n        if (pq.empty()) break;\n        \n        PQ_Elem top = *pq.rbegin();\n        Pos u = top.p;\n        Pos v = best_neighbor[u.r][u.c];\n\n        if(v.r == -1) {\n            pq.erase(std::prev(pq.end()));\n            continue;\n        }\n        \n        auto it_u_orig = pos_iters[u.r][u.c];\n        auto it_after_u = std::next(it_u_orig);\n        auto it_new_u = tour.insert(it_after_u, u);\n        auto it_v = tour.insert(it_new_u, v);\n        \n        pos_iters[u.r][u.c] = it_new_u;\n        pos_iters[v.r][v.c] = it_v;\n\n        k[u.r][u.c]++;\n        k[v.r][v.c]++;\n\n        std::set<Pos> to_update_pq;\n        to_update_pq.insert(u);\n        to_update_pq.insert(v);\n        for(const auto& neighbor: adj[u.r][u.c]) to_update_pq.insert(neighbor);\n        for(const auto& neighbor: adj[v.r][v.c]) to_update_pq.insert(neighbor);\n        \n        for (const auto& p : to_update_pq) {\n            Pos bn = best_neighbor[p.r][p.c];\n            if (bn.r != -1) {\n                pq.erase({g[p.r][p.c] + g[bn.r][bn.c], p});\n            }\n        }\n        \n        g[u.r][u.c] = calculate_g(u);\n        g[v.r][v.c] = calculate_g(v);\n\n        for (const auto& p : to_update_pq) {\n            double max_g = -1.0;\n            Pos bn = {-1, -1};\n            if (!adj[p.r][p.c].empty()){\n                for (const auto& neighbor : adj[p.r][p.c]) {\n                    if (g[neighbor.r][neighbor.c] > max_g) {\n                        max_g = g[neighbor.r][neighbor.c];\n                        bn = neighbor;\n                    }\n                }\n                best_neighbor[p.r][p.c] = bn;\n                if (bn.r != -1) {\n                    pq.insert({g[p.r][p.c] + max_g, p});\n                }\n            }\n        }\n    }\n\n    std::string moves = pos_to_moves(tour);\n    std::cout << moves << std::endl;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    std::cin >> N;\n    h_walls.resize(N - 1);\n    v_walls.resize(N);\n    d.assign(N, std::vector<int>(N));\n    for (int i = 0; i < N - 1; ++i) std::cin >> h_walls[i];\n    for (int i = 0; i < N; ++i) std::cin >> v_walls[i];\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            std::cin >> d[i][j];\n        }\n    }\n    \n    solve();\n    \n    return 0;\n}","ahc028":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <random>\n\nusing namespace std;\n\n// Constants from problem statement\nconst int N_GRID = 15;\nconst int M_TARGETS = 200;\n\n// Global variables for problem input\nint start_r, start_c;\nvector<string> grid(N_GRID);\nvector<string> targets(M_TARGETS);\n\n// Precomputed data structures\nvector<pair<int, int>> char_positions[26];\nint overlaps[M_TARGETS][M_TARGETS];\ndouble avg_transition_cost[26][26];\ndouble weights[M_TARGETS][M_TARGETS];\n\n// Random number generator for SA\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// --- Utility Functions ---\n\nint manhattan_distance(int r1, int c1, int r2, int c2) {\n    return abs(r1 - r2) + abs(c1 - c2);\n}\n\n// --- Precomputation Functions ---\n\nvoid read_input() {\n    int n_in, m_in;\n    cin >> n_in >> m_in;\n    cin >> start_r >> start_c;\n    for (int i = 0; i < N_GRID; ++i) cin >> grid[i];\n    for (int i = 0; i < M_TARGETS; ++i) cin >> targets[i];\n}\n\nvoid precompute_char_positions() {\n    for (int i = 0; i < N_GRID; ++i) {\n        for (int j = 0; j < N_GRID; ++j) {\n            char_positions[grid[i][j] - 'A'].push_back({i, j});\n        }\n    }\n}\n\nvoid precompute_overlaps() {\n    for (int i = 0; i < M_TARGETS; ++i) {\n        for (int j = 0; j < M_TARGETS; ++j) {\n            if (i == j) continue;\n            for (int k = 4; k >= 1; --k) {\n                if (targets[i].substr(5 - k) == targets[j].substr(0, k)) {\n                    overlaps[i][j] = k;\n                    break;\n                }\n            }\n        }\n    }\n}\n\nvoid precompute_avg_transition_cost() {\n    for (int i = 0; i < 26; ++i) {\n        for (int j = 0; j < 26; ++j) {\n            if (char_positions[i].empty() || char_positions[j].empty()) continue;\n            double total_min_dist = 0;\n            for (const auto& p1 : char_positions[i]) {\n                int min_dist = 1e9;\n                for (const auto& p2 : char_positions[j]) {\n                    min_dist = min(min_dist, manhattan_distance(p1.first, p1.second, p2.first, p2.second));\n                }\n                total_min_dist += min_dist;\n            }\n            avg_transition_cost[i][j] = total_min_dist / char_positions[i].size() + 1.0;\n        }\n    }\n}\n\nvoid precompute_weights() {\n    for (int i = 0; i < M_TARGETS; ++i) {\n        for (int j = 0; j < M_TARGETS; ++j) {\n            if (i == j) continue;\n            int ov = overlaps[i][j];\n            const string& t_j = targets[j];\n            const string& t_i = targets[i];\n            \n            double cost_est = 0;\n            if (5 - ov > 0) {\n                cost_est += avg_transition_cost[t_i.back() - 'A'][t_j[ov] - 'A'];\n                for (int k = ov; k < 4; ++k) {\n                    cost_est += avg_transition_cost[t_j[k] - 'A'][t_j[k+1] - 'A'];\n                }\n            }\n            weights[i][j] = (5.0 - ov) + cost_est;\n        }\n    }\n}\n\n// --- Core Logic ---\n\nlong long calculate_path_cost(const vector<int>& path, vector<pair<int, int>>& move_sequence) {\n    move_sequence.clear();\n    string S;\n    S.reserve(5 * M_TARGETS);\n    S += targets[path[0]];\n    for (size_t i = 1; i < path.size(); ++i) {\n        int u = path[i-1];\n        int v = path[i];\n        int ov = overlaps[u][v];\n        S += targets[v].substr(ov);\n    }\n\n    if (S.length() > 5000) return 1e18; \n\n    long long total_cost = 0;\n    int cur_r = start_r;\n    int cur_c = start_c;\n\n    for (char ch : S) {\n        int char_idx = ch - 'A';\n        int best_r = -1, best_c = -1;\n        int min_dist = 1e9;\n\n        for (const auto& pos : char_positions[char_idx]) {\n            int d = manhattan_distance(cur_r, cur_c, pos.first, pos.second);\n            if (d < min_dist) {\n                min_dist = d;\n                best_r = pos.first;\n                best_c = pos.second;\n            }\n        }\n        total_cost += min_dist + 1;\n        cur_r = best_r;\n        cur_c = best_c;\n        move_sequence.push_back({cur_r, cur_c});\n    }\n    return total_cost;\n}\n\nlong long calculate_path_cost(const vector<int>& path) {\n    vector<pair<int, int>> dummy;\n    return calculate_path_cost(path, dummy);\n}\n\ndouble calculate_approx_cost(const vector<int>& path) {\n    double cost = 0;\n    for (size_t i = 0; i < path.size() - 1; ++i) {\n        cost += weights[path[i]][path[i+1]];\n    }\n    return cost;\n}\n\nvector<int> get_initial_solution() {\n    vector<int> best_path;\n    double min_weight_sum = 1e18;\n\n    vector<int> start_nodes_to_try;\n    vector<int> p(M_TARGETS);\n    iota(p.begin(), p.end(), 0);\n    shuffle(p.begin(), p.end(), rng);\n    for(int i = 0; i < min(M_TARGETS, 10); ++i) start_nodes_to_try.push_back(p[i]);\n    \n    for (int start_node : start_nodes_to_try) {\n        vector<int> path;\n        path.reserve(M_TARGETS);\n        path.push_back(start_node);\n        vector<bool> visited(M_TARGETS, false);\n        visited[start_node] = true;\n        int current_node = start_node;\n        double current_weight_sum = 0;\n\n        for (int i = 0; i < M_TARGETS - 1; ++i) {\n            int next_node = -1;\n            double min_weight = 1e18;\n            for (int j = 0; j < M_TARGETS; ++j) {\n                if (!visited[j]) {\n                    if (weights[current_node][j] < min_weight) {\n                        min_weight = weights[current_node][j];\n                        next_node = j;\n                    }\n                }\n            }\n            visited[next_node] = true;\n            path.push_back(next_node);\n            current_weight_sum += min_weight;\n            current_node = next_node;\n        }\n        \n        if (current_weight_sum < min_weight_sum) {\n            min_weight_sum = current_weight_sum;\n            best_path = path;\n        }\n    }\n    return best_path;\n}\n\nvoid solve() {\n    auto time_start = chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_MS = 1950.0;\n    const double FAST_SA_TIME_MS = 1700.0;\n\n    vector<int> current_path = get_initial_solution();\n    vector<int> best_path_overall = current_path;\n    long long best_cost_overall = calculate_path_cost(best_path_overall);\n\n    // --- Fast SA Stage ---\n    {\n        double start_temp = 50.0, end_temp = 0.1;\n        vector<int> best_path_fast = current_path;\n        double current_approx_cost = calculate_approx_cost(current_path);\n        double best_approx_cost = current_approx_cost;\n        int iter_count = 0;\n\n        while (true) {\n            iter_count++;\n            if (iter_count % 100 == 0) {\n                if (chrono::duration<double, milli>(chrono::high_resolution_clock::now() - time_start).count() > FAST_SA_TIME_MS) break;\n            }\n\n            vector<int> new_path = current_path;\n            int i = uniform_int_distribution<int>(0, M_TARGETS - 1)(rng);\n            int j = uniform_int_distribution<int>(0, M_TARGETS - 1)(rng);\n            if (i == j) continue;\n            \n            int move_type = uniform_int_distribution<int>(0, 2)(rng);\n            if (move_type == 0) { // Reverse\n                if (i > j) swap(i, j);\n                reverse(new_path.begin() + i, new_path.begin() + j + 1);\n            } else if (move_type == 1) { // Swap\n                swap(new_path[i], new_path[j]);\n            } else { // Move\n                int element = new_path[i];\n                new_path.erase(new_path.begin() + i);\n                new_path.insert(new_path.begin() + j, element);\n            }\n\n            double new_approx_cost = calculate_approx_cost(new_path);\n            double elapsed_frac = chrono::duration<double, milli>(chrono::high_resolution_clock::now() - time_start).count() / FAST_SA_TIME_MS;\n            double temp = start_temp * pow(end_temp / start_temp, elapsed_frac);\n            \n            if (new_approx_cost < current_approx_cost || uniform_real_distribution<double>(0.0, 1.0)(rng) < exp((current_approx_cost - new_approx_cost) / temp)) {\n                current_path = new_path;\n                current_approx_cost = new_approx_cost;\n            }\n\n            if (current_approx_cost < best_approx_cost) {\n                best_approx_cost = current_approx_cost;\n                best_path_fast = current_path;\n            }\n        }\n        long long fast_sa_best_full_cost = calculate_path_cost(best_path_fast);\n        if (fast_sa_best_full_cost < best_cost_overall) {\n            best_cost_overall = fast_sa_best_full_cost;\n            best_path_overall = best_path_fast;\n        }\n    }\n\n    // --- Slow SA Stage ---\n    {\n        double start_temp = 30.0, end_temp = 0.01;\n        current_path = best_path_overall;\n        long long current_full_cost = best_cost_overall;\n        int iter_count = 0;\n        \n        while (true) {\n            iter_count++;\n             if (iter_count % 5 == 0) {\n                if (chrono::duration<double, milli>(chrono::high_resolution_clock::now() - time_start).count() > TIME_LIMIT_MS) break;\n            }\n\n            vector<int> new_path = current_path;\n            int i = uniform_int_distribution<int>(0, M_TARGETS - 1)(rng);\n            int j = uniform_int_distribution<int>(0, M_TARGETS - 1)(rng);\n            if (i == j) continue;\n            \n            int move_type = uniform_int_distribution<int>(0, 2)(rng);\n            if (move_type == 0) { // Reverse\n                if (i > j) swap(i, j);\n                reverse(new_path.begin() + i, new_path.begin() + j + 1);\n            } else if (move_type == 1) { // Swap\n                swap(new_path[i], new_path[j]);\n            } else { // Move\n                int element = new_path[i];\n                new_path.erase(new_path.begin() + i);\n                new_path.insert(new_path.begin() + j, element);\n            }\n\n            long long new_full_cost = calculate_path_cost(new_path);\n            \n            double elapsed_frac = (chrono::duration<double, milli>(chrono::high_resolution_clock::now() - time_start).count() - FAST_SA_TIME_MS) / (TIME_LIMIT_MS - FAST_SA_TIME_MS);\n            double temp = start_temp * pow(end_temp / start_temp, elapsed_frac);\n            \n            if (new_full_cost < current_full_cost || uniform_real_distribution<double>(0.0, 1.0)(rng) < exp((double)(current_full_cost - new_full_cost) / temp)) {\n                current_path = new_path;\n                current_full_cost = new_full_cost;\n            }\n\n            if (current_full_cost < best_cost_overall) {\n                best_cost_overall = current_full_cost;\n                best_path_overall = current_path;\n            }\n        }\n    }\n\n    vector<pair<int, int>> final_moves;\n    calculate_path_cost(best_path_overall, final_moves);\n    for (const auto& move : final_moves) {\n        cout << move.first << \" \" << move.second << \"\\n\";\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    read_input();\n    precompute_char_positions();\n    precompute_overlaps();\n    precompute_avg_transition_cost();\n    precompute_weights();\n    \n    solve();\n\n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <map>\n#include <iomanip>\n\n// Constants and Typedefs\nusing namespace std;\nusing Point = pair<int, int>;\n\n// Utilities\nstruct Timer {\n    chrono::high_resolution_clock::time_point start_time;\n    Timer() {\n        start_time = chrono::high_resolution_clock::now();\n    }\n    long long get_elapsed_ms() {\n        auto end_time = chrono::high_resolution_clock::now();\n        return chrono::duration_cast<chrono::milliseconds>(end_time - start_time).count();\n    }\n};\n\n// Global random engine\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// Problem specific structures\nstruct Polyomino {\n    int id;\n    int d;\n    vector<Point> coords;\n    int max_i = 0, max_j = 0;\n};\n\nstruct Problem {\n    int N, M;\n    double epsilon;\n    vector<Polyomino> fields;\n    vector<vector<Point>> valid_placements;\n    map<vector<Point>, vector<int>> identical_shapes;\n};\n\nstruct Particle {\n    vector<Point> placements;\n    vector<vector<int>> v_grid;\n\n    Particle(int M, int N) : placements(M), v_grid(N, vector<int>(N, 0)) {}\n\n    void compute_v_grid(const Problem& prob) {\n        for (auto& row : v_grid) fill(row.begin(), row.end(), 0);\n        for (int m = 0; m < prob.M; ++m) {\n            const auto& field = prob.fields[m];\n            const auto& p = placements[m];\n            for (const auto& rel_coord : field.coords) {\n                v_grid[p.first + rel_coord.first][p.second + rel_coord.second]++;\n            }\n        }\n    }\n};\n\n// Main solver\nclass Solver {\nprivate:\n    Problem prob;\n    int num_particles;\n    vector<Particle> particles;\n    vector<double> weights;\n    vector<vector<int>> known_v;\n    Timer timer;\n    int query_count = 0;\n    \npublic:\n    Solver(int N, int M, double epsilon, const vector<Polyomino>& fields, int K)\n        : prob{N, M, epsilon, fields}, num_particles(K), known_v(N, vector<int>(N, -1)) {\n        prob.valid_placements.resize(M);\n        for (int m = 0; m < M; ++m) {\n            auto& field = prob.fields[m];\n            field.max_i = 0;\n            field.max_j = 0;\n            for(const auto& p : field.coords) {\n                field.max_i = max(field.max_i, p.first);\n                field.max_j = max(field.max_j, p.second);\n            }\n            for (int i = 0; i < N - field.max_i; ++i) {\n                for (int j = 0; j < N - field.max_j; ++j) {\n                    prob.valid_placements[m].push_back({i, j});\n                }\n            }\n        }\n        \n        for (int m = 0; m < M; ++m) {\n            vector<Point> sorted_coords = fields[m].coords;\n            sort(sorted_coords.begin(), sorted_coords.end());\n            prob.identical_shapes[sorted_coords].push_back(m);\n        }\n    }\n\n    void solve() {\n        initialize_particles();\n\n        perform_initial_queries();\n\n        while (timer.get_elapsed_ms() < 2800 && query_count < 2 * prob.N * prob.N) {\n            auto p_grid = calculate_p_grid();\n            vector<Point> uncertain_cells;\n            Point most_uncertain_cell = {-1, -1};\n            double min_dist_to_half = 1.0;\n\n            for (int i = 0; i < prob.N; ++i) {\n                for (int j = 0; j < prob.N; ++j) {\n                    if (known_v[i][j] == -1) {\n                         if (p_grid[i][j] > 0.05 && p_grid[i][j] < 0.95) {\n                            uncertain_cells.push_back({i, j});\n                            if (abs(p_grid[i][j] - 0.5) < min_dist_to_half) {\n                                min_dist_to_half = abs(p_grid[i][j] - 0.5);\n                                most_uncertain_cell = {i, j};\n                            }\n                        }\n                    }\n                }\n            }\n            \n            if (most_uncertain_cell.first == -1) {\n                break; // Converged\n            }\n\n            if (uncertain_cells.size() < prob.N) { // Phase 3: Verification\n                query_drill(most_uncertain_cell.first, most_uncertain_cell.second);\n            } else { // Phase 2: Refinement\n                int block_size = 3;\n                vector<Point> query_set;\n                for (int di = -block_size / 2; di <= block_size / 2; ++di) {\n                    for (int dj = -block_size / 2; dj <= block_size / 2; ++dj) {\n                        int ni = most_uncertain_cell.first + di;\n                        int nj = most_uncertain_cell.second + dj;\n                        if (ni >= 0 && ni < prob.N && nj >= 0 && nj < prob.N && known_v[ni][nj] == -1) {\n                           query_set.push_back({ni, nj});\n                        }\n                    }\n                }\n                if (query_set.size() >= 2) {\n                    query_divine(query_set);\n                } else {\n                    query_drill(most_uncertain_cell.first, most_uncertain_cell.second);\n                }\n            }\n\n            if (timer.get_elapsed_ms() > 2800) break;\n\n            resample_and_mutate();\n        }\n\n        make_final_guess();\n    }\n\nprivate:\n    void initialize_particles() {\n        particles.clear();\n        for (int i = 0; i < num_particles; ++i) {\n            particles.emplace_back(prob.M, prob.N);\n            for (int m = 0; m < prob.M; ++m) {\n                uniform_int_distribution<> dist(0, prob.valid_placements[m].size() - 1);\n                particles.back().placements[m] = prob.valid_placements[m][dist(rng)];\n            }\n        }\n        for (auto& p : particles) p.compute_v_grid(prob);\n        weights.assign(num_particles, 1.0 / num_particles);\n    }\n    \n    void perform_initial_queries() {\n        vector<Point> all_cells, half_i, half_j, checker;\n        for (int i = 0; i < prob.N; ++i) {\n            for (int j = 0; j < prob.N; ++j) {\n                all_cells.push_back({i, j});\n                if (i < prob.N / 2) half_i.push_back({i, j});\n                if (j < prob.N / 2) half_j.push_back({i, j});\n                if ((i + j) % 2 == 0) checker.push_back({i, j});\n            }\n        }\n        \n        vector<vector<Point>> initial_queries = {all_cells, half_i, half_j, checker};\n        for(const auto& q_set : initial_queries){\n            if (timer.get_elapsed_ms() > 2800) break;\n            if (q_set.size() >= 2) {\n                query_divine(q_set);\n                resample_and_mutate();\n            }\n        }\n    }\n\n    void query_drill(int r, int c) {\n        if (known_v[r][c] != -1) return;\n        query_count++;\n        cout << \"q 1 \" << r << \" \" << c << endl;\n        int v;\n        cin >> v;\n        known_v[r][c] = v;\n        for (int i = 0; i < num_particles; ++i) {\n            if (particles[i].v_grid[r][c] != v) {\n                weights[i] = 0;\n            }\n        }\n    }\n\n    void query_divine(const vector<Point>& S) {\n        if (S.empty()) return;\n        if (S.size() == 1) {\n            query_drill(S[0].first, S[0].second);\n            return;\n        }\n\n        query_count++;\n        cout << \"q \" << S.size();\n        for (const auto& p : S) {\n            cout << \" \" << p.first << \" \" << p.second;\n        }\n        cout << endl;\n        \n        int O;\n        cin >> O;\n        \n        int k = S.size();\n        double var = k * prob.epsilon * (1.0 - prob.epsilon);\n        double stddev = sqrt(var);\n\n        for (int i = 0; i < num_particles; ++i) {\n            if (weights[i] == 0) continue;\n            int vS = 0;\n            for (const auto& p : S) {\n                vS += particles[i].v_grid[p.first][p.second];\n            }\n            double mu = k * prob.epsilon + vS * (1.0 - 2.0 * prob.epsilon);\n            \n            double prob_density;\n            if (stddev > 1e-9) {\n                prob_density = (1.0 / (stddev * sqrt(2 * M_PI))) * exp(-0.5 * pow((O - mu) / stddev, 2));\n            } else {\n                prob_density = (abs(O - mu) < 0.5) ? 1.0 : 1e-9;\n            }\n            weights[i] *= prob_density;\n        }\n    }\n\n    void resample_and_mutate() {\n        double total_weight = accumulate(weights.begin(), weights.end(), 0.0);\n        if (total_weight < 1e-20) {\n            initialize_particles();\n            return;\n        }\n        for (double& w : weights) {\n            w /= total_weight;\n        }\n\n        vector<Particle> new_particles;\n        new_particles.reserve(num_particles);\n        \n        discrete_distribution<int> dist(weights.begin(), weights.end());\n\n        int num_random_particles = num_particles * 0.05;\n        for (int i = 0; i < num_particles - num_random_particles; ++i) {\n            new_particles.push_back(particles[dist(rng)]);\n        }\n        for (int i = 0; i < num_random_particles; ++i) {\n            new_particles.emplace_back(prob.M, prob.N);\n            for (int m = 0; m < prob.M; ++m) {\n                uniform_int_distribution<> p_dist(0, prob.valid_placements[m].size() - 1);\n                new_particles.back().placements[m] = prob.valid_placements[m][p_dist(rng)];\n            }\n        }\n        \n        uniform_real_distribution<> r_dist(0.0, 1.0);\n        for(auto& p : new_particles) {\n            for(int m = 0; m < prob.M; ++m) {\n                if(r_dist(rng) < 0.1) {\n                    if (r_dist(rng) < 0.8 && prob.valid_placements[m].size() > 1) {\n                        const auto& current_pos = p.placements[m];\n                        vector<Point> neighbors;\n                        int dr[] = {-1,1,0,0}; int dc[] = {0,0,-1,1};\n                        for(int i=0; i<4; ++i) {\n                             Point neighbor = {current_pos.first + dr[i], current_pos.second + dc[i]};\n                             if (neighbor.first >= 0 && neighbor.first <= prob.N - 1 - prob.fields[m].max_i &&\n                                 neighbor.second >= 0 && neighbor.second <= prob.N - 1 - prob.fields[m].max_j) {\n                                neighbors.push_back(neighbor);\n                            }\n                        }\n                        if(!neighbors.empty()){\n                           uniform_int_distribution<> neighbor_dist(0, neighbors.size() - 1);\n                           p.placements[m] = neighbors[neighbor_dist(rng)];\n                        }\n                    } else {\n                        uniform_int_distribution<> p_dist(0, prob.valid_placements[m].size() - 1);\n                        p.placements[m] = prob.valid_placements[m][p_dist(rng)];\n                    }\n                }\n            }\n            for(const auto& [shape_coords, indices] : prob.identical_shapes) {\n                if (indices.size() > 1 && r_dist(rng) < 0.1) {\n                    uniform_int_distribution<int> idx_dist(0, indices.size() - 1);\n                    int m1_idx = idx_dist(rng);\n                    int m2_idx = idx_dist(rng);\n                    if (m1_idx == m2_idx) continue;\n                    swap(p.placements[indices[m1_idx]], p.placements[indices[m2_idx]]);\n                }\n            }\n        }\n\n        particles = new_particles;\n        for (auto& p : particles) p.compute_v_grid(prob);\n        weights.assign(num_particles, 1.0 / num_particles);\n    }\n    \n    vector<vector<double>> calculate_p_grid() {\n        vector<vector<double>> p_grid(prob.N, vector<double>(prob.N, 0.0));\n        for (const auto& p : particles) {\n            for (int i = 0; i < prob.N; ++i) {\n                for (int j = 0; j < prob.N; ++j) {\n                    if (p.v_grid[i][j] > 0) {\n                        p_grid[i][j] += 1.0;\n                    }\n                }\n            }\n        }\n        for (int i = 0; i < prob.N; ++i) {\n            for (int j = 0; j < prob.N; ++j) {\n                p_grid[i][j] /= num_particles;\n            }\n        }\n        return p_grid;\n    }\n\n    void make_final_guess() {\n        auto p_grid = calculate_p_grid();\n        \n        vector<Point> guess;\n        for (int i = 0; i < prob.N; ++i) {\n            for (int j = 0; j < prob.N; ++j) {\n                if (known_v[i][j] != -1) {\n                    if (known_v[i][j] > 0) {\n                        guess.push_back({i, j});\n                    }\n                } else {\n                    if (p_grid[i][j] > 0.5) {\n                        guess.push_back({i, j});\n                    }\n                }\n            }\n        }\n        \n        cout << \"a \" << guess.size();\n        for (const auto& p : guess) {\n            cout << \" \" << p.first << \" \" << p.second;\n        }\n        cout << endl;\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M;\n    double epsilon;\n    cin >> N >> M >> epsilon;\n\n    vector<Polyomino> fields(M);\n    for (int i = 0; i < M; ++i) {\n        fields[i].id = i;\n        cin >> fields[i].d;\n        fields[i].coords.resize(fields[i].d);\n        for (int j = 0; j < fields[i].d; ++j) {\n            cin >> fields[i].coords[j].first >> fields[i].coords[j].second;\n        }\n    }\n    \n    int K = 2000;\n    if (N <= 12) K = 1000;\n    if (M >= 15) K = 3000;\n\n    Solver solver(N, M, epsilon, fields, K);\n    solver.solve();\n\n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n#include <functional>\n\nusing namespace std;\n\n// Constants\nconstexpr int W = 1000;\nint D, N;\n\n// Structures\nstruct Rect {\n    int r0, c0, r1, c1;\n    long long area() const {\n        return (long long)(r1 - r0) * (c1 - c0);\n    }\n};\n\nstruct Node {\n    bool is_leaf;\n    int k_min, k_max; // range of reservation indices\n    Node *left = nullptr, *right = nullptr;\n    Node *parent = nullptr;\n\n    // For internal nodes\n    bool is_vertical_split;\n    int split_idx;\n\n    // For leaf nodes\n    int k;\n};\n\n// Globals\nvector<vector<long long>> a;\nvector<Node> tree_nodes;\nint node_idx_counter;\nvector<Rect> current_rects;\nvector<int> split_coords;\nvector<Node*> split_idx_to_node;\n\nvector<vector<bool>> h_prev_exists, v_prev_exists;\nvector<vector<int>> h_curr_count, v_curr_count;\n\n// Randomness\nuint64_t xor_shift() {\n    static uint64_t x = 88172645463325252ULL;\n    x ^= x << 13;\n    x ^= x >> 7;\n    x ^= x << 17;\n    return x;\n}\n\nint rand_int(int min_val, int max_val) {\n    if (min_val > max_val) return min_val;\n    return min_val + xor_shift() % (max_val - min_val + 1);\n}\n\ndouble rand_double() {\n    return (double)xor_shift() / UINT64_MAX;\n}\n\n// Tree building\nNode* build_tree(int k_min, int k_max, const Rect& region) {\n    Node* node = &tree_nodes[node_idx_counter++];\n    node->k_min = k_min;\n    node->k_max = k_max;\n\n    if (k_max - k_min == 1) {\n        node->is_leaf = true;\n        node->k = k_min;\n        return node;\n    }\n\n    node->is_leaf = false;\n    int k_mid = k_min + (k_max - k_min) / 2;\n    \n    node->is_vertical_split = (region.c1 - region.c0 >= region.r1 - region.r0);\n    \n    Rect left_region, right_region;\n    if (node->is_vertical_split) {\n        int c_split = region.c0 + (region.c1 - region.c0) / 2;\n        left_region = {region.r0, region.c0, region.r1, c_split};\n        right_region = {region.r0, c_split, region.r1, region.c1};\n    } else {\n        int r_split = region.r0 + (region.r1 - region.r0) / 2;\n        left_region = {region.r0, region.c0, r_split, region.c1};\n        right_region = {r_split, region.c0, region.r1, region.c1};\n    }\n    \n    node->left = build_tree(k_min, k_mid, left_region);\n    node->left->parent = node;\n    node->right = build_tree(k_mid, k_max, right_region);\n    node->right->parent = node;\n    return node;\n}\n\nvoid assign_split_indices(Node* node, int& split_idx_counter) {\n    if (node->is_leaf) return;\n    node->split_idx = split_idx_counter++;\n    split_idx_to_node[node->split_idx] = node;\n    assign_split_indices(node->left, split_idx_counter);\n    assign_split_indices(node->right, split_idx_counter);\n}\n\n\n// Layout and cost calculations\nvoid get_rects_from_coords(Node* node, const Rect& region, const vector<int>& coords, vector<Rect>& rects_out) {\n    if (node->is_leaf) {\n        rects_out[node->k] = region;\n        return;\n    }\n\n    int coord = coords[node->split_idx];\n    Rect left_region, right_region;\n\n    if (node->is_vertical_split) {\n        left_region = {region.r0, region.c0, region.r1, coord};\n        right_region = {region.r0, coord, region.r1, region.c1};\n    } else {\n        left_region = {region.r0, region.c0, coord, region.c1};\n        right_region = {coord, region.c0, region.r1, region.c1};\n    }\n    get_rects_from_coords(node->left, left_region, coords, rects_out);\n    get_rects_from_coords(node->right, right_region, coords, rects_out);\n}\n\nvoid get_ideal_coords(Node* node, const Rect& region, int d, vector<int>& coords) {\n    if (node->is_leaf) return;\n    \n    long long total_area_left = 0;\n    for (int k = node->left->k_min; k < node->left->k_max; ++k) total_area_left += a[d][k];\n    \n    long long total_area_right = 0;\n    for (int k = node->right->k_min; k < node->right->k_max; ++k) total_area_right += a[d][k];\n\n    long long total_area_node = total_area_left + total_area_right;\n    if (total_area_node == 0) total_area_node = 1;\n\n    int coord;\n    Rect left_region, right_region;\n    if (node->is_vertical_split) {\n        coord = region.c0 + round((double)(region.c1 - region.c0) * total_area_left / total_area_node);\n        coord = clamp(coord, region.c0 + 1, region.c1 - 1);\n        left_region = {region.r0, region.c0, region.r1, coord};\n        right_region = {region.r0, coord, region.r1, region.c1};\n    } else {\n        coord = region.r0 + round((double)(region.r1 - region.r0) * total_area_left / total_area_node);\n        coord = clamp(coord, region.r0 + 1, region.r1 - 1);\n        left_region = {region.r0, region.c0, coord, region.c1};\n        right_region = {coord, region.c0, region.r1, region.c1};\n    }\n    coords[node->split_idx] = coord;\n    get_ideal_coords(node->left, left_region, d, coords);\n    get_ideal_coords(node->right, right_region, d, coords);\n}\n\nlong long calculate_area_cost(int d, const vector<Rect>& rects) {\n    long long cost = 0;\n    for (int k = 0; k < N; ++k) {\n        cost += 100 * max(0LL, a[d][k] - rects[k].area());\n    }\n    return cost;\n}\n\nvoid populate_partition_counts(const vector<Rect>& rects) {\n    for (int i=1; i<W; ++i) fill(h_curr_count[i].begin(), h_curr_count[i].end(), 0);\n    for (int i=0; i<W; ++i) fill(v_curr_count[i].begin(), v_curr_count[i].end(), 0);\n    \n    for (int k = 0; k < N; ++k) {\n        const auto& r = rects[k];\n        if (r.r0 > 0) for (int c = r.c0; c < r.c1; ++c) h_curr_count[r.r0][c]++;\n        if (r.r1 < W) for (int c = r.c0; c < r.c1; ++c) h_curr_count[r.r1][c]++;\n        if (r.c0 > 0) for (int i = r.r0; i < r.r1; ++i) v_curr_count[i][r.c0]++;\n        if (r.c1 < W) for (int i = r.r0; i < r.r1; ++i) v_curr_count[i][r.c1]++;\n    }\n}\n\nlong long calculate_partition_change_cost_full() {\n    long long cost = 0;\n    for (int i = 1; i < W; ++i) {\n        for (int j = 0; j < W; ++j) {\n            cost += (h_prev_exists[i][j] != (h_curr_count[i][j] > 0));\n        }\n    }\n    for (int i = 0; i < W; ++i) {\n        for (int j = 1; j < W; ++j) {\n            cost += (v_prev_exists[i][j] != (v_curr_count[i][j] > 0));\n        }\n    }\n    return cost;\n}\n\nvoid update_prev_partitions() {\n    for (int i = 1; i < W; ++i) {\n        for (int j = 0; j < W; ++j) {\n            h_prev_exists[i][j] = (h_curr_count[i][j] > 0);\n        }\n    }\n    for (int i = 0; i < W; ++i) {\n        for (int j = 1; j < W; ++j) {\n            v_prev_exists[i][j] = (v_curr_count[i][j] > 0);\n        }\n    }\n}\n\n// Main logic\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int W_in;\n    cin >> W_in >> D >> N; \n    a.resize(D, vector<long long>(N));\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            cin >> a[d][k];\n        }\n    }\n\n    tree_nodes.resize(2 * N);\n    node_idx_counter = 0;\n    split_idx_to_node.resize(N - 1);\n    Node* root = build_tree(0, N, {0, 0, W, W});\n    int split_idx_counter = 0;\n    assign_split_indices(root, split_idx_counter);\n\n    current_rects.resize(N);\n    split_coords.resize(N - 1);\n    \n    h_prev_exists.resize(W + 1, vector<bool>(W + 1, false));\n    v_prev_exists.resize(W + 1, vector<bool>(W + 1, false));\n    h_curr_count.resize(W + 1, vector<int>(W + 1, 0));\n    v_curr_count.resize(W + 1, vector<int>(W + 1, 0));\n\n    // Day 0\n    get_ideal_coords(root, {0, 0, W, W}, 0, split_coords);\n    get_rects_from_coords(root, {0, 0, W, W}, split_coords, current_rects);\n    populate_partition_counts(current_rects);\n    update_prev_partitions();\n\n    vector<vector<Rect>> solution(D, vector<Rect>(N));\n    solution[0] = current_rects;\n\n    auto global_start_time = chrono::high_resolution_clock::now();\n\n    // Day 1 to D-1\n    for (int d = 1; d < D; ++d) {\n        get_rects_from_coords(root, {0, 0, W, W}, split_coords, current_rects);\n        populate_partition_counts(current_rects);\n        \n        long long current_area_cost = calculate_area_cost(d, current_rects);\n        long long partition_change_cost = calculate_partition_change_cost_full();\n        long long current_total_cost = current_area_cost + partition_change_cost;\n        \n        vector<int> best_coords = split_coords;\n        long long best_total_cost = current_total_cost;\n        \n        auto day_start_time = chrono::high_resolution_clock::now();\n        double time_limit_per_day = (2950.0 - chrono::duration_cast<chrono::milliseconds>(day_start_time - global_start_time).count()) / (D - d);\n\n        double temp = 5000;\n        int iter = 0;\n        while (true) {\n            iter++;\n            if (iter % 128 == 0) {\n                 auto now = chrono::high_resolution_clock::now();\n                 double elapsed = chrono::duration_cast<chrono::milliseconds>(now - day_start_time).count();\n                 if (elapsed > time_limit_per_day) break;\n            }\n            temp *= 0.9999;\n\n            int split_to_change = rand_int(0, N - 2);\n            Node* target_node = split_idx_to_node[split_to_change];\n            \n            Rect split_region = {0, 0, W, W};\n            Node* temp_node = target_node;\n            while(temp_node->parent != nullptr) {\n                Node* p = temp_node->parent;\n                int p_coord = split_coords[p->split_idx];\n                if (p->is_vertical_split) {\n                    if (temp_node == p->left) split_region.c1 = min(split_region.c1, p_coord);\n                    else split_region.c0 = max(split_region.c0, p_coord);\n                } else {\n                    if (temp_node == p->left) split_region.r1 = min(split_region.r1, p_coord);\n                    else split_region.r0 = max(split_region.r0, p_coord);\n                }\n                temp_node = p;\n            }\n\n            int old_coord = split_coords[split_to_change];\n            int range_min, range_max;\n            if (target_node->is_vertical_split) {\n                range_min = split_region.c0 + 1; range_max = split_region.c1 - 1;\n            } else {\n                range_min = split_region.r0 + 1; range_max = split_region.r1 - 1;\n            }\n            if (range_min >= range_max) continue;\n\n            int move_range = max(1, (int)((range_max - range_min) * 0.1 * temp / 5000.0));\n            int new_coord = old_coord + rand_int(-move_range, move_range);\n            new_coord = clamp(new_coord, range_min, range_max);\n            \n            if (new_coord == old_coord) continue;\n\n            vector<Rect> new_subtree_rects(N);\n            vector<int> next_coords = split_coords;\n            next_coords[split_to_change] = new_coord;\n\n            std::function<void(Node*, Rect)> compute_subtree_rects = \n                [&](Node* node, Rect region) {\n                    if (node->is_leaf) {\n                        new_subtree_rects[node->k] = region;\n                        return;\n                    }\n                    int coord = next_coords[node->split_idx];\n                    Rect left_region, right_region;\n                    if (node->is_vertical_split) {\n                        left_region = {region.r0, region.c0, region.r1, coord};\n                        right_region = {region.r0, coord, region.r1, region.c1};\n                    } else {\n                        left_region = {region.r0, region.c0, coord, region.c1};\n                        right_region = {coord, region.c0, region.r1, region.c1};\n                    }\n                    compute_subtree_rects(node->left, left_region);\n                    compute_subtree_rects(node->right, right_region);\n            };\n            compute_subtree_rects(target_node, split_region);\n\n            long long area_cost_delta = 0;\n            for(int k=target_node->k_min; k<target_node->k_max; ++k) {\n                area_cost_delta -= 100 * max(0LL, a[d][k] - current_rects[k].area());\n                area_cost_delta += 100 * max(0LL, a[d][k] - new_subtree_rects[k].area());\n            }\n\n            long long partition_cost_delta = 0;\n            if (target_node->is_vertical_split) {\n                for (int i = split_region.r0; i < split_region.r1; ++i) {\n                    partition_cost_delta -= (v_prev_exists[i][old_coord] != (v_curr_count[i][old_coord] > 0));\n                    v_curr_count[i][old_coord]--;\n                    partition_cost_delta += (v_prev_exists[i][old_coord] != (v_curr_count[i][old_coord] > 0));\n                    partition_cost_delta -= (v_prev_exists[i][new_coord] != (v_curr_count[i][new_coord] > 0));\n                    v_curr_count[i][new_coord]++;\n                    partition_cost_delta += (v_prev_exists[i][new_coord] != (v_curr_count[i][new_coord] > 0));\n                }\n            } else {\n                for (int j = split_region.c0; j < split_region.c1; ++j) {\n                    partition_cost_delta -= (h_prev_exists[old_coord][j] != (h_curr_count[old_coord][j] > 0));\n                    h_curr_count[old_coord][j]--;\n                    partition_cost_delta += (h_prev_exists[old_coord][j] != (h_curr_count[old_coord][j] > 0));\n                    partition_cost_delta -= (h_prev_exists[new_coord][j] != (h_curr_count[new_coord][j] > 0));\n                    h_curr_count[new_coord][j]++;\n                    partition_cost_delta += (h_prev_exists[new_coord][j] != (h_curr_count[new_coord][j] > 0));\n                }\n            }\n\n            long long cost_delta = area_cost_delta + partition_cost_delta;\n\n            if (cost_delta < 0 || (temp > 1 && rand_double() < exp(-(double)cost_delta / temp))) {\n                current_total_cost += cost_delta;\n                split_coords[split_to_change] = new_coord;\n                for(int k=target_node->k_min; k<target_node->k_max; ++k) {\n                    current_rects[k] = new_subtree_rects[k];\n                }\n                \n                if (current_total_cost < best_total_cost) {\n                    best_total_cost = current_total_cost;\n                    best_coords = split_coords;\n                }\n            } else { // revert counts\n                if (target_node->is_vertical_split) {\n                    for (int i = split_region.r0; i < split_region.r1; ++i) {\n                        v_curr_count[i][old_coord]++; v_curr_count[i][new_coord]--;\n                    }\n                } else {\n                    for (int j = split_region.c0; j < split_region.c1; ++j) {\n                        h_curr_count[old_coord][j]++; h_curr_count[new_coord][j]--;\n                    }\n                }\n            }\n        }\n        \n        split_coords = best_coords;\n        get_rects_from_coords(root, {0, 0, W, W}, split_coords, current_rects);\n        solution[d] = current_rects;\n        populate_partition_counts(current_rects);\n        update_prev_partitions();\n    }\n\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            const auto& r = solution[d][k];\n            cout << r.r0 << \" \" << r.c0 << \" \" << r.r1 << \" \" << r.c1 << \"\\n\";\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <optional>\n#include <map>\n#include <cmath>\n#include <array>\n\n// --- Constants ---\nconstexpr int N = 9;\nconstexpr int M = 20;\nconstexpr int K = 81;\nconstexpr long long P = 998244353;\nconstexpr int MAX_POS_COORD = N - 3; // 0 to N-3 inclusive\n\n// --- Type Definitions ---\nusing Board = std::vector<std::vector<long long>>;\nusing Stamp = std::vector<std::vector<long long>>;\n\nstruct Operation {\n    int m, p, q;\n};\n\n// --- Global Variables ---\nstd::vector<Stamp> stamps(M, Stamp(3, std::vector<long long>(3)));\nBoard initial_board(N, std::vector<long long>(N));\n\n// --- Randomness ---\nstd::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// --- Timer ---\nstd::chrono::steady_clock::time_point start_time;\n\n// --- Utility Functions ---\nlong long current_time_ms() {\n    return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count();\n}\n\nlong long positive_modulo(long long i, long long n) {\n    return (i % n + n) % n;\n}\n\nBoard apply_operations(const std::vector<Operation>& ops) {\n    Board current_board = initial_board;\n    for (const auto& op : ops) {\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                current_board[op.p + i][op.q + j] += stamps[op.m][i][j];\n            }\n        }\n    }\n    return current_board;\n}\n\nlong long calculate_score(const Board& board) {\n    long long score = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            score += positive_modulo(board[i][j], P);\n        }\n    }\n    return score;\n}\n\n\n// --- Greedy Algorithm ---\nstd::vector<Operation> greedy_solution() {\n    std::vector<Operation> ops;\n    Board current_board = initial_board;\n    \n    for (int k = 0; k < K; ++k) {\n        long long best_delta_score = 0;\n        std::optional<Operation> best_op;\n        \n        for (int m = 0; m < M; ++m) {\n            for (int p = 0; p <= MAX_POS_COORD; ++p) {\n                for (int q = 0; q <= MAX_POS_COORD; ++q) {\n                    long long current_delta_score = 0;\n                    for (int i = 0; i < 3; ++i) {\n                        for (int j = 0; j < 3; ++j) {\n                            long long old_val = current_board[p + i][q + j];\n                            long long new_val = old_val + stamps[m][i][j];\n                            current_delta_score += (new_val % P) - (old_val % P);\n                        }\n                    }\n                    \n                    if (current_delta_score > best_delta_score) {\n                        best_delta_score = current_delta_score;\n                        best_op = {m, p, q};\n                    }\n                }\n            }\n        }\n        \n        if (best_op) {\n            ops.push_back(*best_op);\n            for (int i = 0; i < 3; ++i) {\n                for (int j = 0; j < 3; ++j) {\n                    current_board[best_op->p + i][best_op->q + j] += stamps[best_op->m][i][j];\n                }\n            }\n        } else {\n            break; \n        }\n    }\n    \n    return ops;\n}\n\n// --- Simulated Annealing ---\nvoid simulated_annealing(std::vector<Operation>& solution) {\n    long long time_limit = 1950;\n    \n    Board current_board = apply_operations(solution);\n    long long current_score = calculate_score(current_board);\n    \n    std::vector<Operation> best_solution = solution;\n    long long best_score = current_score;\n    \n    double start_temp = 5e9;\n    double end_temp = 10;\n    \n    std::array<long long, N * N> deltas{};\n    std::vector<int> dirty_keys;\n    dirty_keys.reserve(18);\n\n    while (true) {\n        long long elapsed_time = current_time_ms();\n        if (elapsed_time >= time_limit) {\n            break;\n        }\n        \n        double progress = static_cast<double>(elapsed_time) / time_limit;\n        double temp = start_temp * std::pow(end_temp / start_temp, progress);\n\n        int r = std::uniform_int_distribution<>(0, 99)(rng);\n        int move_type; // 0: change, 1: add, 2: remove\n        int op_count = solution.size();\n\n        if (op_count == K) {\n            if (r < 80) move_type = 0; else move_type = 2;\n        } else if (op_count == 0) {\n            move_type = 1;\n        } else {\n            if (r < 70) move_type = 0;\n            else if (r < 90) move_type = 1;\n            else move_type = 2;\n        }\n        \n        std::optional<Operation> old_op, new_op;\n        int op_idx = -1;\n        \n        if (move_type == 0) { // Change\n            op_idx = std::uniform_int_distribution<int>(0, solution.size() - 1)(rng);\n            old_op = solution[op_idx];\n            \n            int change_type_r = std::uniform_int_distribution<>(0, 99)(rng);\n            if (change_type_r < 45) { // change position\n                Operation candidate = *old_op;\n                do {\n                    candidate.p = std::uniform_int_distribution<int>(0, MAX_POS_COORD)(rng);\n                    candidate.q = std::uniform_int_distribution<int>(0, MAX_POS_COORD)(rng);\n                } while (candidate.p == old_op->p && candidate.q == old_op->q);\n                new_op = candidate;\n            } else if (change_type_r < 90) { // change stamp\n                Operation candidate = *old_op;\n                do {\n                    candidate.m = std::uniform_int_distribution<int>(0, M - 1)(rng);\n                } while (candidate.m == old_op->m);\n                new_op = candidate;\n            } else { // change both\n                new_op = {\n                    std::uniform_int_distribution<int>(0, M - 1)(rng),\n                    std::uniform_int_distribution<int>(0, MAX_POS_COORD)(rng),\n                    std::uniform_int_distribution<int>(0, MAX_POS_COORD)(rng)\n                };\n            }\n        } else if (move_type == 1) { // Add\n            new_op = {\n                std::uniform_int_distribution<int>(0, M - 1)(rng),\n                std::uniform_int_distribution<int>(0, MAX_POS_COORD)(rng),\n                std::uniform_int_distribution<int>(0, MAX_POS_COORD)(rng)\n            };\n        } else { // Remove\n            op_idx = std::uniform_int_distribution<int>(0, solution.size() - 1)(rng);\n            old_op = solution[op_idx];\n        }\n\n        if (old_op) {\n            for (int i = 0; i < 3; ++i) {\n                for (int j = 0; j < 3; ++j) {\n                    int key = (old_op->p + i) * N + old_op->q + j;\n                    if (deltas[key] == 0) dirty_keys.push_back(key);\n                    deltas[key] -= stamps[old_op->m][i][j];\n                }\n            }\n        }\n        if (new_op) {\n            for (int i = 0; i < 3; ++i) {\n                for (int j = 0; j < 3; ++j) {\n                    int key = (new_op->p + i) * N + new_op->q + j;\n                    if (deltas[key] == 0) dirty_keys.push_back(key);\n                    deltas[key] += stamps[new_op->m][i][j];\n                }\n            }\n        }\n        \n        long long delta_score = 0;\n        for (int key : dirty_keys) {\n            long long old_val = current_board[key / N][key % N];\n            long long new_val = old_val + deltas[key];\n            delta_score += positive_modulo(new_val, P) - positive_modulo(old_val, P);\n        }\n        \n        if (delta_score > 0 || std::uniform_real_distribution<>(0.0, 1.0)(rng) < std::exp(static_cast<double>(delta_score) / temp)) {\n            current_score += delta_score;\n            for (int key : dirty_keys) {\n                current_board[key / N][key % N] += deltas[key];\n            }\n            \n            if (move_type == 0) {\n                solution[op_idx] = *new_op;\n            } else if (move_type == 1) {\n                solution.push_back(*new_op);\n            } else {\n                solution.erase(solution.begin() + op_idx);\n            }\n            \n            if (current_score > best_score) {\n                best_score = current_score;\n                best_solution = solution;\n            }\n        }\n        \n        for (int key : dirty_keys) {\n            deltas[key] = 0;\n        }\n        dirty_keys.clear();\n    }\n    \n    solution = best_solution;\n}\n\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    start_time = std::chrono::steady_clock::now();\n    \n    int n_dummy, m_dummy, k_dummy;\n    std::cin >> n_dummy >> m_dummy >> k_dummy;\n    \n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            std::cin >> initial_board[i][j];\n        }\n    }\n    \n    for (int m = 0; m < M; ++m) {\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                std::cin >> stamps[m][i][j];\n            }\n        }\n    }\n    \n    auto solution = greedy_solution();\n    simulated_annealing(solution);\n    \n    std::cout << solution.size() << std::endl;\n    for (const auto& op : solution) {\n        std::cout << op.m << \" \" << op.p << \" \" << op.q << std::endl;\n    }\n    \n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <map>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nconst int N = 5;\nconst int MAX_TURNS = 10000;\n\nstruct Pos {\n    int r, c;\n    bool operator==(const Pos& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Pos& other) const {\n        return !(*this == other);\n    }\n    bool operator<(const Pos& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n};\n\nenum TaskType {\n    NONE,\n    MOVE_TO_PARK,\n    UNLOAD,\n    SORT,\n    DISPATCH\n};\n\nstruct Task {\n    TaskType type = NONE;\n    int container_id = -1;\n    Pos from;\n    Pos to;\n};\n\nstruct Crane {\n    int id;\n    Pos pos;\n    int payload = -1;\n    Task task;\n    bool bombed = false;\n};\n\nint grid[N][N];\nPos container_pos[N * N];\nCrane cranes[N];\nint arrival_idx[N];\nint dispatch_next[N];\nvector<string> history(N);\n\nvoid init() {\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            grid[i][j] = -1;\n        }\n    }\n    for (int i = 0; i < N * N; ++i) {\n        container_pos[i] = {-1, -1};\n    }\n    for (int i = 0; i < N; ++i) {\n        cranes[i].id = i;\n        cranes[i].pos = {i, 0};\n        arrival_idx[i] = 0;\n        dispatch_next[i] = N * i;\n    }\n}\n\nvoid apply_actions(const string& actions) {\n    for (int i = 0; i < N; ++i) {\n        history[i] += actions[i];\n    }\n    \n    // Update payload first\n    for (int i = 0; i < N; ++i) {\n        char act = actions[i];\n        if (act == 'P') {\n            cranes[i].payload = grid[cranes[i].pos.r][cranes[i].pos.c];\n            grid[cranes[i].pos.r][cranes[i].pos.c] = -1;\n        } else if (act == 'Q') {\n            grid[cranes[i].pos.r][cranes[i].pos.c] = cranes[i].payload;\n            container_pos[cranes[i].payload] = cranes[i].pos;\n            cranes[i].payload = -1;\n        } else if (act == 'B') {\n            cranes[i].bombed = true;\n        }\n    }\n\n    // Update positions\n    for (int i = 0; i < N; ++i) {\n        char act = actions[i];\n        if (act == 'U') cranes[i].pos.r--;\n        else if (act == 'D') cranes[i].pos.r++;\n        else if (act == 'L') cranes[i].pos.c--;\n        else if (act == 'R') cranes[i].pos.c++;\n    }\n}\n\nPos get_next_pos(Pos current, char action) {\n    if (action == 'U') return {current.r - 1, current.c};\n    if (action == 'D') return {current.r + 1, current.c};\n    if (action == 'L') return {current.r, current.c - 1};\n    if (action == 'R') return {current.r, current.c + 1};\n    return current;\n}\n\nchar get_move_action(Pos from, Pos to) {\n    if (from.r < to.r) return 'D';\n    if (from.r > to.r) return 'U';\n    if (from.c < to.c) return 'R';\n    if (from.c > to.c) return 'L';\n    return '.';\n}\n\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n_dummy;\n    cin >> n_dummy;\n    vector<vector<int>> A(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> A[i][j];\n        }\n    }\n\n    init();\n\n    int dispatched_count = 0;\n\n    for (int t = 0; t < MAX_TURNS; ++t) {\n        if (dispatched_count == N * N) break;\n\n        // 1. Containers arrive\n        for (int i = 0; i < N; ++i) {\n            if (arrival_idx[i] < N && grid[i][0] == -1) {\n                int new_container = A[i][arrival_idx[i]];\n                grid[i][0] = new_container;\n                container_pos[new_container] = {i, 0};\n                arrival_idx[i]++;\n            }\n        }\n\n        // 2. Crane actions\n        \n        // Task assignment\n        for (int i = 0; i < N; ++i) {\n            if (cranes[i].task.type != NONE && cranes[i].payload == -1 && container_pos[cranes[i].task.container_id].r == -1) {\n                 cranes[i].task.type = NONE;\n            }\n            if (cranes[i].task.type == NONE) {\n                if (i == 0) { // Large crane\n                    int c_to_dispatch = dispatch_next[0];\n                    if (c_to_dispatch < N && grid[0][N - 1] == -1 && container_pos[c_to_dispatch].r != -1) {\n                        Pos c_pos = container_pos[c_to_dispatch];\n                        if(c_pos.r == 0 && c_pos.c == 3) {\n                           cranes[i].task = {DISPATCH, c_to_dispatch, c_pos, {0, N - 1}};\n                        }\n                    }\n                    if (cranes[i].task.type == NONE) {\n                        for (int r = 0; r < N; ++r) {\n                            if (grid[r][0] != -1 && grid[r][1] == -1) {\n                                int c = grid[r][0];\n                                cranes[i].task = {UNLOAD, c, {r, 0}, {r, 1}};\n                                break;\n                            }\n                        }\n                    }\n                    if (cranes[i].task.type == NONE) {\n                        for (int r = 0; r < N; ++r) {\n                            if (grid[r][1] != -1) {\n                                int c = grid[r][1];\n                                int dest_r = c / N;\n                                if (grid[dest_r][3] == -1) {\n                                    cranes[i].task = {SORT, c, {r, 1}, {dest_r, 3}};\n                                    break;\n                                }\n                            }\n                        }\n                    }\n                } else { // Small cranes\n                    int c_to_dispatch = dispatch_next[i];\n                    if (c_to_dispatch < N * (i + 1) && grid[i][N - 1] == -1 && container_pos[c_to_dispatch].r != -1) {\n                        Pos c_pos = container_pos[c_to_dispatch];\n                        if (c_pos.r == i && c_pos.c == 3) {\n                           cranes[i].task = {DISPATCH, c_to_dispatch, c_pos, {i, N-1}};\n                        }\n                    }\n                    if (cranes[i].task.type == NONE) {\n                        if (cranes[i].pos != Pos{i, 2}) {\n                           cranes[i].task.type = MOVE_TO_PARK;\n                           cranes[i].task.to = {i,2};\n                        }\n                    }\n                }\n            }\n        }\n        \n        string actions(N, '.');\n        vector<Pos> next_pos(N);\n        for(int i=0; i<N; ++i) next_pos[i] = cranes[i].pos;\n        \n        for(int iter=0; iter<5; ++iter) { // Iteratively resolve conflicts\n            vector<Pos> current_next_pos(N);\n            for(int i=0; i<N; ++i) current_next_pos[i] = get_next_pos(cranes[i].pos, actions[i]);\n\n            string planned_actions = actions;\n\n            // --- Action planning for each crane, considering current state of others ---\n            for (int k = 0; k < N; ++k) {\n                if(cranes[k].bombed) { planned_actions[k] = '.'; continue;}\n\n                char best_action = '.';\n                Task& task = cranes[k].task;\n\n                if (t < 2 && k > 0) {\n                    best_action = 'R';\n                } else if (task.type != NONE) {\n                    if (cranes[k].payload != -1) {\n                        if (cranes[k].pos == task.to) {\n                            best_action = 'Q';\n                            task.type = NONE; \n                        } else {\n                            Pos target = task.to;\n                            if (k == 0 && cranes[k].pos.c != 1 && cranes[k].pos.c != target.c) {\n                                target = {cranes[k].pos.r, 1};\n                            } else if (k == 0 && cranes[k].pos.c == 1 && cranes[k].pos.r != target.r) {\n                                target = {target.r, 1};\n                            }\n                            best_action = get_move_action(cranes[k].pos, target);\n                        }\n                    } else {\n                        if (task.type == MOVE_TO_PARK) {\n                             if (cranes[k].pos == task.to) {\n                                task.type = NONE;\n                                best_action = '.';\n                             } else {\n                                best_action = get_move_action(cranes[k].pos, task.to);\n                             }\n                        } else if (cranes[k].pos == task.from) {\n                            if (grid[task.from.r][task.from.c] == task.container_id){\n                               best_action = 'P';\n                            } else {\n                               task.type = NONE;\n                            }\n                        } else {\n                            Pos target = task.from;\n                            if (k == 0 && cranes[k].pos.c != 1 && cranes[k].pos.c != target.c) {\n                                target = {cranes[k].pos.r, 1};\n                            } else if (k == 0 && cranes[k].pos.c == 1 && cranes[k].pos.r != target.r) {\n                                target = {target.r, 1};\n                            }\n                            best_action = get_move_action(cranes[k].pos, target);\n                        }\n                    }\n                }\n                planned_actions[k] = best_action;\n            }\n\n            // --- Conflict resolution with priorities ---\n            actions = planned_actions;\n            for(int i=0; i<N; ++i) next_pos[i] = get_next_pos(cranes[i].pos, actions[i]);\n            \n            // Evasion\n            Pos np0 = next_pos[0];\n            for (int j=1; j<N; ++j) {\n                if (np0 == cranes[j].pos && cranes[j].pos == next_pos[j]) { // Crane 0 wants to move into stationary Crane j\n                    // j must evade\n                    char original_action_j = actions[j];\n                    actions[j] = '.';\n                    Pos evade_targets[] = {{cranes[j].pos.r, 1}, {cranes[j].pos.r - 1, 2}, {cranes[j].pos.r + 1, 2}};\n                    for(const Pos& evade_pos : evade_targets) {\n                        if (evade_pos.r < 0 || evade_pos.r >= N || evade_pos.c < 0 || evade_pos.c >= N) continue;\n                        \n                        bool pos_ok = true;\n                        if (evade_pos == np0) pos_ok = false;\n                        for(int k=0; k<N; ++k) if(k!=j && evade_pos == cranes[k].pos) pos_ok = false;\n                        \n                        if(pos_ok) {\n                            actions[j] = get_move_action(cranes[j].pos, evade_pos);\n                            break;\n                        }\n                    }\n                    if (actions[j] == '.') { // could not evade\n                        actions[0] = '.'; // crane 0 waits\n                        actions[j] = original_action_j;\n                    }\n                }\n            }\n\n            for(int i=0; i<N; ++i) next_pos[i] = get_next_pos(cranes[i].pos, actions[i]);\n\n            // General collision\n            for (int i = 0; i < N; ++i) {\n                for (int j = i + 1; j < N; ++j) {\n                    if (next_pos[i] == next_pos[j] || (next_pos[i] == cranes[j].pos && next_pos[j] == cranes[i].pos)) {\n                        actions[j] = '.';\n                        next_pos[j] = cranes[j].pos;\n                    }\n                }\n            }\n\n            // Small crane payload constraints\n            for(int i=1; i<N; ++i) {\n                if (cranes[i].payload != -1) {\n                    Pos np = get_next_pos(cranes[i].pos, actions[i]);\n                    if (np.r < 0 || np.r >= N || np.c < 0 || np.c >= N) {\n                        actions[i] = '.';\n                        continue;\n                    }\n                    for(int c=0; c<N*N; ++c) {\n                        if (container_pos[c] == np) {\n                            actions[i] = '.';\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n\n        // Bomb cranes whose jobs are done\n        for(int i=1; i<N; ++i){\n            if(dispatch_next[i] >= N*(i+1) && cranes[i].payload == -1 && !cranes[i].bombed) {\n                actions[i] = 'B';\n            }\n        }\n        \n        apply_actions(actions);\n        \n        // 3. Containers are dispatched\n        for (int i = 0; i < N; ++i) {\n            if (grid[i][N - 1] != -1) {\n                int dispatched_container = grid[i][N - 1];\n                if (dispatched_container / N == i) {\n                    if (dispatch_next[i] == dispatched_container)\n                        dispatch_next[i]++;\n                }\n                grid[i][N - 1] = -1;\n                container_pos[dispatched_container] = {-1, -1};\n                dispatched_count++;\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << history[i] << endl;\n    }\n\n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <cmath>\n#include <map>\n#include <algorithm>\n#include <chrono>\n#include <random>\n\n#include <atcoder/mincostflow>\n\nusing namespace std;\n\n// --- Utilities ---\nstruct XorShift {\n    unsigned int x, y, z, w;\n    XorShift() : x(123456789), y(362436069), z(521288629), w(88675123) {}\n    unsigned int next() {\n        unsigned int t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));\n    }\n    int next_int(int upper) { return next() % upper; }\n    int next_int(int lower, int upper) { return lower + next() % (upper - lower + 1); }\n    double next_double() { return next() / 4294967295.0; }\n};\nXorShift rnd;\n\nauto start_time = chrono::steady_clock::now();\ndouble time_limit = 1.95;\n\nbool is_time_up() {\n    auto now = chrono::steady_clock::now();\n    double elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count() / 1000.0;\n    return elapsed > time_limit;\n}\n\n// --- Problem specific structures ---\nconst int N = 20;\n\nstruct Pos {\n    int r, c;\n};\n\nint manhattan_dist(const Pos& p1, const Pos& p2) {\n    return abs(p1.r - p2.r) + abs(p1.c - p2.c);\n}\n\nvector<Pos> sources, sinks;\nvector<int> source_supply, sink_demand;\n\nusing Plan = vector<vector<int>>;\n\n// --- Core Logic ---\n\nlong long calculate_tour_cost(Pos start_pos, int initial_load, const vector<pair<int, int>>& tour, vector<string>* ops = nullptr) {\n    long long cost = 0;\n    Pos current_pos = start_pos;\n    int truck_load = initial_load;\n\n    for (const auto& stop : tour) {\n        int t_idx = stop.first;\n        int amount = stop.second;\n        Pos t_pos = sinks[t_idx];\n        \n        int dist = manhattan_dist(current_pos, t_pos);\n        cost += (long long)dist * (100 + truck_load);\n\n        if (ops) {\n            int dr = t_pos.r - current_pos.r;\n            int dc = t_pos.c - current_pos.c;\n            if (dr > 0) for(int i=0; i<dr; ++i) ops->push_back(\"D\");\n            if (dr < 0) for(int i=0; i<-dr; ++i) ops->push_back(\"U\");\n            if (dc > 0) for(int i=0; i<dc; ++i) ops->push_back(\"R\");\n            if (dc < 0) for(int i=0; i<-dc; ++i) ops->push_back(\"L\");\n\n            ops->push_back(\"-\" + to_string(amount));\n        }\n\n        cost += amount;\n        truck_load -= amount;\n        current_pos = t_pos;\n    }\n    return cost;\n}\n\nvoid optimize_tour(Pos start_pos, vector<pair<int, int>>& tour) {\n    if (tour.size() <= 1) return;\n\n    auto get_tour_dist = [&](const vector<pair<int, int>>& current_tour) {\n        long long d = 0;\n        Pos current_pos = start_pos;\n        for (const auto& stop : current_tour) {\n            d += manhattan_dist(current_pos, sinks[stop.first]);\n            current_pos = sinks[stop.first];\n        }\n        return d;\n    };\n\n    for(int iter = 0; iter < 2 * tour.size() * tour.size() && iter < 200; ++iter) {\n        int i = rnd.next_int(tour.size());\n        int j = rnd.next_int(tour.size());\n        if (i == j) continue;\n        if (i > j) swap(i, j);\n\n        vector<pair<int, int>> next_tour = tour;\n        reverse(next_tour.begin() + i, next_tour.begin() + j + 1);\n\n        if (get_tour_dist(next_tour) < get_tour_dist(tour)) {\n            tour = next_tour;\n        }\n    }\n}\n\nlong long evaluate(const Plan& plan, vector<string>* ops = nullptr) {\n    if (ops) ops->clear();\n    long long total_cost = 0;\n    Pos current_pos = {0, 0};\n\n    map<int, vector<pair<int, int>>> deliveries_by_source;\n    for (size_t s_idx = 0; s_idx < sources.size(); ++s_idx) {\n        for (size_t t_idx = 0; t_idx < sinks.size(); ++t_idx) {\n            if (plan[s_idx][t_idx] > 0) {\n                deliveries_by_source[s_idx].push_back({(int)t_idx, plan[s_idx][t_idx]});\n            }\n        }\n    }\n\n    vector<int> active_sources_indices;\n    for (const auto& [s_idx, v] : deliveries_by_source) {\n        active_sources_indices.push_back(s_idx);\n    }\n    \n    while (!active_sources_indices.empty()) {\n        int best_s_idx = -1;\n        int min_dist = 1e9;\n        size_t best_vec_idx = -1;\n\n        for (size_t i = 0; i < active_sources_indices.size(); ++i) {\n            int s_idx = active_sources_indices[i];\n            int d = manhattan_dist(current_pos, sources[s_idx]);\n            if (d < min_dist) {\n                min_dist = d;\n                best_s_idx = s_idx;\n                best_vec_idx = i;\n            }\n        }\n        \n        Pos s_pos = sources[best_s_idx];\n        total_cost += (long long)manhattan_dist(current_pos, s_pos) * 100;\n        \n        if (ops) {\n            int dr = s_pos.r - current_pos.r;\n            int dc = s_pos.c - current_pos.c;\n            if (dr > 0) for(int i=0; i<dr; ++i) ops->push_back(\"D\");\n            if (dr < 0) for(int i=0; i<-dr; ++i) ops->push_back(\"U\");\n            if (dc > 0) for(int i=0; i<dc; ++i) ops->push_back(\"R\");\n            if (dc < 0) for(int i=0; i<-dc; ++i) ops->push_back(\"L\");\n        }\n        current_pos = s_pos;\n\n        int total_load_amount = 0;\n        vector<pair<int, int>> tour_stops; // {t_idx, amount}\n        for (const auto& delivery : deliveries_by_source[best_s_idx]) {\n            total_load_amount += delivery.second;\n            tour_stops.push_back(delivery);\n        }\n\n        total_cost += total_load_amount;\n        if (ops && total_load_amount > 0) {\n            ops->push_back(\"+\" + to_string(total_load_amount));\n        }\n        \n        Pos tour_start_pos = current_pos;\n        vector<pair<int, int>> tour;\n        while (!tour_stops.empty()) {\n            auto best_it = tour_stops.end();\n            int min_dist_t = 1e9;\n            for (auto it = tour_stops.begin(); it != tour_stops.end(); ++it) {\n                int t_idx = it->first;\n                int d = manhattan_dist(current_pos, sinks[t_idx]);\n                if (d < min_dist_t) {\n                    min_dist_t = d;\n                    best_it = it;\n                }\n            }\n            tour.push_back(*best_it);\n            current_pos = sinks[best_it->first];\n            tour_stops.erase(best_it);\n        }\n\n        optimize_tour(tour_start_pos, tour);\n\n        total_cost += calculate_tour_cost(tour_start_pos, total_load_amount, tour, ops);\n        if (!tour.empty()) {\n            current_pos = sinks[tour.back().first];\n        }\n\n        active_sources_indices.erase(active_sources_indices.begin() + best_vec_idx);\n    }\n    return total_cost;\n}\n\nvoid solve() {\n    vector<vector<int>> h(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> h[i][j];\n            if (h[i][j] > 0) {\n                sources.push_back({i, j});\n                source_supply.push_back(h[i][j]);\n            } else if (h[i][j] < 0) {\n                sinks.push_back({i, j});\n                sink_demand.push_back(-h[i][j]);\n            }\n        }\n    }\n    \n    if (sources.empty()) return;\n\n    int num_s = sources.size();\n    int num_t = sinks.size();\n    atcoder::mcf_graph<int, int> g(num_s + num_t + 2);\n    int S_node = num_s + num_t;\n    int T_node = S_node + 1;\n\n    long long total_supply_val = 0;\n    for (int i = 0; i < num_s; ++i) {\n        g.add_edge(S_node, i, source_supply[i], 0);\n        total_supply_val += source_supply[i];\n    }\n    for (int i = 0; i < num_t; ++i) {\n        g.add_edge(num_s + i, T_node, sink_demand[i], 0);\n    }\n    for (int i = 0; i < num_s; ++i) {\n        for (int j = 0; j < num_t; ++j) {\n            g.add_edge(i, num_s + j, 1e9, manhattan_dist(sources[i], sinks[j]));\n        }\n    }\n    \n    g.flow(S_node, T_node, total_supply_val);\n    \n    Plan current_plan(num_s, vector<int>(num_t, 0));\n    for (const auto& e : g.edges()) {\n        if (e.from >= 0 && e.from < num_s && e.to >= num_s && e.to < num_s + num_t) {\n            if (e.flow > 0) {\n                current_plan[e.from][e.to-num_s] = e.flow;\n            }\n        }\n    }\n\n    Plan best_plan = current_plan;\n    long long best_cost = evaluate(best_plan);\n    long long current_cost = best_cost;\n    \n    double start_temp = 5000, end_temp = 10;\n    \n    while (!is_time_up()) {\n        double elapsed_ratio = chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count() / 1000.0 / time_limit;\n        double temp = start_temp * pow(end_temp / start_temp, elapsed_ratio);\n\n        int s1 = rnd.next_int(num_s);\n        int s2 = rnd.next_int(num_s);\n        int t1 = rnd.next_int(num_t);\n        int t2 = rnd.next_int(num_t);\n\n        if (s1 == s2 || t1 == t2) continue;\n        \n        int amount1 = current_plan[s1][t1];\n        int amount2 = current_plan[s2][t2];\n        if (amount1 == 0 || amount2 == 0) continue;\n        \n        int d = rnd.next_int(1, min(amount1, amount2));\n        \n        Plan new_plan = current_plan;\n        new_plan[s1][t1] -= d;\n        new_plan[s2][t2] -= d;\n        new_plan[s1][t2] += d;\n        new_plan[s2][t1] += d;\n\n        long long new_cost = evaluate(new_plan);\n        \n        if (new_cost < current_cost || rnd.next_double() < exp((double)(current_cost - new_cost) / temp)) {\n            current_plan = new_plan;\n            current_cost = new_cost;\n            if (current_cost < best_cost) {\n                best_cost = current_cost;\n                best_plan = current_plan;\n            }\n        }\n    }\n    \n    vector<string> ops;\n    evaluate(best_plan, &ops);\n    for (const auto& op : ops) {\n        cout << op << '\\n';\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    int N_dummy;\n    cin >> N_dummy;\n    solve();\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n#include <random>\n#include <unordered_set>\n\n// --- Constants ---\nconstexpr int N = 6;\nconstexpr int M = 15;\nconstexpr int T = 10;\nconstexpr int SEED_COUNT = 2 * N * (N - 1); // 60\nconstexpr int GRID_SIZE = N * N;             // 36\nconstexpr long long TIME_LIMIT_MS = 190;\nconstexpr int TOP_K_SELECTION = 3; // Consider top K seeds for each criterion\n\n// --- Type Definitions ---\nstruct Seed {\n    int id;\n    std::vector<int> x;\n    int total_value;\n};\n\n// --- Global State ---\nstd::vector<Seed> current_seeds;\nstd::mt19937 rng;\nauto turn_start_time = std::chrono::high_resolution_clock::now();\n\n// --- Helper Functions ---\nvoid read_seeds() {\n    current_seeds.assign(SEED_COUNT, Seed());\n    for (int i = 0; i < SEED_COUNT; ++i) {\n        current_seeds[i].id = i;\n        current_seeds[i].x.resize(M);\n        current_seeds[i].total_value = 0;\n        for (int j = 0; j < M; ++j) {\n            std::cin >> current_seeds[i].x[j];\n            current_seeds[i].total_value += current_seeds[i].x[j];\n        }\n    }\n}\n\n// --- Core Logic for a Single Turn ---\nvoid solve_turn() {\n    // 1. REFINED SEED SELECTION: \"Top-K\" strategy\n    // This strategy selects seeds based on how many times they appear in the\n    // top K for any criterion. This prioritizes seeds that are champions or\n    // strong contenders in one or more areas, increasing the chance of\n    // combining multiple high-value traits.\n    \n    std::vector<int> top_K_counts(SEED_COUNT, 0);\n    std::vector<std::pair<int, int>> ranked_seeds(SEED_COUNT);\n\n    for (int j = 0; j < M; ++j) {\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            ranked_seeds[i] = {current_seeds[i].x[j], i};\n        }\n        std::sort(ranked_seeds.rbegin(), ranked_seeds.rend());\n        \n        for (int k = 0; k < TOP_K_SELECTION; ++k) {\n            top_K_counts[ranked_seeds[k].second]++;\n        }\n    }\n\n    std::vector<int> all_indices(SEED_COUNT);\n    std::iota(all_indices.begin(), all_indices.end(), 0);\n\n    // Sort all seeds by their top-K appearance count, then by total value as a tie-breaker.\n    std::sort(all_indices.begin(), all_indices.end(), [&](int a, int b) {\n        if (top_K_counts[a] != top_K_counts[b]) {\n            return top_K_counts[a] > top_K_counts[b];\n        }\n        return current_seeds[a].total_value > current_seeds[b].total_value;\n    });\n\n    std::vector<int> seeds_to_plant_indices;\n    seeds_to_plant_indices.reserve(GRID_SIZE);\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        seeds_to_plant_indices.push_back(all_indices[i]);\n    }\n\n    // 2. PLACEMENT using SIMULATED ANNEALING\n    \n    // Pre-calculate desirability for all pairs of selected seeds.\n    std::vector<std::vector<double>> desirability_cache(GRID_SIZE, std::vector<double>(GRID_SIZE));\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = i; j < GRID_SIZE; ++j) {\n            int seed_idx1 = seeds_to_plant_indices[i];\n            int seed_idx2 = seeds_to_plant_indices[j];\n            double d = 0;\n            for (int k = 0; k < M; ++k) {\n                d += std::max(current_seeds[seed_idx1].x[k], current_seeds[seed_idx2].x[k]);\n            }\n            desirability_cache[i][j] = desirability_cache[j][i] = d;\n        }\n    }\n\n    // Initialize with a random placement.\n    std::vector<int> p_indices(GRID_SIZE);\n    std::iota(p_indices.begin(), p_indices.end(), 0);\n    std::shuffle(p_indices.begin(), p_indices.end(), rng);\n\n    std::vector<std::vector<int>> current_placement(N, std::vector<int>(N));\n    for(int i = 0; i < GRID_SIZE; ++i) {\n        current_placement[i/N][i%N] = p_indices[i];\n    }\n    \n    auto calculate_total_desirability = [&](const auto& placement) {\n        double total_d = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (i + 1 < N) total_d += desirability_cache[placement[i][j]][placement[i + 1][j]];\n                if (j + 1 < N) total_d += desirability_cache[placement[i][j]][placement[i][j + 1]];\n            }\n        }\n        return total_d;\n    };\n    \n    double current_desirability = calculate_total_desirability(current_placement);\n    auto best_placement = current_placement;\n    double best_desirability = current_desirability;\n    \n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n\n    // Fast delta calculation for a swap move.\n    auto calculate_delta = [&](int r1, int c1, int r2, int c2) {\n        double delta = 0;\n        int s1_idx = current_placement[r1][c1];\n        int s2_idx = current_placement[r2][c2];\n\n        for (int k=0; k<4; ++k) {\n            int nr = r1 + dr[k], nc = c1 + dc[k];\n            if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n            if (nr == r2 && nc == c2) continue;\n            int neighbor_idx = current_placement[nr][nc];\n            delta += desirability_cache[s2_idx][neighbor_idx] - desirability_cache[s1_idx][neighbor_idx];\n        }\n        for (int k=0; k<4; ++k) {\n            int nr = r2 + dr[k], nc = c2 + dc[k];\n            if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n            if (nr == r1 && nc == c1) continue;\n            int neighbor_idx = current_placement[nr][nc];\n            delta += desirability_cache[s1_idx][neighbor_idx] - desirability_cache[s2_idx][neighbor_idx];\n        }\n        return delta;\n    };\n\n    // Auto-tune starting temperature.\n    double T_start = 2000.0, T_end = 0.1;\n    double avg_bad_delta = 0;\n    int bad_move_count = 0;\n    std::uniform_int_distribution<> dis_pos(0, GRID_SIZE - 1);\n    for (int i = 0; i < 500; ++i) { // Increased samples for better tuning\n        int p1_idx = dis_pos(rng), p2_idx = dis_pos(rng);\n        if (p1_idx == p2_idx) continue;\n        double delta = calculate_delta(p1_idx / N, p1_idx % N, p2_idx / N, p2_idx % N);\n        if (delta < 0) {\n            avg_bad_delta += -delta;\n            bad_move_count++;\n        }\n    }\n    if (bad_move_count > 0) {\n        avg_bad_delta /= bad_move_count;\n        T_start = avg_bad_delta / log(2.0);\n    }\n\n    std::uniform_real_distribution<double> accept_dis(0.0, 1.0);\n    int iter_count = 0;\n    while (true) {\n        iter_count++;\n        if (iter_count % 1024 == 0) {\n            if (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - turn_start_time).count() > TIME_LIMIT_MS) break;\n        }\n\n        double progress = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - turn_start_time).count() / (double)TIME_LIMIT_MS;\n        if (progress >= 1.0) break;\n        double temp = T_start * std::pow(T_end / T_start, progress);\n\n        int p1_idx = dis_pos(rng), p2_idx = dis_pos(rng);\n        if (p1_idx == p2_idx) continue;\n\n        int r1 = p1_idx / N, c1 = p1_idx % N;\n        int r2 = p2_idx / N, c2 = p2_idx % N;\n        \n        double delta_desirability = calculate_delta(r1, c1, r2, c2);\n        \n        if (delta_desirability > 0 || (temp > 1e-9 && accept_dis(rng) < std::exp(delta_desirability / temp))) {\n            std::swap(current_placement[r1][c1], current_placement[r2][c2]);\n            current_desirability += delta_desirability;\n            if (current_desirability > best_desirability) {\n                best_desirability = current_desirability;\n                best_placement = current_placement;\n            }\n        }\n    }\n\n    // 3. OUTPUT the best placement found.\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int placement_idx = best_placement[i][j];\n            int seed_id_to_print = seeds_to_plant_indices[placement_idx];\n            std::cout << seed_id_to_print << (j == N - 1 ? \"\" : \" \");\n        }\n        std::cout << std::endl;\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    rng.seed(std::chrono::steady_clock::now().time_since_epoch().count());\n    \n    int n_in, m_in, t_in;\n    std::cin >> n_in >> m_in >> t_in;\n\n    read_seeds();\n\n    for (int t = 0; t < T; ++t) {\n        turn_start_time = std::chrono::high_resolution_clock::now();\n        solve_turn();\n        if (t < T - 1) {\n            read_seeds();\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <set>\n#include <map>\n#include <tuple>\n#include <chrono>\n\n#include <atcoder/mincostflow>\n\nusing namespace std;\n\n// --- Utilities ---\nstruct Timer {\n    chrono::steady_clock::time_point start_time;\n    Timer() {\n        start_time = chrono::steady_clock::now();\n    }\n    double get_elapsed_time() const {\n        auto end_time = chrono::steady_clock::now();\n        return chrono::duration_cast<chrono::duration<double>>(end_time - start_time).count();\n    }\n};\n\nstruct Point {\n    int r, c;\n    bool operator<(const Point& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n    bool operator==(const Point& other) const {\n        return r == other.r && c == other.c;\n    }\n};\n\nPoint operator+(const Point& a, const Point& b) { return {a.r + b.r, a.c + b.c}; }\nPoint operator-(const Point& a, const Point& b) { return {a.r - b.r, a.c - b.c}; }\nPoint operator*(const Point& p, int scalar) { return {p.r * scalar, p.c * scalar}; }\nint manhattan(const Point& a, const Point& b) { return abs(a.r - b.r) + abs(a.c - b.c); }\n\n// Global constants for directions\nconst Point DIRS[] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; // 0:U, 1:R, 2:D, 3:L\nconst char MOVE_CHARS[] = {'U', 'R', 'D', 'L'};\nconst Point REL_DIRS[] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; // 0:R, 1:D, 2:L, 3:U\n\nint N, M, V;\n\n// --- Arm Structure ---\nstruct Arm {\n    int v_count;\n    Point root_pos;\n    vector<int> parent;\n    vector<int> length;\n    vector<vector<int>> children;\n    vector<int> is_leaf;\n\n    vector<int> edge_dir;\n    vector<Point> abs_pos;\n    \n    vector<int> finger_indices;\n\n    Arm(int v, Point root, const vector<pair<int, int>>& edges) : v_count(v), root_pos(root) {\n        parent.assign(v, -1);\n        length.assign(v, 0);\n        children.assign(v, vector<int>());\n        edge_dir.assign(v, 0); // All edges point right initially\n        abs_pos.resize(v);\n        is_leaf.assign(v, 0);\n\n        for(int i = 1; i < v; ++i) {\n            parent[i] = edges[i-1].first;\n            length[i] = edges[i-1].second;\n            children[parent[i]].push_back(i);\n        }\n\n        for (int i = 0; i < v; ++i) {\n            if (children[i].empty()) {\n                is_leaf[i] = 1;\n                finger_indices.push_back(i);\n            }\n        }\n        update_abs_pos();\n    }\n\n    void update_abs_pos() {\n        abs_pos.resize(v_count);\n        abs_pos[0] = root_pos;\n        vector<int> q;\n        q.push_back(0);\n        int q_ptr = 0;\n        while(q_ptr < (int)q.size()){\n            int u = q[q_ptr++];\n            for(int v : children[u]){\n                Point rel = REL_DIRS[edge_dir[v]] * length[v];\n                abs_pos[v] = abs_pos[u] + rel;\n                q.push_back(v);\n            }\n        }\n    }\n    \n    void apply_command(const string& cmd) {\n        if (cmd[0] == 'U') root_pos.r--;\n        else if (cmd[0] == 'D') root_pos.r++;\n        else if (cmd[0] == 'L') root_pos.c--;\n        else if (cmd[0] == 'R') root_pos.c++;\n\n        for (int i = 1; i < v_count; ++i) {\n            if (cmd[i] == 'L') edge_dir[i] = (edge_dir[i] + 3) % 4;\n            else if (cmd[i] == 'R') edge_dir[i] = (edge_dir[i] + 1) % 4;\n        }\n        update_abs_pos();\n    }\n};\n\n// --- Game State ---\nstruct GameState {\n    Arm arm;\n    set<Point> sources_left;\n    set<Point> targets_to_fill;\n    map<int, Point> held_by_finger; // finger_idx -> original_source_pos\n    map<Point, Point> s_to_t_map;\n\n    GameState(Arm a, set<Point> s, set<Point> t, map<Point, Point> st_map)\n        : arm(a), sources_left(s), targets_to_fill(t), s_to_t_map(st_map) {}\n};\n\nstruct TargetConfig {\n    bool is_pickup;\n    Point root_pos;\n    vector<int> edge_dirs;\n    map<int, Point> finger_assignments;\n    double value = -1e18;\n};\n\n// --- Planning Functions ---\nTargetConfig find_best_config(const GameState& state, bool is_pickup, const Timer& timer, double time_limit) {\n    TargetConfig best_config;\n    best_config.is_pickup = is_pickup;\n\n    vector<int> available_fingers;\n    if (is_pickup) {\n        for (int f_idx : state.arm.finger_indices) {\n            if (state.held_by_finger.find(f_idx) == state.held_by_finger.end()) {\n                available_fingers.push_back(f_idx);\n            }\n        }\n        if (available_fingers.empty() || state.sources_left.empty()) return best_config;\n\n        const int K_ANCHORS = 30;\n        vector<Point> anchor_candidates;\n        if (state.sources_left.size() <= K_ANCHORS) {\n            anchor_candidates.assign(state.sources_left.begin(), state.sources_left.end());\n        } else {\n            vector<pair<int, Point>> sorted_sources;\n            sorted_sources.reserve(state.sources_left.size());\n            for (const auto& s : state.sources_left) {\n                sorted_sources.push_back({manhattan(state.arm.root_pos, s), s});\n            }\n            std::partial_sort(sorted_sources.begin(), sorted_sources.begin() + K_ANCHORS, sorted_sources.end());\n            anchor_candidates.reserve(K_ANCHORS);\n            for (int i = 0; i < K_ANCHORS; ++i) {\n                anchor_candidates.push_back(sorted_sources[i].second);\n            }\n        }\n\n        for (const Point& p_anchor : anchor_candidates) {\n            if (timer.get_elapsed_time() > time_limit) break;\n            for (int f_anchor_idx : available_fingers) {\n                if (state.arm.parent[f_anchor_idx] != 0) continue;\n                for (int dir = 0; dir < 4; ++dir) {\n                    Point root_rel = REL_DIRS[dir] * state.arm.length[f_anchor_idx];\n                    Point cand_root_pos = p_anchor - root_rel;\n\n                    map<int, Point> assignments;\n                    vector<int> cand_dirs(state.arm.v_count, 0);\n                    \n                    set<Point> remaining_sources = state.sources_left;\n                    \n                    int current_score = 0;\n\n                    for(int f_idx : available_fingers) {\n                        for(int f_dir = 0; f_dir < 4; ++f_dir) {\n                            Point f_rel = REL_DIRS[f_dir] * state.arm.length[f_idx];\n                            Point f_pos = cand_root_pos + f_rel;\n                            if (remaining_sources.count(f_pos)) {\n                                assignments[f_idx] = f_pos;\n                                cand_dirs[f_idx] = f_dir;\n                                remaining_sources.erase(f_pos);\n                                current_score++;\n                                break;\n                            }\n                        }\n                    }\n\n                    int dist_cost = manhattan(state.arm.root_pos, cand_root_pos);\n                    double value = current_score * 400.0 - dist_cost;\n\n                    if (value > best_config.value) {\n                        best_config.value = value;\n                        best_config.root_pos = cand_root_pos;\n                        best_config.edge_dirs = cand_dirs;\n                        best_config.finger_assignments = assignments;\n                    }\n                }\n            }\n        }\n    } else { // dropoff\n        map<int, Point> finger_to_dest;\n        for (const auto& [f_idx, s_pos] : state.held_by_finger) {\n            available_fingers.push_back(f_idx);\n            finger_to_dest[f_idx] = state.s_to_t_map.at(s_pos);\n        }\n        if (available_fingers.empty()) return best_config;\n        \n        for (int f_anchor_idx : available_fingers) {\n            if (timer.get_elapsed_time() > time_limit) break;\n            const Point& p_anchor = finger_to_dest.at(f_anchor_idx);\n            if (state.arm.parent[f_anchor_idx] != 0) continue;\n\n            for (int dir = 0; dir < 4; ++dir) {\n                Point root_rel = REL_DIRS[dir] * state.arm.length[f_anchor_idx];\n                Point cand_root_pos = p_anchor - root_rel;\n\n                vector<int> cand_dirs(state.arm.v_count, 0);\n                map<int, Point> assignments;\n                \n                int current_score = 0;\n                for(auto const& [f_idx, dest_pos] : finger_to_dest) {\n                    for (int f_dir = 0; f_dir < 4; ++f_dir) {\n                        Point f_rel = REL_DIRS[f_dir] * state.arm.length[f_idx];\n                        if (cand_root_pos + f_rel == dest_pos) {\n                            cand_dirs[f_idx] = f_dir;\n                            assignments[f_idx] = dest_pos;\n                            current_score++;\n                            break;\n                        }\n                    }\n                }\n\n                int dist_cost = manhattan(state.arm.root_pos, cand_root_pos);\n                double value = current_score * 400.0 - dist_cost;\n                if (value > best_config.value) {\n                    best_config.value = value;\n                    best_config.root_pos = cand_root_pos;\n                    best_config.edge_dirs = cand_dirs;\n                    best_config.finger_assignments = assignments;\n                }\n            }\n        }\n    }\n    return best_config;\n}\n\nstring get_next_command(const GameState& state, const TargetConfig& target) {\n    Arm current_arm = state.arm;\n    string command(2 * state.arm.v_count, '.');\n\n    bool is_at_target_config = (current_arm.root_pos == target.root_pos);\n    if (is_at_target_config) {\n        for (const auto& [f_idx, f_pos] : target.finger_assignments) {\n            if (current_arm.edge_dir[f_idx] != target.edge_dirs[f_idx]) {\n                is_at_target_config = false;\n                break;\n            }\n        }\n    }\n\n    if (is_at_target_config) {\n        for (auto const& [f_idx, _] : target.finger_assignments) {\n            command[current_arm.v_count + f_idx] = 'P';\n        }\n        return command;\n    }\n\n    char best_move_c = '.';\n    int min_dist = manhattan(current_arm.root_pos, target.root_pos);\n    Point next_root_pos = current_arm.root_pos;\n\n    if (min_dist > 0) {\n        for (int i = 0; i < 4; ++i) {\n            Point new_pos = current_arm.root_pos + DIRS[i];\n            if (new_pos.r >= 0 && new_pos.r < N && new_pos.c >= 0 && new_pos.c < N) {\n                if (manhattan(new_pos, target.root_pos) < min_dist) {\n                    min_dist = manhattan(new_pos, target.root_pos);\n                    best_move_c = MOVE_CHARS[i];\n                    next_root_pos = new_pos;\n                }\n            }\n        }\n    }\n    command[0] = best_move_c;\n\n    for (int i = 1; i < current_arm.v_count; ++i) {\n        if (current_arm.parent[i] != 0) continue;\n        if (target.finger_assignments.find(i) == target.finger_assignments.end()) continue;\n        \n        Point finger_target_abs = target.root_pos + (REL_DIRS[target.edge_dirs[i]] * current_arm.length[i]);\n\n        char best_rot_c = '.';\n        int best_rot_dist = manhattan(next_root_pos + (REL_DIRS[current_arm.edge_dir[i]] * current_arm.length[i]), finger_target_abs);\n        \n        int l_dir = (current_arm.edge_dir[i] + 3) % 4;\n        int l_dist = manhattan(next_root_pos + (REL_DIRS[l_dir] * current_arm.length[i]), finger_target_abs);\n        if (l_dist < best_rot_dist) {\n            best_rot_dist = l_dist;\n            best_rot_c = 'L';\n        }\n\n        int r_dir = (current_arm.edge_dir[i] + 1) % 4;\n        int r_dist = manhattan(next_root_pos + (REL_DIRS[r_dir] * current_arm.length[i]), finger_target_abs);\n        if (r_dist < best_rot_dist) {\n            best_rot_c = 'R';\n        }\n        command[i] = best_rot_c;\n    }\n    return command;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    Timer timer;\n    cin >> N >> M >> V;\n    set<Point> sources, targets;\n    for (int i = 0; i < N; ++i) {\n        string row; cin >> row;\n        for (int j = 0; j < N; ++j) if (row[j] == '1') sources.insert({i, j});\n    }\n    for (int i = 0; i < N; ++i) {\n        string row; cin >> row;\n        for (int j = 0; j < N; ++j) if (row[j] == '1') targets.insert({i, j});\n    }\n\n    // --- Arm Design ---\n    int v_to_use = V;\n    vector<pair<int, int>> edges;\n    int num_fingers = v_to_use > 1 ? v_to_use - 1 : 0;\n    if (num_fingers > 0) {\n        int L_small = 1;\n        int L_large = max(2, (int)round(N / 3.0));\n        int num_small = num_fingers / 2;\n        for (int i = 0; i < num_small; ++i) {\n            edges.push_back({0, L_small});\n        }\n        for (int i = 0; i < num_fingers - num_small; ++i) {\n            edges.push_back({0, L_large});\n        }\n    }\n    \n    long long sum_r = 0, sum_c = 0; for(const auto& p : sources) { sum_r += p.r; sum_c += p.c; }\n    Point initial_root = {(int)round((double)sum_r/M), (int)round((double)sum_c/M)};\n    \n    cout << v_to_use << endl;\n    for (const auto& edge : edges) cout << edge.first << \" \" << edge.second << endl;\n    cout << initial_root.r << \" \" << initial_root.c << endl;\n\n    // --- Initial Planning (Matching) ---\n    map<Point, Point> s_to_t_map;\n    vector<Point> s_vec(sources.begin(), sources.end());\n    vector<Point> t_vec(targets.begin(), targets.end());\n    atcoder::mcf_graph<int, int> g(2 * M + 2);\n    int S_node = 2 * M, T_node = 2 * M + 1;\n    for (int i = 0; i < M; ++i) {\n        g.add_edge(S_node, i, 1, 0);\n        g.add_edge(M + i, T_node, 1, 0);\n        for (int j = 0; j < M; ++j) g.add_edge(i, M + j, 1, manhattan(s_vec[i], t_vec[j]));\n    }\n    g.flow(S_node, T_node, M);\n    for (auto e : g.edges()) {\n        if (e.from < M && e.to >= M && e.to < 2*M && e.flow > 0) s_to_t_map[s_vec[e.from]] = t_vec[e.to - M];\n    }\n\n    // --- Main Loop ---\n    Arm arm(v_to_use, initial_root, edges);\n    GameState state(arm, sources, targets, s_to_t_map);\n    \n    TargetConfig current_target;\n    int plan_life = 0;\n    const double TIME_LIMIT = 2.90;\n\n    int max_turns = 100000;\n    for (int turn = 0; turn < max_turns; ++turn) {\n        if (state.targets_to_fill.empty() || timer.get_elapsed_time() > TIME_LIMIT) break;\n\n        if (plan_life <= 0) {\n            TargetConfig pickup_config = find_best_config(state, true, timer, TIME_LIMIT);\n            TargetConfig dropoff_config = find_best_config(state, false, timer, TIME_LIMIT);\n\n            if (pickup_config.value > -1e17 || dropoff_config.value > -1e17) {\n                 if (pickup_config.value >= dropoff_config.value) current_target = pickup_config;\n                 else current_target = dropoff_config;\n                 plan_life = manhattan(state.arm.root_pos, current_target.root_pos) + 5;\n            } else { \n                string cmd(2 * v_to_use, '.'); cout << cmd << endl; continue;\n            }\n        }\n        \n        string command = get_next_command(state, current_target);\n        cout << command << endl;\n\n        state.arm.apply_command(command);\n        \n        bool action_taken = false;\n        for (int i = 0; i < v_to_use; ++i) {\n            if (command[v_to_use + i] == 'P') {\n                action_taken = true;\n                if (current_target.is_pickup) {\n                    Point s_pos = state.arm.abs_pos[i];\n                    state.sources_left.erase(s_pos);\n                    state.held_by_finger[i] = s_pos;\n                } else {\n                    Point s_pos = state.held_by_finger.at(i);\n                    state.targets_to_fill.erase(state.s_to_t_map.at(s_pos));\n                    state.held_by_finger.erase(i);\n                }\n            }\n        }\n        if(action_taken) plan_life = 0; else plan_life--;\n\n    }\n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n#include <random>\n#include <set>\n#include <map>\n#include <queue>\n\n// --- Utilities ---\nstruct Point {\n    int x, y;\n    bool operator<(const Point& other) const {\n        if (x != other.x) return x < other.x;\n        return y < other.y;\n    }\n     bool operator==(const Point& other) const {\n        return x == other.x && y == other.y;\n    }\n};\n\nlong long cross_product(Point a, Point b, Point c) {\n    return (long long)(b.x - a.x) * (c.y - a.y) - (long long)(b.y - a.y) * (c.x - a.x);\n}\n\n// Global timer\nstd::chrono::high_resolution_clock::time_point start_time;\n\n// --- Polygon Utilities ---\nstruct Polygon {\n    std::vector<Point> vertices;\n\n    bool is_inside(Point p) const {\n        if (vertices.empty()) return false;\n        int n = vertices.size();\n        bool inside = false;\n        for (int i = 0; i < n; ++i) {\n            const Point& p1 = vertices[i];\n            const Point& p2 = vertices[(i + 1) % n];\n\n            if (p1.y == p2.y && p.y == p1.y && p.x >= std::min(p1.x, p2.x) && p.x <= std::max(p1.x, p2.x)) {\n                return true;\n            }\n            if (p1.x == p2.x && p.x == p1.x && p.y >= std::min(p1.y, p2.y) && p.y <= std::max(p1.y, p2.y)) {\n                return true;\n            }\n\n            if ((p1.y > p.y) != (p2.y > p.y)) {\n                double intersect_x = (double)(p2.x - p1.x) * (p.y - p1.y) / (double)(p2.y - p1.y) + p1.x;\n                if (p.x < intersect_x) {\n                    inside = !inside;\n                }\n            }\n        }\n        return inside;\n    }\n\n    long long calculate_perimeter() const {\n        if (vertices.size() < 2) return 0;\n        long long p = 0;\n        for (size_t i = 0; i < vertices.size(); ++i) {\n            const auto& v1 = vertices[i];\n            const auto& v2 = vertices[(i + 1) % vertices.size()];\n            p += std::abs(v1.x - v2.x) + std::abs(v1.y - v2.y);\n        }\n        return p;\n    }\n};\n\n// --- Problem Data ---\nint N;\nstd::vector<Point> mackerels;\nstd::vector<Point> sardines;\n\n// --- Main Algorithm ---\n\nusing GridPoint = std::pair<int, int>;\n\nconst int DX[] = {0, 1, 0, -1};\nconst int DY[] = {1, 0, -1, 0};\n\nPolygon generate_polygon_from_cells(const std::set<GridPoint>& cells, int cell_size) {\n    if (cells.empty()) {\n        return Polygon{};\n    }\n\n    std::map<Point, std::vector<Point>> adj;\n    for (const auto& cell : cells) {\n        int gx = cell.first;\n        int gy = cell.second;\n        Point corners[] = {\n            {gx * cell_size, gy * cell_size},\n            {(gx + 1) * cell_size, gy * cell_size},\n            {(gx + 1) * cell_size, (gy + 1) * cell_size},\n            {gx * cell_size, (gy + 1) * cell_size}\n        };\n\n        for (int i = 0; i < 4; ++i) {\n            GridPoint neighbor = {gx + DX[i], gy + DY[i]};\n            if (cells.find(neighbor) == cells.end()) {\n                Point p1 = corners[i];\n                Point p2 = corners[(i + 3) % 4];\n                adj[p1].push_back(p2);\n                adj[p2].push_back(p1);\n            }\n        }\n    }\n    \n    std::vector<Point> vertices;\n    if (adj.empty()) return Polygon{};\n    \n    Point start_node = adj.begin()->first;\n    Point current_node = start_node;\n    Point prev_node = {start_node.x, start_node.y - 1};\n\n    for(size_t i = 0; i < 2 * adj.size(); ++i) {\n        vertices.push_back(current_node);\n        auto& neighbors = adj[current_node];\n        \n        std::sort(neighbors.begin(), neighbors.end(), [&](const Point& a, const Point& b) {\n            long long cp_a = cross_product(prev_node, current_node, a);\n            long long cp_b = cross_product(prev_node, current_node, b);\n            if (cp_a > 0 && cp_b <= 0) return true;\n            if (cp_a <= 0 && cp_b > 0) return false;\n            return cp_a > cp_b;\n        });\n        \n        Point next_node = neighbors[0];\n        for(const auto& neighbor : neighbors) {\n            if (!(neighbor == prev_node)) {\n                next_node = neighbor;\n                break;\n            }\n        }\n        \n        prev_node = current_node;\n        current_node = next_node;\n        if (current_node == start_node) break;\n    }\n\n    if (vertices.size() > 2) {\n        std::vector<Point> simplified;\n        for (size_t i = 0; i < vertices.size(); ++i) {\n            Point p_prev = simplified.empty() ? vertices.back() : simplified.back();\n            Point p_curr = vertices[i];\n            Point p_next = vertices[(i + 1) % vertices.size()];\n            if (cross_product(p_prev, p_curr, p_next) != 0 || simplified.size() < 2) {\n                simplified.push_back(p_curr);\n            }\n        }\n        vertices = simplified;\n    }\n    \n    return Polygon{vertices};\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    start_time = std::chrono::high_resolution_clock::now();\n\n    std::cin >> N;\n    mackerels.resize(N);\n    sardines.resize(N);\n    for (int i = 0; i < N; ++i) std::cin >> mackerels[i].x >> mackerels[i].y;\n    for (int i = 0; i < N; ++i) std::cin >> sardines[i].x >> sardines[i].y;\n    \n    int best_a = 0, best_b = 0;\n    Polygon best_polygon;\n    \n    std::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n    std::vector<int> cell_sizes = {1000, 667, 500, 400, 333, 250, 200};\n    int time_per_grid = 1980 / cell_sizes.size();\n\n    for (int cell_size : cell_sizes) {\n        auto loop_start_time = std::chrono::high_resolution_clock::now();\n        \n        int grid_dim_x = 100001 / cell_size + 1;\n        int grid_dim_y = 100001 / cell_size + 1;\n        std::vector<std::vector<int>> grid_scores(grid_dim_x, std::vector<int>(grid_dim_y, 0));\n\n        for (const auto& p : mackerels) grid_scores[p.x / cell_size][p.y / cell_size]++;\n        for (const auto& p : sardines) grid_scores[p.x / cell_size][p.y / cell_size]--;\n\n        std::vector<std::vector<bool>> visited(grid_dim_x, std::vector<bool>(grid_dim_y, false));\n\n        for (int gx = 0; gx < grid_dim_x; ++gx) {\n            for (int gy = 0; gy < grid_dim_y; ++gy) {\n                 auto now = std::chrono::high_resolution_clock::now();\n                 if (std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time).count() > 1980) break;\n                 \n                if (grid_scores[gx][gy] > 0 && !visited[gx][gy]) {\n                    std::set<GridPoint> component_cells;\n                    std::queue<GridPoint> q;\n\n                    q.push({gx, gy});\n                    visited[gx][gy] = true;\n                    while (!q.empty()) {\n                        GridPoint curr = q.front(); q.pop();\n                        component_cells.insert(curr);\n                        for (int i = 0; i < 4; ++i) {\n                            GridPoint next = {curr.first + DX[i], curr.second + DY[i]};\n                            if (next.first >= 0 && next.first < grid_dim_x && next.second >= 0 && next.second < grid_dim_y &&\n                                !visited[next.first][next.second] && grid_scores[next.first][next.second] > 0) {\n                                visited[next.first][next.second] = true;\n                                q.push(next);\n                            }\n                        }\n                    }\n\n                    std::set<GridPoint> current_cells = component_cells;\n                    \n                    double T = 5.0;\n                    double T_end = 0.01;\n                    int sa_iter = 0;\n                    \n                    while (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - loop_start_time).count() < time_per_grid - 20 && T > T_end) {\n                        sa_iter++;\n                        if (sa_iter % 200 == 0) T *= 0.99;\n                        \n                        std::vector<GridPoint> boundary_plus_neighbors;\n                        for(const auto& cell : current_cells) {\n                            for(int i=0; i<4; ++i) {\n                                GridPoint neighbor = {cell.first + DX[i], cell.second + DY[i]};\n                                if (neighbor.first >= 0 && neighbor.first < grid_dim_x && neighbor.second >= 0 && neighbor.second < grid_dim_y) {\n                                    boundary_plus_neighbors.push_back(neighbor);\n                                }\n                            }\n                        }\n                        if(boundary_plus_neighbors.empty()) continue;\n                        std::uniform_int_distribution<int> dist_op(0, boundary_plus_neighbors.size() - 1);\n                        GridPoint cand_cell = boundary_plus_neighbors[dist_op(rng)];\n\n                        bool is_in = current_cells.count(cand_cell);\n                        long long delta_score = grid_scores[cand_cell.first][cand_cell.second];\n                        if (is_in) delta_score = -delta_score;\n\n                        std::uniform_real_distribution<double> prob_dist(0.0, 1.0);\n                        if (delta_score > 0 || prob_dist(rng) < std::exp(delta_score / T)) {\n                            if (is_in) { if(current_cells.size() > 1) current_cells.erase(cand_cell); }\n                            else current_cells.insert(cand_cell);\n                        }\n                    }\n\n                    std::set<GridPoint> filled_cells = current_cells;\n                    if (!filled_cells.empty()) {\n                        std::vector<std::vector<bool>> is_component(grid_dim_x, std::vector<bool>(grid_dim_y, false));\n                        for(const auto& cell : filled_cells) is_component[cell.first][cell.second] = true;\n\n                        std::queue<GridPoint> hole_q;\n                        std::vector<std::vector<bool>> visited_bfs(grid_dim_x, std::vector<bool>(grid_dim_y, false));\n                        for(int i=0; i<grid_dim_x; ++i) {\n                            if (!is_component[i][0] && !visited_bfs[i][0]) { hole_q.push({i,0}); visited_bfs[i][0] = true; }\n                            if (grid_dim_y > 1 && !is_component[i][grid_dim_y-1] && !visited_bfs[i][grid_dim_y-1]) { hole_q.push({i,grid_dim_y-1}); visited_bfs[i][grid_dim_y-1] = true; }\n                        }\n                        for(int i=0; i<grid_dim_y; ++i) {\n                            if (!is_component[0][i] && !visited_bfs[0][i]) { hole_q.push({0,i}); visited_bfs[0][i] = true; }\n                            if (grid_dim_x > 1 && !is_component[grid_dim_x-1][i] && !visited_bfs[grid_dim_x-1][i]) { hole_q.push({grid_dim_x-1,i}); visited_bfs[grid_dim_x-1][i] = true; }\n                        }\n\n                        while(!hole_q.empty()){\n                            GridPoint curr = hole_q.front(); hole_q.pop();\n                            for(int i=0; i<4; ++i){\n                                GridPoint next = {curr.first + DX[i], curr.second + DY[i]};\n                                if (next.first >= 0 && next.first < grid_dim_x && next.second >= 0 && next.second < grid_dim_y && !visited_bfs[next.first][next.second] && !is_component[next.first][next.second]){\n                                    visited_bfs[next.first][next.second] = true;\n                                    hole_q.push(next);\n                                }\n                            }\n                        }\n                        \n                        for(int i=0; i<grid_dim_x; ++i) for(int j=0; j<grid_dim_y; ++j) {\n                            if(!visited_bfs[i][j] && !is_component[i][j]) filled_cells.insert({i,j});\n                        }\n                    }\n\n                    Polygon p = generate_polygon_from_cells(filled_cells, cell_size);\n                    if (p.vertices.size() >= 4 && p.vertices.size() <= 1000 && p.calculate_perimeter() <= 400000) {\n                        int current_a = 0, current_b = 0;\n                        for (const auto& m : mackerels) if (p.is_inside(m)) current_a++;\n                        for (const auto& s : sardines) if (p.is_inside(s)) current_b++;\n\n                        if (current_a - current_b > best_a - best_b) {\n                            best_a = current_a;\n                            best_b = current_b;\n                            best_polygon = p;\n                        }\n                    }\n                }\n            }\n             if (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start_time).count() > 1980) break;\n        }\n    }\n\n    if (best_polygon.vertices.empty()) {\n        if (!mackerels.empty()) {\n            Point m = mackerels[0];\n            best_polygon.vertices.push_back({m.x, m.y});\n            best_polygon.vertices.push_back({m.x + 1, m.y});\n            best_polygon.vertices.push_back({m.x + 1, m.y + 1});\n            best_polygon.vertices.push_back({m.x, m.y + 1});\n        }\n    }\n\n    std::cout << best_polygon.vertices.size() << '\\n';\n    for (const auto& v : best_polygon.vertices) {\n        std::cout << v.x << \" \" << v.y << '\\n';\n    }\n\n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <string>\n#include <chrono>\n#include <random>\n#include <numeric>\n#include <algorithm>\n#include <map>\n#include <tuple>\n#include <cmath>\n\n#include <Eigen/Dense>\n\n// --- Timer ---\nusing namespace std;\nusing namespace std::chrono;\n\nlong long start_time;\n\nlong long get_time() {\n    return duration_cast<milliseconds>(high_resolution_clock::now().time_since_epoch()).count();\n}\n\n// --- Random ---\nmt19937 rng(0);\n\n// --- Problem specific structs ---\nstruct Rect {\n    long long x, y, w, h;\n};\n\nstruct Action {\n    int p, r;\n    char d;\n    int b;\n};\n\nusing Plan = vector<Action>;\n\n// O(N^2) simulation. N = plan.size().\npair<long long, long long> simulate(int N_total, const vector<double>& w_est, const vector<double>& h_est, const Plan& plan) {\n    if (plan.empty()) return {0,0};\n\n    vector<Rect> placed_rects;\n    long long W = 0, H = 0;\n    vector<int> p_to_idx(N_total, -1);\n\n    for (const auto& action : plan) {\n        long long w = round((action.r == 0) ? w_est[action.p] : h_est[action.p]);\n        long long h = round((action.r == 0) ? h_est[action.p] : w_est[action.p]);\n        long long new_x, new_y;\n        if (action.d == 'U') {\n            new_x = 0;\n            if (action.b != -1) {\n                const auto& ref_rect = placed_rects[p_to_idx[action.b]];\n                new_x = ref_rect.x + ref_rect.w;\n            }\n            new_y = 0;\n            for (const auto& rect : placed_rects) {\n                if (max(new_x, rect.x) < min(new_x + w, rect.x + rect.w)) {\n                    new_y = max(new_y, rect.y + rect.h);\n                }\n            }\n        } else { // 'L'\n            new_y = 0;\n            if (action.b != -1) {\n                const auto& ref_rect = placed_rects[p_to_idx[action.b]];\n                new_y = ref_rect.y + ref_rect.h;\n            }\n            new_x = 0;\n            for (const auto& rect : placed_rects) {\n                if (max(new_y, rect.y) < min(new_y + h, rect.y + rect.h)) {\n                    new_x = max(new_x, rect.x + rect.w);\n                }\n            }\n        }\n        p_to_idx[action.p] = placed_rects.size();\n        placed_rects.push_back({new_x, new_y, w, h});\n        W = max(W, new_x + w);\n        H = max(H, new_y + h);\n    }\n    return {W, H};\n}\n\n\n// --- Main logic ---\nint N, T;\ndouble SIGMA;\nvector<double> w_obs, h_obs;\nvector<double> w_mean, h_mean;\n\nvector<Plan> exploratory_plans;\nvector<tuple<Plan, long long, long long>> history;\n\nlong long best_score = -1;\nPlan best_plan;\n\nvoid generate_exploratory_plans() {\n    for (int k = 0; k < 4; ++k) {\n        Plan p_L, p_U;\n        for (int i = 0; i < N; ++i) {\n            p_L.push_back({i, (int)(rng() % 2), 'L', i > 0 ? i-1 : -1});\n            p_U.push_back({i, (int)(rng() % 2), 'U', i > 0 ? i-1 : -1});\n        }\n        exploratory_plans.push_back(p_L);\n        exploratory_plans.push_back(p_U);\n    }\n}\n\nvoid update_estimates_by_lsq() {\n    int num_vars = 2 * N;\n    \n    vector<vector<pair<int, double>>> A_rows;\n    vector<double> b_vals;\n\n    for (int i = 0; i < N; ++i) {\n        A_rows.push_back({{i, 1.0}}); b_vals.push_back(w_obs[i]);\n        A_rows.push_back({{N + i, 1.0}}); b_vals.push_back(h_obs[i]);\n    }\n\n    for (const auto& [plan, W_prime, H_prime] : history) {\n        if(plan.size() != N) continue;\n        bool is_sum_plan = true;\n        char first_d = plan[0].d;\n        for(size_t j=1; j<plan.size(); ++j) {\n            if(plan[j].d != first_d) { is_sum_plan = false; break; }\n        }\n        if(!is_sum_plan) continue;\n\n        vector<pair<int, double>> row;\n        if (first_d == 'L') {\n            for (const auto& action : plan) {\n                if (action.r == 0) row.push_back({action.p, 1.0});\n                else row.push_back({N + action.p, 1.0});\n            }\n            A_rows.push_back(row); b_vals.push_back(W_prime);\n        } else {\n            for (const auto& action : plan) {\n                if (action.r == 0) row.push_back({N + action.p, 1.0});\n                else row.push_back({action.p, 1.0});\n            }\n            A_rows.push_back(row); b_vals.push_back(H_prime);\n        }\n    }\n\n    int num_equations = A_rows.size();\n    Eigen::MatrixXd A(num_equations, num_vars);\n    Eigen::VectorXd b(num_equations);\n    A.setZero();\n    for(int i=0; i<num_equations; ++i){\n        for(auto const& [col, val] : A_rows[i]) {\n            A(i, col) = val;\n        }\n        b(i) = b_vals[i];\n    }\n    \n    Eigen::VectorXd x = A.bdcSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(b);\n\n    for (int i = 0; i < N; ++i) {\n        w_mean[i] = max(1.0, x(i));\n        h_mean[i] = max(1.0, x(N + i));\n    }\n}\n\nPlan greedy_search() {\n    Plan plan;\n    vector<Rect> placed_rects;\n    long long current_W = 0, current_H = 0;\n\n    for (int i = 0; i < N; ++i) { // Assuming p_i = i\n        Action best_action;\n        long long best_score = -1;\n        \n        for (int r = 0; r < 2; ++r) {\n            long long w = round((r == 0) ? w_mean[i] : h_mean[i]);\n            long long h = round((r == 0) ? h_mean[i] : w_mean[i]);\n            for (char d : {'U', 'L'}) {\n                vector<int> b_candidates;\n                const int B_SAMPLES = 10;\n                const int FULL_SEARCH_THRESHOLD = 20;\n\n                b_candidates.push_back(-1);\n                if (i > 0) {\n                    if (i < FULL_SEARCH_THRESHOLD) {\n                        for(int k=0; k<i; ++k) b_candidates.push_back(k);\n                    } else {\n                        b_candidates.push_back(i - 1);\n                        uniform_int_distribution<int> dist(0, i - 1);\n                        for (int k=0; k < B_SAMPLES; ++k) {\n                            b_candidates.push_back(dist(rng));\n                        }\n                    }\n                }\n                sort(b_candidates.begin(), b_candidates.end());\n                b_candidates.erase(unique(b_candidates.begin(), b_candidates.end()), b_candidates.end());\n\n                for (int b_val : b_candidates) {\n                    long long new_x, new_y;\n                    if(d == 'U'){\n                        new_x = 0; \n                        if (b_val != -1) new_x = placed_rects[b_val].x + placed_rects[b_val].w;\n                        new_y = 0;\n                        for(const auto& rect : placed_rects) {\n                            if(max(new_x, rect.x) < min(new_x+w, rect.x+rect.w)) {\n                                new_y = max(new_y, rect.y+rect.h);\n                            }\n                        }\n                    } else { // 'L'\n                        new_y = 0;\n                        if (b_val != -1) new_y = placed_rects[b_val].y + placed_rects[b_val].h;\n                        new_x = 0;\n                        for(const auto& rect : placed_rects) {\n                            if(max(new_y, rect.y) < min(new_y+h, rect.y+rect.h)) {\n                                new_x = max(new_x, rect.x+rect.w);\n                            }\n                        }\n                    }\n                    long long next_W = max(current_W, new_x+w);\n                    long long next_H = max(current_H, new_y+h);\n\n                    long long current_score = next_W + next_H;\n                    if (best_score == -1 || current_score < best_score) {\n                        best_score = current_score;\n                        best_action = {i, r, d, b_val};\n                    }\n                }\n            }\n        }\n        \n        plan.push_back(best_action);\n        long long w = round((best_action.r == 0) ? w_mean[i] : h_mean[i]);\n        long long h = round((best_action.r == 0) ? h_mean[i] : w_mean[i]);\n        long long new_x, new_y;\n        if(best_action.d == 'U'){\n            new_x = 0; if (best_action.b != -1) new_x = placed_rects[best_action.b].x + placed_rects[best_action.b].w;\n            new_y = 0;\n            for(const auto& rect : placed_rects) if(max(new_x, rect.x) < min(new_x+w, rect.x+rect.w)) new_y = max(new_y, rect.y+rect.h);\n        } else {\n            new_y = 0; if (best_action.b != -1) new_y = placed_rects[best_action.b].y + placed_rects[best_action.b].h;\n            new_x = 0;\n            for(const auto& rect : placed_rects) if(max(new_y, rect.y) < min(new_y+h, rect.y+rect.h)) new_x = max(new_x, rect.x+rect.w);\n        }\n        placed_rects.push_back({new_x, new_y, w, h});\n        current_W = max(current_W, new_x+w);\n        current_H = max(current_H, new_y+h);\n    }\n    return plan;\n}\n\nPlan local_search(Plan initial_plan, int time_limit_ms) {\n    long long turn_start_time = get_time();\n    Plan current_best_plan = initial_plan;\n    auto [W, H] = simulate(N, w_mean, h_mean, current_best_plan);\n    long long best_eval_score = W + H;\n\n    while(get_time() - turn_start_time < time_limit_ms) {\n        Plan current_plan = current_best_plan;\n        int i = rng() % N;\n        \n        int change_type = uniform_int_distribution<int>(0, 2)(rng);\n        if (change_type == 0) {\n            current_plan[i].r = 1 - current_plan[i].r;\n        } else if (change_type == 1) {\n            current_plan[i].d = (current_plan[i].d == 'U' ? 'L' : 'U');\n        } else { // change_type == 2\n            if (i > 0) {\n                current_plan[i].b = uniform_int_distribution<int>(-1, i - 1)(rng);\n            }\n        }\n        \n        auto [cur_W, cur_H] = simulate(N, w_mean, h_mean, current_plan);\n        long long current_eval_score = cur_W + cur_H;\n\n        if (current_eval_score < best_eval_score) {\n            best_eval_score = current_eval_score;\n            current_best_plan = current_plan;\n        }\n    }\n    return current_best_plan;\n}\n\nvoid solve() {\n    cin >> N >> T >> SIGMA;\n    w_obs.resize(N); h_obs.resize(N);\n    w_mean.resize(N); h_mean.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> w_obs[i] >> h_obs[i];\n        w_mean[i] = w_obs[i];\n        h_mean[i] = h_obs[i];\n    }\n    \n    generate_exploratory_plans();\n    \n    int K = min((int)exploratory_plans.size(), T / 2);\n    \n    for (int t = 0; t < T; ++t) {\n        Plan p_to_submit;\n        if (t < K) {\n            p_to_submit = exploratory_plans[t];\n        } else {\n            if (t == K && K > 0) { // Update estimates only once after exploration\n                update_estimates_by_lsq();\n            }\n            \n            long long time_left = 2800 - (get_time() - start_time);\n            long long time_per_turn = time_left / (T - t + 1);\n            \n            long long greedy_start_time = get_time();\n            Plan initial_plan = greedy_search();\n            long long greedy_time = get_time() - greedy_start_time;\n\n            p_to_submit = local_search(initial_plan, max(0LL, time_per_turn - greedy_time));\n            \n            if (!best_plan.empty()) {\n                auto [w_cand, h_cand] = simulate(N, w_mean, h_mean, p_to_submit);\n                auto [w_best, h_best] = simulate(N, w_mean, h_mean, best_plan);\n                if (w_best + h_best < w_cand + h_cand) {\n                    p_to_submit = best_plan;\n                }\n            }\n        }\n        \n        cout << p_to_submit.size() << endl;\n        for (const auto& action : p_to_submit) {\n            cout << action.p << \" \" << action.r << \" \" << action.d << \" \" << action.b << endl;\n        }\n\n        long long W_prime, H_prime;\n        cin >> W_prime >> H_prime;\n        \n        if (t < K) {\n            history.emplace_back(p_to_submit, W_prime, H_prime);\n        }\n        \n        long long current_score = W_prime + H_prime;\n        if (best_score == -1 || current_score < best_score) {\n            best_score = current_score;\n            best_plan = p_to_submit;\n        }\n    }\n}\n\nint main() {\n    start_time = get_time();\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <cmath>\n#include <tuple>\n\nusing namespace std;\n\n// --- Utilities ---\nstruct XorShift {\n    unsigned int x, y, z, w;\n    XorShift(unsigned int seed) : x(seed), y(362436069), z(521288629), w(88675123) {}\n    unsigned int next() {\n        unsigned int t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));\n    }\n    int next_int(int n) {\n        if (n == 0) return 0;\n        return next() % n;\n    }\n    double next_double() {\n        return (double)next() / ((long long)1 << 32);\n    }\n};\n\nXorShift rnd(12345);\nauto start_time = chrono::steady_clock::now();\n\n// --- Problem data ---\nint N, M, H;\nvector<int> A;\nvector<pair<int, int>> edges;\nvector<vector<int>> adj;\n\n// --- Solution state and helpers ---\nstruct Solution {\n    vector<int> p;\n    long long score;\n\n    vector<vector<int>> children;\n    vector<int> h;\n    vector<int> max_d;\n    vector<long long> sum_A_sub;\n    vector<int> root_of;\n\n    Solution() {}\n\n    void init(int n_nodes) {\n        p.assign(n_nodes, -1);\n        children.assign(n_nodes, {});\n        h.assign(n_nodes, 0);\n        max_d.assign(n_nodes, 0);\n        sum_A_sub.assign(n_nodes, 0);\n        root_of.assign(n_nodes, -1);\n    }\n\n    void compute_properties() {\n        for(int i=0; i<N; ++i) children[i].clear();\n        vector<int> roots;\n        for (int i = 0; i < N; ++i) {\n            if (p[i] == -1) {\n                roots.push_back(i);\n            } else {\n                children[p[i]].push_back(i);\n            }\n        }\n\n        for (int r : roots) {\n            vector<int> q;\n            q.push_back(r);\n            root_of[r] = r;\n            h[r] = 0;\n            \n            int head = 0;\n            while(head < q.size()){\n                int u = q[head++];\n                for(int v : children[u]){\n                    h[v] = h[u] + 1;\n                    root_of[v] = r;\n                    q.push_back(v);\n                }\n            }\n            \n            reverse(q.begin(), q.end());\n            for(int u : q){\n                sum_A_sub[u] = A[u];\n                max_d[u] = 0;\n                for(int v : children[u]){\n                    sum_A_sub[u] += sum_A_sub[v];\n                    max_d[u] = max(max_d[u], max_d[v] + 1);\n                }\n            }\n        }\n        score = 0;\n        for(int i=0; i<N; ++i) {\n            if (h[i] > H) {\n                score = -1; // Invalid\n                return;\n            }\n            score += (long long)(h[i] + 1) * A[i];\n        }\n    }\n};\n\nvoid solve() {\n    Solution sol;\n    sol.init(N);\n    \n    // --- Greedy construction ---\n    double greedy_time_limit = 0.8;\n    int roots_count = N;\n    while(roots_count > 1) {\n        auto current_time = chrono::steady_clock::now();\n        double elapsed_time = chrono::duration_cast<chrono::milliseconds>(current_time - start_time).count() / 1000.0;\n        if (elapsed_time > greedy_time_limit) break;\n\n        sol.compute_properties();\n\n        double best_gain = -1.0;\n        int best_u = -1, best_v = -1;\n\n        for (const auto& edge : edges) {\n            int u1 = edge.first;\n            int v1 = edge.second;\n\n            if (sol.root_of[u1] == sol.root_of[v1]) continue;\n\n            // Try u1 -> v1\n            if (sol.p[v1] == -1) {\n                if (sol.h[u1] + 1 + sol.max_d[v1] <= H) {\n                    double gain = (double)(sol.h[u1] + 1) * sol.sum_A_sub[v1];\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        best_u = u1;\n                        best_v = v1;\n                    }\n                }\n            }\n            // Try v1 -> u1\n            if (sol.p[u1] == -1) {\n                if (sol.h[v1] + 1 + sol.max_d[u1] <= H) {\n                    double gain = (double)(sol.h[v1] + 1) * sol.sum_A_sub[u1];\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        best_u = v1;\n                        best_v = u1;\n                    }\n                }\n            }\n        }\n\n        if (best_u == -1) break;\n        sol.p[best_v] = best_u;\n        roots_count--;\n    }\n\n    sol.compute_properties();\n    Solution best_sol = sol;\n\n    // --- Simulated Annealing ---\n    double time_limit = 1.95;\n    double temp_start = 500.0, temp_end = 0.1;\n\n    while (true) {\n        auto current_time = chrono::steady_clock::now();\n        double elapsed_time = chrono::duration_cast<chrono::milliseconds>(current_time - start_time).count() / 1000.0;\n        if (elapsed_time > time_limit) break;\n\n        double progress = (elapsed_time - greedy_time_limit) / (time_limit - greedy_time_limit);\n        if (progress < 0) progress = 0;\n        if (progress > 1) progress = 1;\n\n        double temp = temp_start * pow(temp_end / temp_start, progress);\n\n        int v = rnd.next_int(N);\n        \n        vector<int> candidates = adj[v];\n        candidates.push_back(-1);\n        int u = candidates[rnd.next_int(candidates.size())];\n\n        int old_p = sol.p[v];\n        if (u == old_p) continue;\n        \n        bool is_ancestor = false;\n        if (u != -1) {\n            int curr = u;\n            while(curr != -1) {\n                if (curr == v) {\n                    is_ancestor = true;\n                    break;\n                }\n                curr = sol.p[curr];\n            }\n        }\n        if (is_ancestor) continue;\n        \n        int u_h = (u == -1) ? -1 : sol.h[u];\n        if (u_h + 1 + sol.max_d[v] > H) continue;\n\n        int old_p_h = (old_p == -1) ? -1 : sol.h[old_p];\n        long long score_delta = (long long)(u_h - old_p_h) * sol.sum_A_sub[v];\n\n        if (score_delta > 0 || (temp > 1e-9 && rnd.next_double() < exp(score_delta / temp))) {\n            sol.p[v] = u;\n            sol.compute_properties();\n            if (sol.score > best_sol.score) {\n                best_sol = sol;\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << best_sol.p[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N >> M >> H;\n    A.resize(N);\n    adj.resize(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        edges.push_back({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    solve();\n\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <array>\n#include <chrono>\n#include <queue>\n#include <memory>\n\nusing namespace std;\nusing namespace std::chrono;\n\nconst int N = 20;\nconst int BEAM_WIDTH = 250; \nconst double TIME_LIMIT_MS = 1950.0;\n\nstruct Piece {\n    int id; // unique id for Oni (0 to 2N-1), -1 for Fuku\n    int r, c;\n    bool removed = false;\n};\n\nstruct MacroMove {\n    char dir;\n    int line_idx;\n    int cost;\n};\n\nstruct State {\n    vector<Piece> onis;\n    vector<Piece> fukus;\n    \n    vector<MacroMove> history;\n    int total_cost = 0;\n    int uncovered_count = 0;\n\n    double score = 0.0; // g + h\n\n    bool operator>(const State& other) const {\n        if (abs(score - other.score) > 1e-9) {\n            return score > other.score;\n        }\n        return total_cost > other.total_cost;\n    }\n};\n\ndouble calculate_heuristic(const State& s) {\n    if (s.uncovered_count == 0) return 0.0;\n\n    double h = 0;\n    for (const auto& oni : s.onis) {\n        if (oni.removed) continue;\n        \n        int min_cost = 1e9;\n        \n        bool safe_u = true;\n        for(const auto& fuku : s.fukus) if (!fuku.removed && fuku.c == oni.c && fuku.r < oni.r) { safe_u = false; break; }\n        if(safe_u) min_cost = min(min_cost, oni.r + 1);\n\n        bool safe_d = true;\n        for(const auto& fuku : s.fukus) if (!fuku.removed && fuku.c == oni.c && fuku.r > oni.r) { safe_d = false; break; }\n        if(safe_d) min_cost = min(min_cost, N - oni.r);\n\n        bool safe_l = true;\n        for(const auto& fuku : s.fukus) if (!fuku.removed && fuku.r == oni.r && fuku.c < oni.c) { safe_l = false; break; }\n        if(safe_l) min_cost = min(min_cost, oni.c + 1);\n        \n        bool safe_r = true;\n        for(const auto& fuku : s.fukus) if (!fuku.removed && fuku.r == oni.r && fuku.c > oni.c) { safe_r = false; break; }\n        if(safe_r) min_cost = min(min_cost, N - oni.c);\n\n        if (min_cost < 1e8) {\n            h += min_cost;\n        } else {\n            return 1e18;\n        }\n    }\n    return h;\n}\n\nvector<MacroMove> generate_actions(const State& s) {\n    vector<MacroMove> actions;\n    \n    vector<vector<int>> onis_in_row(N);\n    vector<vector<int>> onis_in_col(N);\n    for (const auto& oni : s.onis) if (!oni.removed) {\n        onis_in_row[oni.r].push_back(oni.id);\n        onis_in_col[oni.c].push_back(oni.id);\n    }\n    \n    auto generate_for_line = [&](char dir, int idx) {\n        int cost = 0;\n        bool has_target = false;\n        \n        const auto& line_oni_ids = (dir == 'U' || dir == 'D') ? onis_in_col[idx] : onis_in_row[idx];\n        \n        for (int oni_id : line_oni_ids) {\n            bool safe = true;\n            for (const auto& fuku : s.fukus) {\n                if (fuku.removed) continue;\n                if ((dir == 'U' && fuku.c == s.onis[oni_id].c && fuku.r < s.onis[oni_id].r) ||\n                    (dir == 'D' && fuku.c == s.onis[oni_id].c && fuku.r > s.onis[oni_id].r) ||\n                    (dir == 'L' && fuku.r == s.onis[oni_id].r && fuku.c < s.onis[oni_id].c) ||\n                    (dir == 'R' && fuku.r == s.onis[oni_id].r && fuku.c > s.onis[oni_id].c)) {\n                    safe = false;\n                    break;\n                }\n            }\n            if (safe) {\n                has_target = true;\n                if(dir == 'U') cost = max(cost, s.onis[oni_id].r + 1);\n                if(dir == 'D') cost = max(cost, N - s.onis[oni_id].r);\n                if(dir == 'L') cost = max(cost, s.onis[oni_id].c + 1);\n                if(dir == 'R') cost = max(cost, N - s.onis[oni_id].c);\n            }\n        }\n        if (has_target) {\n            actions.push_back({dir, idx, cost});\n        }\n    };\n    \n    for (int i = 0; i < N; ++i) { generate_for_line('L', i); generate_for_line('R', i); }\n    for (int j = 0; j < N; ++j) { generate_for_line('U', j); generate_for_line('D', j); }\n\n    return actions;\n}\n\nState apply_action_to_state(const State& current, const MacroMove& action) {\n    State next = current;\n    next.history.push_back(action);\n    next.total_cost += action.cost;\n\n    auto update_piece = [&](Piece& p) {\n        if (p.removed) return;\n        bool piece_removed = false;\n        switch(action.dir) {\n            case 'U': if (p.c == action.line_idx) { if (p.r < action.cost) piece_removed = true; else p.r -= action.cost; } break;\n            case 'D': if (p.c == action.line_idx) { if (p.r > N - 1 - action.cost) piece_removed = true; else p.r += action.cost; } break;\n            case 'L': if (p.r == action.line_idx) { if (p.c < action.cost) piece_removed = true; else p.c -= action.cost; } break;\n            case 'R': if (p.r == action.line_idx) { if (p.c > N - 1 - action.cost) piece_removed = true; else p.c += action.cost; } break;\n        }\n        if (piece_removed) {\n            p.removed = true;\n            if (p.id != -1) {\n                 next.uncovered_count--;\n            }\n        }\n    };\n\n    for (auto& oni : next.onis) update_piece(oni);\n    for (auto& fuku : next.fukus) update_piece(fuku);\n\n    return next;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    auto start_time = high_resolution_clock::now();\n\n    int n_dummy;\n    cin >> n_dummy;\n\n    State initial_state;\n    int oni_id_counter = 0;\n    for (int i = 0; i < N; ++i) {\n        string row_str;\n        cin >> row_str;\n        for (int j = 0; j < N; ++j) {\n            if (row_str[j] == 'x') {\n                initial_state.onis.push_back({oni_id_counter++, i, j, false});\n            } else if (row_str[j] == 'o') {\n                initial_state.fukus.push_back({-1, i, j, false});\n            }\n        }\n    }\n    initial_state.uncovered_count = initial_state.onis.size();\n    \n    priority_queue<State, vector<State>, greater<State>> beam;\n    initial_state.score = calculate_heuristic(initial_state);\n    beam.push(initial_state);\n\n    State best_solution;\n    best_solution.total_cost = 1e9;\n\n    while(true) {\n        auto current_time = high_resolution_clock::now();\n        if (duration_cast<milliseconds>(current_time - start_time).count() > TIME_LIMIT_MS) break;\n        if (beam.empty()) break;\n\n        priority_queue<State, vector<State>, greater<State>> next_beam_candidates;\n        int beam_proc_count = 0;\n        while(!beam.empty() && beam_proc_count < BEAM_WIDTH) {\n            State current = beam.top();\n            beam.pop();\n\n            if (current.total_cost >= best_solution.total_cost) continue;\n\n            if (current.uncovered_count == 0) {\n                 if (current.total_cost < best_solution.total_cost) best_solution = current;\n                continue;\n            }\n\n            vector<MacroMove> possible_actions = generate_actions(current);\n\n            for (const auto& action : possible_actions) {\n                State next_state = apply_action_to_state(current, action);\n                double h = calculate_heuristic(next_state);\n                if (h > 1e17) continue;\n                next_state.score = next_state.total_cost + h;\n                next_beam_candidates.push(next_state);\n            }\n            beam_proc_count++;\n        }\n        \n        beam = priority_queue<State, vector<State>, greater<State>>();\n        int count = 0;\n        while (!next_beam_candidates.empty() && count < BEAM_WIDTH) {\n            beam.push(next_beam_candidates.top());\n            next_beam_candidates.pop();\n            count++;\n        }\n    }\n\n    if (best_solution.total_cost > 4*N*N) {\n       // Should not happen given problem constraints, but as a failsafe,\n       // find any solution in the final beam and use it.\n       if(!beam.empty()){\n          best_solution = beam.top();\n       }\n    }\n    \n    for (const auto& macro_move : best_solution.history) {\n        for (int i = 0; i < macro_move.cost; ++i) {\n            cout << macro_move.dir << \" \" << macro_move.line_idx << \"\\n\";\n        }\n    }\n\n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <tuple>\n\n// --- Start of Timer and RNG Utilities ---\nclass Timer {\n    std::chrono::high_resolution_clock::time_point start_time;\npublic:\n    Timer() {\n        start_time = std::chrono::high_resolution_clock::now();\n    }\n    double get_elapsed_sec() {\n        auto now = std::chrono::high_resolution_clock::now();\n        return std::chrono::duration_cast<std::chrono::duration<double>>(now - start_time).count();\n    }\n};\n\nclass XorShiftRng {\n    uint64_t x;\npublic:\n    XorShiftRng(uint64_t seed) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 13;\n        x ^= x >> 7;\n        x ^= x << 17;\n        return x;\n    }\n    int next_int(int max) { // [0, max-1]\n        if (max <= 0) return 0;\n        return next() % max;\n    }\n    double next_double() { // [0.0, 1.0)\n        return static_cast<double>(next()) / UINT64_MAX;\n    }\n};\n// --- End of Timer and RNG Utilities ---\n\nconst int N_CONST = 100;\nconst int L_CONST = 500000;\nconst double TIME_LIMIT_SEC = 1.95;\n\nstruct EvalResult {\n    long long error;\n    std::vector<int> t;\n    std::vector<int> count_a;\n    std::vector<int> count_b;\n};\n\nEvalResult evaluate(const std::vector<int>& a, const std::vector<int>& b, const std::vector<int>& T) {\n    std::vector<int> t(N_CONST, 0);\n    std::vector<int> count_a(N_CONST, 0);\n    std::vector<int> count_b(N_CONST, 0);\n    \n    int cleaner = 0;\n    t[cleaner]++;\n    \n    for (int k = 1; k < L_CONST; ++k) {\n        int last_cleaner = cleaner;\n        int count_of_last_cleaner = t[last_cleaner];\n        \n        if (count_of_last_cleaner % 2 != 0) {\n            cleaner = a[last_cleaner];\n            count_a[last_cleaner]++;\n        } else {\n            cleaner = b[last_cleaner];\n            count_b[last_cleaner]++;\n        }\n        t[cleaner]++;\n    }\n    \n    long long error = 0;\n    for (int i = 0; i < N_CONST; ++i) {\n        error += std::abs(static_cast<long long>(t[i]) - T[i]);\n    }\n    \n    return {error, std::move(t), std::move(count_a), std::move(count_b)};\n}\n\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    Timer timer;\n    \n    int n_in, l_in;\n    std::cin >> n_in >> l_in; \n    std::vector<int> T(N_CONST);\n    for (int i = 0; i < N_CONST; ++i) {\n        std::cin >> T[i];\n    }\n\n    uint64_t seed = std::chrono::high_resolution_clock::now().time_since_epoch().count();\n    XorShiftRng rng(seed);\n\n    // --- Initial solution ---\n    std::vector<int> a(N_CONST), b(N_CONST);\n    \n    std::vector<double> weights;\n    double total_weight = 0;\n    for(int i = 0; i < N_CONST; ++i) {\n        double w = T[i] > 0 ? static_cast<double>(T[i]) : 1.0;\n        weights.push_back(w);\n        total_weight += w;\n    }\n    auto select_weighted = [&](const std::vector<double>& w, double total_w) {\n        double r = rng.next_double() * total_w;\n        for(size_t i = 0; i < w.size(); ++i) {\n            r -= w[i];\n            if (r <= 0) return (int)i;\n        }\n        return (int)w.size() - 1;\n    };\n    for (int i = 0; i < N_CONST; ++i) {\n        a[i] = select_weighted(weights, total_weight);\n        b[i] = select_weighted(weights, total_weight);\n    }\n\n    auto current_eval = evaluate(a, b, T);\n    long long current_error = current_eval.error;\n    auto& current_t = current_eval.t;\n    auto& current_count_a = current_eval.count_a;\n    auto& current_count_b = current_eval.count_b;\n\n    std::vector<int> best_a = a;\n    std::vector<int> best_b = b;\n    long long best_error = current_error;\n\n    // --- Simulated Annealing ---\n    double T_start = 2500.0;\n    double T_end = 0.1;\n\n    auto make_random_move = [&](std::vector<int>& target_a, std::vector<int>& target_b) {\n        int change_i = rng.next_int(N_CONST);\n        int change_ab = rng.next_int(2);\n        int new_val = rng.next_int(N_CONST);\n        if (change_ab == 0) {\n            target_a[change_i] = new_val;\n        } else {\n            target_b[change_i] = new_val;\n        }\n    };\n    \n    auto make_weighted_smart_move = [&](std::vector<int>& target_a, std::vector<int>& target_b) -> bool {\n        std::vector<std::pair<int, double>> over_candidates, under_candidates;\n        for (int i=0; i<N_CONST; ++i) {\n            if (current_t[i] > T[i]) over_candidates.push_back({i, (double)current_t[i] - T[i]});\n            else if (current_t[i] < T[i]) under_candidates.push_back({i, (double)T[i] - current_t[i]});\n        }\n        if (over_candidates.empty() || under_candidates.empty()) return false;\n        \n        double total_over_w = 0; for(const auto& p : over_candidates) total_over_w += p.second;\n        double r_over = rng.next_double() * total_over_w;\n        int v = -1;\n        for(const auto& p : over_candidates) { r_over -= p.second; if(r_over <= 0) {v = p.first; break;} }\n        if (v == -1) v = over_candidates.back().first;\n\n        double total_under_w = 0; for(const auto& p : under_candidates) total_under_w += p.second;\n        double r_under = rng.next_double() * total_under_w;\n        int w = -1;\n        for(const auto& p : under_candidates) { r_under -= p.second; if(r_under <= 0) {w = p.first; break;} }\n        if (w == -1) w = under_candidates.back().first;\n        \n        std::vector<std::tuple<int, int, double>> active_edges;\n        for (int u = 0; u < N_CONST; ++u) {\n            if (a[u] == v && current_count_a[u] > 0) active_edges.emplace_back(u, 0, current_count_a[u]);\n            if (b[u] == v && current_count_b[u] > 0) active_edges.emplace_back(u, 1, current_count_b[u]);\n        }\n        if (active_edges.empty()) return false;\n\n        double total_edge_w = 0; for(const auto& t : active_edges) total_edge_w += std::get<2>(t);\n        double r_edge = rng.next_double() * total_edge_w;\n        const auto* edge_to_change = &active_edges.back();\n        for(const auto& t : active_edges) { r_edge -= std::get<2>(t); if(r_edge <= 0) {edge_to_change = &t; break;} }\n\n        int u = std::get<0>(*edge_to_change), ab = std::get<1>(*edge_to_change);\n        if (ab == 0) target_a[u] = w; else target_b[u] = w;\n        return true;\n    };\n\n\n    while (timer.get_elapsed_sec() < TIME_LIMIT_SEC) {\n        double progress = timer.get_elapsed_sec() / TIME_LIMIT_SEC;\n        double temp = T_start * std::pow(T_end / T_start, progress);\n\n        std::vector<int> next_a = a;\n        std::vector<int> next_b = b;\n        \n        if (rng.next_double() < 0.05) {\n            make_random_move(next_a, next_b);\n        } else {\n            if (!make_weighted_smart_move(next_a, next_b)) {\n                make_random_move(next_a, next_b);\n            }\n        }\n        \n        auto neighbor_eval = evaluate(next_a, next_b, T);\n        long long neighbor_error = neighbor_eval.error;\n\n        double delta_e = static_cast<double>(neighbor_error) - current_error;\n\n        if (delta_e <= 0 || rng.next_double() < std::exp(-delta_e / temp)) {\n            a = std::move(next_a);\n            b = std::move(next_b);\n            current_error = neighbor_error;\n            current_t = std::move(neighbor_eval.t);\n            current_count_a = std::move(neighbor_eval.count_a);\n            current_count_b = std::move(neighbor_eval.count_b);\n            if (current_error < best_error) {\n                best_error = current_error;\n                best_a = a;\n                best_b = b;\n            }\n        }\n    }\n\n    for (int i = 0; i < N_CONST; ++i) {\n        std::cout << best_a[i] << \" \" << best_b[i] << \"\\n\";\n    }\n    \n    return 0;\n}","ahc045":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <set>\n#include <map>\n#include <queue>\n#include <tuple>\n#include <chrono>\n\n// Start timer\nauto start_time = std::chrono::high_resolution_clock::now();\ndouble time_limit = 1.95; // seconds\n\nstruct City {\n    int id;\n    long long lx, rx, ly, ry;\n    long long cx, cy;\n};\n\n// Z-order curve (Morton code)\nuint64_t z_order(uint32_t x, uint32_t y) {\n    uint64_t z = 0;\n    x &= 0x7FFF; // Max coord is 10000, 15 bits are enough\n    y &= 0x7FFF;\n    for (int i = 0; i < 15; ++i) {\n        z |= (static_cast<uint64_t>(x) & (1u << i)) << (i + 1);\n        z |= (static_cast<uint64_t>(y) & (1u << i)) << i;\n    }\n    return z;\n}\n\nstruct DSU {\n    std::vector<int> parent;\n    DSU(int n) {\n        parent.resize(n);\n        std::iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int i) {\n        if (parent[i] == i)\n            return i;\n        return parent[i] = find(parent[i]);\n    }\n    void unite(int i, int j) {\n        int root_i = find(i);\n        int root_j = find(j);\n        if (root_i != root_j) {\n            parent[root_i] = root_j;\n        }\n    }\n};\n\nlong double expected_dist_sq(const City& a, const City& b) {\n    long double w_a = a.rx - a.lx;\n    long double w_b = b.rx - b.lx;\n    long double h_a = a.ry - a.ly;\n    long double h_b = b.ry - b.ly;\n\n    long double var_x_a = w_a * w_a / 12.0;\n    long double var_x_b = w_b * w_b / 12.0;\n    long double var_y_a = h_a * h_a / 12.0;\n    long double var_y_b = h_b * h_b / 12.0;\n\n    long double mean_x_a = a.lx + w_a / 2.0;\n    long double mean_x_b = b.lx + w_b / 2.0;\n    long double mean_y_a = a.ly + h_a / 2.0;\n    long double mean_y_b = b.ly + h_b / 2.0;\n    \n    long double dx = mean_x_a - mean_x_b;\n    long double dy = mean_y_a - mean_y_b;\n    \n    return var_x_a + var_x_b + dx * dx + var_y_a + var_y_b + dy * dy;\n}\n\nstd::vector<std::pair<int, int>> do_query(const std::vector<int>& c) {\n    std::cout << \"? \" << c.size();\n    for (int city_id : c) {\n        std::cout << \" \" << city_id;\n    }\n    std::cout << std::endl;\n\n    std::vector<std::pair<int, int>> edges;\n    if (c.size() > 1) {\n        for (size_t i = 0; i < c.size() - 1; ++i) {\n            int u, v;\n            std::cin >> u >> v;\n            edges.emplace_back(u, v);\n        }\n    }\n    return edges;\n}\n\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    \n    std::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\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<City> cities(N);\n    for (int i = 0; i < N; ++i) {\n        cities[i].id = i;\n        std::cin >> cities[i].lx >> cities[i].rx >> cities[i].ly >> cities[i].ry;\n        cities[i].cx = (cities[i].lx + cities[i].rx) / 2;\n        cities[i].cy = (cities[i].ly + cities[i].ry) / 2;\n    }\n\n    // 1. Grouping\n    std::vector<int> city_indices(N);\n    std::iota(city_indices.begin(), city_indices.end(), 0);\n    std::sort(city_indices.begin(), city_indices.end(), [&](int a, int b) {\n        return z_order(cities[a].cx, cities[a].cy) < z_order(cities[b].cx, cities[b].cy);\n    });\n    \n    std::vector<std::vector<int>> groups(M);\n    int current_city_idx = 0;\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < G[i]; ++j) {\n            groups[i].push_back(city_indices[current_city_idx++]);\n        }\n    }\n    \n    // 2. Query Planning\n    std::vector<std::tuple<long double, int, int, int>> mst_edges_all_groups;\n    for (int k = 0; k < M; ++k) {\n        if (G[k] < 2) continue;\n        const auto& group_cities = groups[k];\n        std::vector<std::tuple<long double, int, int>> candidate_edges;\n        for (size_t i = 0; i < group_cities.size(); ++i) {\n            for (size_t j = i + 1; j < group_cities.size(); ++j) {\n                int u = group_cities[i];\n                int v = group_cities[j];\n                candidate_edges.emplace_back(expected_dist_sq(cities[u], cities[v]), u, v);\n            }\n        }\n        std::sort(candidate_edges.begin(), candidate_edges.end());\n\n        DSU mst_dsu(N);\n        for (const auto& [w, u, v] : candidate_edges) {\n            if (mst_dsu.find(u) != mst_dsu.find(v)) {\n                mst_dsu.unite(u, v);\n                mst_edges_all_groups.emplace_back(w, u, v, k);\n            }\n        }\n    }\n    std::sort(mst_edges_all_groups.begin(), mst_edges_all_groups.end());\n\n    // 3. Querying\n    int queries_left = Q;\n    DSU global_dsu(N);\n    std::vector<std::pair<int, int>> known_edges[M];\n    \n    // Phase 1: Connectivity\n    for (const auto& [w, u, v, k] : mst_edges_all_groups) {\n        if (queries_left == 0) break;\n        auto now = std::chrono::high_resolution_clock::now();\n        if (std::chrono::duration<double>(now - start_time).count() > time_limit) break;\n\n        if (global_dsu.find(u) != global_dsu.find(v)) {\n            std::vector<int> query_cities;\n            query_cities.push_back(u);\n            query_cities.push_back(v);\n            \n            long long mid_x = (cities[u].cx + cities[v].cx) / 2;\n            long long mid_y = (cities[u].cy + cities[v].cy) / 2;\n            \n            std::vector<std::pair<long long, int>> dist_to_mid;\n            for (int city_id : groups[k]) {\n                if (city_id == u || city_id == v) continue;\n                long long dx = cities[city_id].cx - mid_x;\n                long long dy = cities[city_id].cy - mid_y;\n                dist_to_mid.push_back({dx * dx + dy * dy, city_id});\n            }\n            std::sort(dist_to_mid.begin(), dist_to_mid.end());\n            for (size_t i = 0; i < dist_to_mid.size() && query_cities.size() < (size_t)L; ++i) {\n                query_cities.push_back(dist_to_mid[i].second);\n            }\n\n            auto edges = do_query(query_cities);\n            queries_left--;\n            for (const auto& edge : edges) {\n                known_edges[k].push_back(edge);\n                global_dsu.unite(edge.first, edge.second);\n            }\n        }\n    }\n    \n    // Phase 2: Improvement\n    using WeakLink = std::tuple<long double, int, int, int>;\n    std::priority_queue<WeakLink> weak_links_pq;\n    \n    for (int k = 0; k < M; ++k) {\n        for (const auto& edge : known_edges[k]) {\n            weak_links_pq.emplace(expected_dist_sq(cities[edge.first], cities[edge.second]), edge.first, edge.second, k);\n        }\n    }\n\n    while (queries_left > 0 && !weak_links_pq.empty()) {\n        auto now = std::chrono::high_resolution_clock::now();\n        if (std::chrono::duration<double>(now - start_time).count() > time_limit) break;\n\n        auto [w, u, v, k] = weak_links_pq.top();\n        weak_links_pq.pop();\n\n        std::vector<int> query_cities;\n        query_cities.push_back(u);\n        query_cities.push_back(v);\n        \n        long long mid_x = (cities[u].cx + cities[v].cx) / 2;\n        long long mid_y = (cities[u].cy + cities[v].cy) / 2;\n        \n        std::vector<std::pair<long long, int>> dist_to_mid;\n        for (int city_id : groups[k]) {\n            if (city_id == u || city_id == v) continue;\n            long long dx = cities[city_id].cx - mid_x;\n            long long dy = cities[city_id].cy - mid_y;\n            dist_to_mid.push_back({dx * dx + dy * dy, city_id});\n        }\n        std::sort(dist_to_mid.begin(), dist_to_mid.end());\n        for (size_t i = 0; i < dist_to_mid.size() && query_cities.size() < (size_t)L; ++i) {\n            query_cities.push_back(dist_to_mid[i].second);\n        }\n        \n        auto edges = do_query(query_cities);\n        queries_left--;\n        for (const auto& edge : edges) {\n            known_edges[k].push_back(edge);\n        }\n    }\n\n    // 4. Output\n    std::cout << \"!\" << std::endl;\n    for (int k = 0; k < M; ++k) {\n        for (size_t i = 0; i < groups[k].size(); ++i) {\n            std::cout << groups[k][i] << (i == groups[k].size() - 1 ? \"\" : \" \");\n        }\n        std::cout << std::endl;\n\n        if (G[k] > 1) {\n            std::vector<std::pair<int, int>> final_edges;\n            DSU group_dsu(N);\n            \n            std::sort(known_edges[k].begin(), known_edges[k].end());\n            known_edges[k].erase(std::unique(known_edges[k].begin(), known_edges[k].end()), known_edges[k].end());\n\n            for (const auto& edge : known_edges[k]) {\n                if (group_dsu.find(edge.first) != group_dsu.find(edge.second)) {\n                    group_dsu.unite(edge.first, edge.second);\n                    final_edges.push_back(edge);\n                }\n            }\n\n            if ((int)final_edges.size() < G[k] - 1) {\n                std::map<int, std::vector<int>> components;\n                for (int city_id : groups[k]) {\n                    components[group_dsu.find(city_id)].push_back(city_id);\n                }\n\n                if (components.size() > 1) {\n                    std::vector<std::tuple<long double, int, int>> component_edges;\n                    auto it1 = components.begin();\n                    while (it1 != components.end()) {\n                        auto it2 = std::next(it1);\n                        while (it2 != components.end()) {\n                            for (int c1 : it1->second) {\n                                for (int c2 : it2->second) {\n                                    component_edges.emplace_back(expected_dist_sq(cities[c1], cities[c2]), c1, c2);\n                                }\n                            }\n                            it2++;\n                        }\n                        it1++;\n                    }\n                    std::sort(component_edges.begin(), component_edges.end());\n                    \n                    for (const auto& [w, c1, c2] : component_edges) {\n                        if (group_dsu.find(c1) != group_dsu.find(c2)) {\n                            group_dsu.unite(c1, c2);\n                            final_edges.emplace_back(c1, c2);\n                        }\n                        if ((int)final_edges.size() >= G[k] - 1) break;\n                    }\n                }\n            }\n\n            for (const auto& edge : final_edges) {\n                std::cout << edge.first << \" \" << edge.second << std::endl;\n            }\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <map>\n#include <set>\n#include <cmath>\n#include <algorithm>\n#include <tuple>\n\nusing namespace std;\n\nconst int N = 20;\nconst int M = 40;\n\nstruct Pos {\n    int r, c;\n\n    bool operator<(const Pos& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n    bool operator==(const Pos& other) const {\n        return r == other.r && c == other.c;\n    }\n};\n\nint manhattan_distance(const Pos& a, const Pos& b) {\n    return abs(a.r - b.r) + abs(a.c - b.c);\n}\n\nbool is_valid(const Pos& p) {\n    return p.r >= 0 && p.r < N && p.c >= 0 && p.c < N;\n}\n\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\nconst char dir_char[] = {'U', 'D', 'L', 'R'};\n\nstruct Action {\n    char act, dir;\n};\n\nmap<Pos, int> dijkstra(const Pos& start, const set<Pos>& blocks) {\n    map<Pos, int> dist;\n    priority_queue<pair<int, Pos>, vector<pair<int, Pos>>, greater<pair<int, Pos>>> pq;\n\n    if (blocks.count(start)) return dist;\n\n    dist[start] = 0;\n    pq.push({0, start});\n\n    while (!pq.empty()) {\n        auto [cost, pos] = pq.top();\n        pq.pop();\n\n        if (cost > dist.at(pos)) {\n            continue;\n        }\n\n        // Move\n        for (int i = 0; i < 4; ++i) {\n            Pos next_pos = {pos.r + dr[i], pos.c + dc[i]};\n            if (is_valid(next_pos) && !blocks.count(next_pos)) {\n                int next_cost = cost + 1;\n                if (!dist.count(next_pos) || next_cost < dist.at(next_pos)) {\n                    dist[next_pos] = next_cost;\n                    pq.push({next_cost, next_pos});\n                }\n            }\n        }\n        \n        // Slide\n        for (int i = 0; i < 4; ++i) {\n            Pos stop_pos = pos;\n            Pos next_pos = {stop_pos.r + dr[i], stop_pos.c + dc[i]};\n            while (is_valid(next_pos) && !blocks.count(next_pos)) {\n                stop_pos = next_pos;\n                next_pos = {stop_pos.r + dr[i], stop_pos.c + dc[i]};\n            }\n            \n            if (stop_pos == pos) continue;\n\n            int next_cost = cost + 1;\n            if (!dist.count(stop_pos) || next_cost < dist.at(stop_pos)) {\n                dist[stop_pos] = next_cost;\n                pq.push({next_cost, stop_pos});\n            }\n        }\n    }\n    return dist;\n}\n\npair<int, vector<Action>> a_star_full(const Pos& start, const Pos& end, const set<Pos>& blocks) {\n    if (start == end) return {0, {}};\n    if (blocks.count(end)) return {1000000, {}};\n\n    map<Pos, int> dist;\n    map<Pos, Action> parent_action;\n    map<Pos, Pos> parent_pos;\n\n    priority_queue<pair<int, Pos>, vector<pair<int, Pos>>, greater<pair<int, Pos>>> pq;\n\n    dist[start] = 0;\n    pq.push({manhattan_distance(start, end), start});\n\n    while (!pq.empty()) {\n        auto [est_cost_pq, pos] = pq.top();\n        pq.pop();\n        \n        int cost = dist.at(pos);\n\n        if (pos == end) {\n            vector<Action> actions;\n            Pos curr = end;\n            while (!(curr == start)) {\n                actions.push_back(parent_action.at(curr));\n                curr = parent_pos.at(curr);\n            }\n            reverse(actions.begin(), actions.end());\n            return {cost, actions};\n        }\n\n        // Move\n        for (int i = 0; i < 4; ++i) {\n            Pos next_pos = {pos.r + dr[i], pos.c + dc[i]};\n            if (is_valid(next_pos) && !blocks.count(next_pos)) {\n                int next_cost = cost + 1;\n                if (!dist.count(next_pos) || next_cost < dist.at(next_pos)) {\n                    dist[next_pos] = next_cost;\n                    parent_pos[next_pos] = pos;\n                    parent_action[next_pos] = {'M', dir_char[i]};\n                    pq.push({next_cost + manhattan_distance(next_pos, end), next_pos});\n                }\n            }\n        }\n        \n        // Slide\n        for (int i = 0; i < 4; ++i) {\n            Pos stop_pos = pos;\n            Pos next_pos = {stop_pos.r + dr[i], stop_pos.c + dc[i]};\n            while (is_valid(next_pos) && !blocks.count(next_pos)) {\n                stop_pos = next_pos;\n                next_pos = {stop_pos.r + dr[i], stop_pos.c + dc[i]};\n            }\n            \n            if (stop_pos == pos) continue;\n\n            int next_cost = cost + 1;\n            if (!dist.count(stop_pos) || next_cost < dist.at(stop_pos)) {\n                dist[stop_pos] = next_cost;\n                parent_pos[stop_pos] = pos;\n                parent_action[stop_pos] = {'S', dir_char[i]};\n                pq.push({next_cost + manhattan_distance(stop_pos, end), stop_pos});\n            }\n        }\n    }\n\n    return {1000000, {}};\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N_in, M_in;\n    cin >> N_in >> M_in;\n\n    vector<Pos> targets(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> targets[i].r >> targets[i].c;\n    }\n\n    Pos current_pos = targets[0];\n    set<Pos> blocks;\n    vector<Action> total_actions;\n    \n    const int K = 20;\n\n    for (int k = 0; k < M - 1; ++k) {\n        Pos start_node = current_pos;\n        Pos end_node = targets[k + 1];\n\n        int best_cost = 1000000;\n        vector<Action> best_actions;\n        char best_plan_type = ' '; // B=base, A=add, R=remove\n        Pos best_alter_block, best_alter_adj;\n        \n        auto [base_cost, base_acts] = a_star_full(start_node, end_node, blocks);\n        if (base_cost < best_cost) {\n            best_cost = base_cost;\n            best_actions = base_acts;\n            best_plan_type = 'B';\n        }\n\n        auto dist_from_start = dijkstra(start_node, blocks);\n\n        set<Pos> cand_targets;\n        cand_targets.insert(end_node);\n        cand_targets.insert({start_node.r, end_node.c});\n        cand_targets.insert({end_node.r, start_node.c});\n        \n        set<Pos> cand_add_blocks;\n        for(const auto& t : cand_targets) {\n            for(int i=0; i<4; ++i) {\n                cand_add_blocks.insert({t.r + dr[i], t.c + dc[i]});\n            }\n        }\n\n        for (const auto& b : cand_add_blocks) {\n            if (!is_valid(b) || blocks.count(b)) continue;\n\n            set<Pos> next_blocks = blocks;\n            next_blocks.insert(b);\n            auto dist_to_end = dijkstra(end_node, next_blocks);\n            \n            for (int i = 0; i < 4; ++i) {\n                Pos adj_b = {b.r - dr[i], b.c - dc[i]};\n                if (!is_valid(adj_b) || blocks.count(adj_b)) continue;\n                \n                if (dist_from_start.count(adj_b) && dist_to_end.count(adj_b)) {\n                    int cost = dist_from_start.at(adj_b) + 1 + dist_to_end.at(adj_b);\n                    if (cost < best_cost) {\n                        best_cost = cost;\n                        best_plan_type = 'A';\n                        best_alter_block = b;\n                        best_alter_adj = adj_b;\n                    }\n                }\n            }\n        }\n\n        for (const auto& b : blocks) {\n            set<Pos> next_blocks = blocks;\n            next_blocks.erase(b);\n            auto dist_to_end = dijkstra(end_node, next_blocks);\n\n            for (int i = 0; i < 4; ++i) {\n                Pos adj_b = {b.r - dr[i], b.c - dc[i]};\n                if (!is_valid(adj_b) || blocks.count(adj_b)) continue;\n                \n                if (dist_from_start.count(adj_b) && dist_to_end.count(adj_b)) {\n                    int cost = dist_from_start.at(adj_b) + 1 + dist_to_end.at(adj_b);\n                     if (cost < best_cost) {\n                        best_cost = cost;\n                        best_plan_type = 'R';\n                        best_alter_block = b;\n                        best_alter_adj = adj_b;\n                    }\n                }\n            }\n        }\n        \n        if (best_cost >= 1000000) {\n            // Target is unreachable, just update position and hope for the best\n            // This case should ideally not happen in this problem\n        } else if (best_plan_type == 'B') {\n            total_actions.insert(total_actions.end(), best_actions.begin(), best_actions.end());\n        } else {\n            auto [c1, p1] = a_star_full(start_node, best_alter_adj, blocks);\n            total_actions.insert(total_actions.end(), p1.begin(), p1.end());\n            \n            char alter_dir = ' ';\n            for (int j = 0; j < 4; ++j) {\n                if (best_alter_block.r == best_alter_adj.r + dr[j] && best_alter_block.c == best_alter_adj.c + dc[j]) {\n                    alter_dir = dir_char[j];\n                    break;\n                }\n            }\n            total_actions.push_back({'A', alter_dir});\n\n            if (best_plan_type == 'A') {\n                blocks.insert(best_alter_block);\n            } else { // 'R'\n                blocks.erase(best_alter_block);\n            }\n            auto [c2, p2] = a_star_full(best_alter_adj, end_node, blocks);\n            total_actions.insert(total_actions.end(), p2.begin(), p2.end());\n        }\n        current_pos = end_node;\n\n        if (blocks.size() > K) {\n            Pos to_evict;\n            long long max_score = -1;\n\n            for (const auto& b : blocks) {\n                long long current_score = 0;\n                for (int i = k + 2; i < M; ++i) {\n                    current_score += manhattan_distance(b, targets[i]);\n                }\n                if (current_score > max_score) {\n                    max_score = current_score;\n                    to_evict = b;\n                }\n            }\n            \n            Pos adj_to_evict;\n            int min_dist = 1000000;\n            \n            auto dist_from_curr = dijkstra(current_pos, blocks);\n            \n            for (int i = 0; i < 4; ++i) {\n                Pos adj_b = {to_evict.r - dr[i], to_evict.c - dc[i]};\n                if (is_valid(adj_b) && !blocks.count(adj_b)) {\n                    if (dist_from_curr.count(adj_b)) {\n                        int d = dist_from_curr.at(adj_b);\n                        if (d < min_dist) {\n                            min_dist = d;\n                            adj_to_evict = adj_b;\n                        }\n                    }\n                }\n            }\n\n            if (min_dist < 1000000) {\n                auto [c, p] = a_star_full(current_pos, adj_to_evict, blocks);\n                total_actions.insert(total_actions.end(), p.begin(), p.end());\n                current_pos = adj_to_evict;\n\n                char alter_dir = ' ';\n                 for (int j = 0; j < 4; ++j) {\n                    if (to_evict.r == current_pos.r + dr[j] && to_evict.c == current_pos.c + dc[j]) {\n                        alter_dir = dir_char[j];\n                        break;\n                    }\n                }\n                total_actions.push_back({'A', alter_dir});\n                blocks.erase(to_evict);\n            }\n        }\n    }\n\n    for (const auto& action : total_actions) {\n        cout << action.act << \" \" << action.dir << \"\\n\";\n    }\n\n    return 0;\n}"},"8":{"ahc001":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <cfloat>\n#include <chrono>\n#include <random>\n\n// --- Utilities and Structs ---\nstruct Company {\n    int id;\n    int x, y;\n    long long r;\n};\n\nstruct Rect {\n    int x1, y1, x2, y2;\n};\n\nstruct PointBox {\n    int min_x = 10001, min_y = 10001, max_x = -1, max_y = -1;\n    void update(const Company& c) {\n        min_x = std::min(min_x, c.x);\n        min_y = std::min(min_y, c.y);\n        max_x = std::max(max_x, c.x);\n        max_y = std::max(max_y, c.y);\n    }\n    void merge(const PointBox& other) {\n        min_x = std::min(min_x, other.min_x);\n        min_y = std::min(min_y, other.min_y);\n        max_x = std::max(max_x, other.max_x);\n        max_y = std::max(max_y, other.max_y);\n    }\n};\n\nstruct Node {\n    bool is_leaf = false;\n    int company_id = -1;\n\n    // For internal nodes\n    int parent = -1;\n    bool is_vertical = false;\n    int split_coord = 0;\n    int children[2] = {-1, -1};\n    std::vector<int> company_indices;\n    PointBox pbox;\n};\n\n// --- Global State ---\nint N;\nstd::vector<Company> companies;\nstd::vector<bool> is_in_partition1; // Temporary helper for partitioning\n\n// --- For SA ---\nstd::vector<Node> tree;\nstd::vector<int> internal_node_indices;\nstd::mt19937 rnd;\nstd::chrono::time_point<std::chrono::high_resolution_clock> start_time_chrono;\nstd::vector<Rect> best_result;\ndouble best_score = -1.0;\nstd::vector<Rect> current_result;\ndouble current_score;\n\n// --- Helper Functions ---\ndouble get_time() {\n    return std::chrono::duration<double>(std::chrono::high_resolution_clock::now() - start_time_chrono).count();\n}\n\ndouble calculate_satisfaction(long long s, long long r) {\n    if (s <= 0 || r <= 0) return 0;\n    double ratio = std::min((double)s / r, (double)r / s);\n    double error = 1.0 - ratio;\n    return 1.0 - error * error;\n}\n\ndouble calculate_total_score(const std::vector<Rect>& rects) {\n    double total_sat = 0;\n    for (int i = 0; i < N; ++i) {\n        long long s = (long long)(rects[i].x2 - rects[i].x1) * (rects[i].y2 - rects[i].y1);\n        total_sat += calculate_satisfaction(s, companies[i].r);\n    }\n    return total_sat;\n}\n\n// --- Core Algorithm: Greedy Construction + SA ---\n\nint build_tree(int x1, int y1, int x2, int y2, std::vector<int>& indices_by_x, std::vector<int>& indices_by_y, int parent_idx) {\n    int n = indices_by_x.size();\n    int current_node_idx = tree.size();\n    tree.emplace_back();\n    tree[current_node_idx].parent = parent_idx;\n    \n    if (n == 0) return -1;\n\n    if (n == 1) {\n        int company_idx = indices_by_x[0];\n        tree[current_node_idx].is_leaf = true;\n        tree[current_node_idx].company_id = company_idx;\n        tree[current_node_idx].company_indices = {company_idx};\n        tree[current_node_idx].pbox.update(companies[company_idx]);\n        return current_node_idx;\n    }\n\n    int best_k_v = -1, best_x_split = -1;\n    double min_badness_v = DBL_MAX;\n    long long total_r = 0;\n    for (int idx : indices_by_x) total_r += companies[idx].r;\n    \n    if (companies[indices_by_x.front()].x < companies[indices_by_x.back()].x) {\n        long long current_r_sum = 0;\n        for (int k = 1; k < n; ++k) {\n            current_r_sum += companies[indices_by_x[k - 1]].r;\n            if (companies[indices_by_x[k - 1]].x < companies[indices_by_x[k]].x) {\n                double target_ratio = (double)current_r_sum / total_r;\n                double ideal_x_split = x1 + (double)(x2 - x1) * target_ratio;\n                int lower_bound = companies[indices_by_x[k - 1]].x + 1;\n                int upper_bound = companies[indices_by_x[k]].x;\n                \n                std::vector<int> candidates;\n                candidates.push_back(std::max(lower_bound, std::min(upper_bound, (int)round(ideal_x_split))));\n                candidates.push_back(lower_bound);\n                candidates.push_back(upper_bound);\n                std::sort(candidates.begin(), candidates.end());\n                candidates.erase(std::unique(candidates.begin(), candidates.end()), candidates.end());\n\n                for (int x_split : candidates) {\n                    double actual_ratio = (x2 - x1 == 0) ? 0.5 : (double)(x_split - x1) / (x2 - x1);\n                    double badness = std::pow(actual_ratio - target_ratio, 2);\n                    if (badness < min_badness_v) {\n                        min_badness_v = badness;\n                        best_k_v = k;\n                        best_x_split = x_split;\n                    }\n                }\n            }\n        }\n    }\n\n    int best_k_h = -1, best_y_split = -1;\n    double min_badness_h = DBL_MAX;\n    if (companies[indices_by_y.front()].y < companies[indices_by_y.back()].y) {\n        long long current_r_sum = 0;\n        for (int k = 1; k < n; ++k) {\n            current_r_sum += companies[indices_by_y[k - 1]].r;\n            if (companies[indices_by_y[k - 1]].y < companies[indices_by_y[k]].y) {\n                double target_ratio = (double)current_r_sum / total_r;\n                double ideal_y_split = y1 + (double)(y2 - y1) * target_ratio;\n                int lower_bound = companies[indices_by_y[k - 1]].y + 1;\n                int upper_bound = companies[indices_by_y[k]].y;\n\n                std::vector<int> candidates;\n                candidates.push_back(std::max(lower_bound, std::min(upper_bound, (int)round(ideal_y_split))));\n                candidates.push_back(lower_bound);\n                candidates.push_back(upper_bound);\n                std::sort(candidates.begin(), candidates.end());\n                candidates.erase(std::unique(candidates.begin(), candidates.end()), candidates.end());\n                \n                for (int y_split : candidates) {\n                     double actual_ratio = (y2 - y1 == 0) ? 0.5 : (double)(y_split - y1) / (y2 - y1);\n                     double badness = std::pow(actual_ratio - target_ratio, 2);\n                     if (badness < min_badness_h) {\n                         min_badness_h = badness;\n                         best_k_h = k;\n                         best_y_split = y_split;\n                     }\n                }\n            }\n        }\n    }\n\n    bool perform_vertical_split;\n    if (best_k_v == -1) {\n        perform_vertical_split = false;\n    } else if (best_k_h == -1) {\n        perform_vertical_split = true;\n    } else {\n        constexpr double TIE_TOLERANCE = 1.05;\n        if (min_badness_v < min_badness_h * TIE_TOLERANCE && min_badness_h < min_badness_v * TIE_TOLERANCE) {\n            perform_vertical_split = (x2 - x1) >= (y2 - y1);\n        } else {\n            perform_vertical_split = min_badness_v < min_badness_h;\n        }\n    }\n    \n    internal_node_indices.push_back(current_node_idx);\n    tree[current_node_idx].is_vertical = perform_vertical_split;\n    \n    if (perform_vertical_split) {\n        tree[current_node_idx].split_coord = best_x_split;\n        int k = best_k_v;\n        for (int i = 0; i < k; ++i) is_in_partition1[indices_by_x[i]] = true;\n        for (int i = k; i < n; ++i) is_in_partition1[indices_by_x[i]] = false;\n        std::vector<int> left_x(indices_by_x.begin(), indices_by_x.begin() + k);\n        std::vector<int> right_x(indices_by_x.begin() + k, indices_by_x.end());\n        std::vector<int> left_y, right_y;\n        for (int idx : indices_by_y) (is_in_partition1[idx] ? left_y : right_y).push_back(idx);\n        tree[current_node_idx].children[0] = build_tree(x1, y1, best_x_split, y2, left_x, left_y, current_node_idx);\n        tree[current_node_idx].children[1] = build_tree(best_x_split, y1, x2, y2, right_x, right_y, current_node_idx);\n    } else {\n        tree[current_node_idx].split_coord = best_y_split;\n        int k = best_k_h;\n        for (int i = 0; i < k; ++i) is_in_partition1[indices_by_y[i]] = true;\n        for (int i = k; i < n; ++i) is_in_partition1[indices_by_y[i]] = false;\n        std::vector<int> bottom_y(indices_by_y.begin(), indices_by_y.begin() + k);\n        std::vector<int> top_y(indices_by_y.begin() + k, indices_by_y.end());\n        std::vector<int> bottom_x, top_x;\n        for (int idx : indices_by_x) (is_in_partition1[idx] ? bottom_x : top_x).push_back(idx);\n        tree[current_node_idx].children[0] = build_tree(x1, y1, x2, best_y_split, bottom_x, bottom_y, current_node_idx);\n        tree[current_node_idx].children[1] = build_tree(x1, best_y_split, x2, y2, top_x, top_y, current_node_idx);\n    }\n\n    tree[current_node_idx].pbox = tree[tree[current_node_idx].children[0]].pbox;\n    tree[current_node_idx].pbox.merge(tree[tree[current_node_idx].children[1]].pbox);\n    tree[current_node_idx].company_indices = tree[tree[current_node_idx].children[0]].company_indices;\n    tree[current_node_idx].company_indices.insert(\n        tree[current_node_idx].company_indices.end(),\n        tree[tree[current_node_idx].children[1]].company_indices.begin(),\n        tree[tree[current_node_idx].children[1]].company_indices.end()\n    );\n    return current_node_idx;\n}\n\nvoid recompute_rects(int node_idx, const Rect& bbox, std::vector<Rect>& target_rects) {\n    if (node_idx == -1) return;\n    const auto& node = tree[node_idx];\n    if (node.is_leaf) {\n        target_rects[node.company_id] = bbox;\n        return;\n    }\n    if (node.is_vertical) {\n        recompute_rects(node.children[0], {bbox.x1, bbox.y1, node.split_coord, bbox.y2}, target_rects);\n        recompute_rects(node.children[1], {node.split_coord, bbox.y1, bbox.x2, bbox.y2}, target_rects);\n    } else {\n        recompute_rects(node.children[0], {bbox.x1, bbox.y1, bbox.x2, node.split_coord}, target_rects);\n        recompute_rects(node.children[1], {bbox.x1, node.split_coord, bbox.x2, bbox.y2}, target_rects);\n    }\n}\n\nRect get_bbox(int node_idx) {\n    if (tree[node_idx].parent == -1) return {0, 0, 10000, 10000};\n    const auto& parent = tree[tree[node_idx].parent];\n    Rect parent_bbox = get_bbox(tree[node_idx].parent);\n    bool is_child0 = (parent.children[0] == node_idx);\n    if (parent.is_vertical) {\n        return is_child0 ? Rect{parent_bbox.x1, parent_bbox.y1, parent.split_coord, parent_bbox.y2}\n                         : Rect{parent.split_coord, parent_bbox.y1, parent_bbox.x2, parent_bbox.y2};\n    } else {\n        return is_child0 ? Rect{parent_bbox.x1, parent_bbox.y1, parent_bbox.x2, parent.split_coord}\n                         : Rect{parent_bbox.x1, parent.split_coord, parent_bbox.x2, parent_bbox.y2};\n    }\n}\n\n\nvoid simulated_annealing() {\n    const double TIME_LIMIT = 4.95;\n    \n    current_score = calculate_total_score(current_result);\n    best_score = current_score;\n    best_result = current_result;\n    \n    double T_start = 0.1, T_end = 1e-9;\n    \n    std::uniform_int_distribution<int> node_dist(0, internal_node_indices.size() - 1);\n    std::uniform_real_distribution<double> accept_dist(0.0, 1.0);\n\n    while (true) {\n        double elapsed_time = get_time();\n        if (elapsed_time > TIME_LIMIT) break;\n\n        int node_idx = internal_node_indices[node_dist(rnd)];\n        auto& node = tree[node_idx];\n        \n        int c_old = node.split_coord;\n        int c_min, c_max;\n        if (node.is_vertical) {\n            c_min = tree[node.children[0]].pbox.max_x + 1;\n            c_max = tree[node.children[1]].pbox.min_x;\n        } else {\n            c_min = tree[node.children[0]].pbox.max_y + 1;\n            c_max = tree[node.children[1]].pbox.min_y;\n        }\n        \n        if (c_min > c_max) continue;\n        int range = c_max - c_min;\n        if (range == 0) continue;\n        \n        double progress = elapsed_time / TIME_LIMIT;\n        double W = std::max(1.0, 0.25 * static_cast<double>(range) * (1.0 - progress));\n        \n        std::uniform_int_distribution<int> delta_dist(-(int)W, (int)W);\n        int c_new = c_old + delta_dist(rnd);\n        c_new = std::max(c_min, std::min(c_max, c_new));\n\n        if (c_new == c_old) continue;\n        \n        double score_before_move = 0;\n        for (int company_idx : node.company_indices) {\n            const auto& rect = current_result[company_idx];\n            long long s = (long long)(rect.x2 - rect.x1) * (rect.y2 - rect.y1);\n            score_before_move += calculate_satisfaction(s, companies[company_idx].r);\n        }\n\n        node.split_coord = c_new;\n        Rect bbox = get_bbox(node_idx);\n        recompute_rects(node_idx, bbox, current_result);\n        \n        double score_after_move = 0;\n        for (int company_idx : node.company_indices) {\n            const auto& rect = current_result[company_idx];\n            long long s = (long long)(rect.x2 - rect.x1) * (rect.y2 - rect.y1);\n            score_after_move += calculate_satisfaction(s, companies[company_idx].r);\n        }\n\n        double delta_score = score_after_move - score_before_move;\n        double T = T_start * std::pow(T_end / T_start, progress);\n\n        if (delta_score > 0 || accept_dist(rnd) < std::exp(delta_score / T)) { // Accept\n            current_score += delta_score;\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_result = current_result;\n            }\n        } else { // Reject\n            node.split_coord = c_old;\n            recompute_rects(node_idx, bbox, current_result);\n        }\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    start_time_chrono = std::chrono::high_resolution_clock::now();\n    \n    rnd.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());\n    \n    std::cin >> N;\n    companies.resize(N);\n    is_in_partition1.resize(N);\n    tree.reserve(2 * N);\n\n    std::vector<int> indices_by_x(N), indices_by_y(N);\n    for (int i = 0; i < N; ++i) {\n        companies[i].id = i;\n        std::cin >> companies[i].x >> companies[i].y >> companies[i].r;\n        indices_by_x[i] = i;\n        indices_by_y[i] = i;\n    }\n\n    std::sort(indices_by_x.begin(), indices_by_x.end(), [&](int a, int b) {\n        if (companies[a].x != companies[b].x) return companies[a].x < companies[b].x;\n        return companies[a].y < companies[b].y;\n    });\n    std::sort(indices_by_y.begin(), indices_by_y.end(), [&](int a, int b) {\n        if (companies[a].y != companies[b].y) return companies[a].y < companies[b].y;\n        return companies[a].x < companies[b].x;\n    });\n\n    int root_node = build_tree(0, 0, 10000, 10000, indices_by_x, indices_by_y, -1);\n    \n    current_result.resize(N);\n    recompute_rects(root_node, {0, 0, 10000, 10000}, current_result);\n\n    simulated_annealing();\n\n    for (int i = 0; i < N; ++i) {\n        std::cout << best_result[i].x1 << \" \" << best_result[i].y1 << \" \" << best_result[i].x2 << \" \" << best_result[i].y2 << \"\\n\";\n    }\n\n    return 0;\n}","ahc002":"#include <iostream>\n#include <vector>\n#include <string>\n#include <map>\n#include <utility>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n\n// Fast I/O\nvoid fast_io() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n}\n\n// Timer\nstruct Timer {\n    std::chrono::steady_clock::time_point start_time;\n    Timer() : start_time(std::chrono::steady_clock::now()) {}\n    long long get_ms() {\n        return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count();\n    }\n};\n\nconstexpr int N = 50;\n\n#ifdef LOCAL_TEST\nconstexpr int TIME_LIMIT_MS = 1980;\nconstexpr int BEAM_WIDTH = 200;\n#else\nconstexpr int TIME_LIMIT_MS = 1980;\nconstexpr int BEAM_WIDTH = 2000;\n#endif\n\nint si, sj;\nint t[N][N];\nint p[N][N];\n\nstruct Tile {\n    int id;\n    std::vector<std::pair<int, int>> squares;\n};\n\nint tile_id_map[N][N];\nstd::vector<Tile> tiles;\nint M; // number of tiles\n\nstruct State {\n    long long score;\n    std::pair<int, int> pos;\n    std::vector<bool> visited_tiles;\n\n    int prev_idx_in_history;\n    std::string path_segment;\n};\n\nchar get_move_char(const std::pair<int, int>& from, const std::pair<int, int>& to) {\n    if (to.first == from.first - 1 && to.second == from.second) return 'U';\n    if (to.first == from.first + 1 && to.second == from.second) return 'D';\n    if (to.second == from.second - 1 && to.first == from.first) return 'L';\n    if (to.second == from.second + 1 && to.first == from.first) return 'R';\n    return ' '; // Should not happen\n}\n\nvoid solve() {\n    Timer timer;\n\n    std::cin >> si >> sj;\n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) std::cin >> t[i][j];\n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) std::cin >> p[i][j];\n\n    std::map<int, int> raw_id_to_my_id;\n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) {\n        if (raw_id_to_my_id.find(t[i][j]) == raw_id_to_my_id.end()) {\n            raw_id_to_my_id[t[i][j]] = raw_id_to_my_id.size();\n        }\n    }\n    M = raw_id_to_my_id.size();\n    tiles.resize(M);\n    for (int i=0; i<M; ++i) tiles[i].id = i;\n\n    for (int i=0; i<N; ++i) for(int j=0; j<N; ++j) {\n        int my_id = raw_id_to_my_id[t[i][j]];\n        tile_id_map[i][j] = my_id;\n        tiles[my_id].squares.push_back({i,j});\n    }\n\n    State initial_state;\n    int start_tile_id = tile_id_map[si][sj];\n    const auto& start_tile = tiles[start_tile_id];\n    \n    initial_state.score = 0;\n    initial_state.visited_tiles.assign(M, false);\n    initial_state.visited_tiles[start_tile_id] = true;\n    initial_state.prev_idx_in_history = -1;\n\n    std::pair<int, int> current_pos = {si, sj};\n    initial_state.score += p[si][sj];\n\n    if (start_tile.squares.size() == 2) {\n        std::pair<int, int> other_pos = (start_tile.squares[0] == current_pos) ? start_tile.squares[1] : start_tile.squares[0];\n        char move = get_move_char(current_pos, other_pos);\n        initial_state.path_segment += move;\n        initial_state.score += p[other_pos.first][other_pos.second];\n        current_pos = other_pos;\n    }\n    initial_state.pos = current_pos;\n\n    long long best_score = initial_state.score;\n    std::pair<int, int> best_state_locus = {0, 0};\n\n    std::vector<std::vector<State>> history;\n    std::vector<State> beam;\n    beam.push_back(std::move(initial_state));\n    history.push_back(std::move(beam));\n    \n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n    char move_chars[] = {'U', 'D', 'L', 'R'};\n\n    while (timer.get_ms() < TIME_LIMIT_MS) {\n        const auto& current_beam = history.back();\n        std::vector<State> candidates;\n        \n        for (int i = 0; i < current_beam.size(); ++i) {\n            const auto& s = current_beam[i];\n            int r = s.pos.first;\n            int c = s.pos.second;\n\n            for (int k = 0; k < 4; ++k) {\n                int nr = r + dr[k];\n                int nc = c + dc[k];\n\n                if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n\n                int next_tile_id = tile_id_map[nr][nc];\n                if (s.visited_tiles[next_tile_id]) continue;\n\n                State new_s;\n                new_s.visited_tiles = s.visited_tiles;\n                new_s.visited_tiles[next_tile_id] = true;\n\n                std::string path_ext;\n                long long score_ext = 0;\n                std::pair<int, int> next_pos = {nr, nc};\n\n                path_ext += move_chars[k];\n                score_ext += p[nr][nc];\n\n                const auto& next_tile = tiles[next_tile_id];\n                if (next_tile.squares.size() == 2) {\n                    std::pair<int, int> other_pos = (next_tile.squares[0] == next_pos) ? next_tile.squares[1] : next_tile.squares[0];\n                    char move = get_move_char(next_pos, other_pos);\n                    path_ext += move;\n                    score_ext += p[other_pos.first][other_pos.second];\n                    next_pos = other_pos;\n                }\n                \n                new_s.score = s.score + score_ext;\n                new_s.pos = next_pos;\n                new_s.path_segment = path_ext;\n                new_s.prev_idx_in_history = i;\n                candidates.push_back(std::move(new_s));\n            }\n        }\n\n        if (candidates.empty()) break;\n\n        size_t sort_end_idx = std::min((size_t)candidates.size(), (size_t)BEAM_WIDTH);\n        std::partial_sort(candidates.begin(), candidates.begin() + sort_end_idx, candidates.end(), \n            [](const State& a, const State& b){ return a.score > b.score; });\n\n        std::vector<State> next_beam;\n        next_beam.reserve(sort_end_idx);\n        for (int i = 0; i < sort_end_idx; ++i) {\n            next_beam.push_back(std::move(candidates[i]));\n        }\n        \n        if (next_beam[0].score > best_score) {\n            best_score = next_beam[0].score;\n            best_state_locus = {(int)history.size(), 0};\n        }\n        history.push_back(std::move(next_beam));\n    }\n    \n    std::string final_path = \"\";\n    int hist_idx = best_state_locus.first;\n    int beam_idx = best_state_locus.second;\n    while (hist_idx >= 0) {\n        const auto& s = history[hist_idx][beam_idx];\n        final_path = s.path_segment + final_path;\n        if (s.prev_idx_in_history == -1) break;\n        beam_idx = s.prev_idx_in_history;\n        hist_idx--;\n    }\n    std::cout << final_path << std::endl;\n}\n\nint main() {\n    fast_io();\n    solve();\n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <numeric>\n#include <random>\n#include <algorithm>\n#include <iomanip>\n#include <chrono>\n\n// Constants\nconstexpr int GRID_SIZE = 30;\nconstexpr int NUM_QUERIES = 1000;\n\n// Grid coordinates\nstruct Point {\n    int r, c;\n    bool operator==(const Point& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Point& other) const {\n        return !(*this == other);\n    }\n};\n\n// For priority queue in Dijkstra\nstruct State {\n    Point pos;\n    double dist;\n\n    bool operator>(const State& other) const {\n        return dist > other.dist;\n    }\n};\n\n// Global state for our estimates and models\ndouble est_h[GRID_SIZE][GRID_SIZE - 1]; // Raw estimates\ndouble est_v[GRID_SIZE - 1][GRID_SIZE];\ndouble model_h[GRID_SIZE][GRID_SIZE - 1]; // Smoothed/model-based estimates\ndouble model_v[GRID_SIZE - 1][GRID_SIZE];\nint updates_h[GRID_SIZE][GRID_SIZE - 1];\nint updates_v[GRID_SIZE - 1][GRID_SIZE];\nint global_M = 1; // Start with assumption M=1, decide definitively later\n\n// Randomness\nstd::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// Helper function to check bounds\nbool is_valid(int r, int c) {\n    return r >= 0 && r < GRID_SIZE && c >= 0 && c < GRID_SIZE;\n}\n\n// For model fitting\nstruct ModelFitResult {\n    double sse1 = 0.0;\n    double sse2 = 1e18;\n    int split_point = -1;\n    double mean1 = 5000.0;\n    double mean_l = 5000.0, mean_r = 5000.0;\n    int n_pts = 0;\n};\n\n// Dijkstra's algorithm\nPoint parent[GRID_SIZE][GRID_SIZE];\nchar move_char[GRID_SIZE][GRID_SIZE];\ndouble dist[GRID_SIZE][GRID_SIZE];\n\nstd::string find_path(Point start, Point goal, int k) {\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            dist[i][j] = 1e18;\n        }\n    }\n\n    std::priority_queue<State, std::vector<State>, std::greater<State>> pq;\n    dist[start.r][start.c] = 0;\n    pq.push({start, 0.0});\n\n    double progress = static_cast<double>(k) / (NUM_QUERIES - 1);\n    double C_k = 0.3 * (1.0 - std::pow(progress, 1.5));\n    if (k > NUM_QUERIES - 50) C_k = 0;\n    \n    double lambda_k = 400.0 * (1.0 - progress);\n\n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n    char moves[] = {'U', 'D', 'L', 'R'};\n    \n    std::uniform_real_distribution<double> dist_expl(1.0 - C_k, 1.0 + C_k);\n\n    while (!pq.empty()) {\n        State current = pq.top();\n        pq.pop();\n        Point pos = current.pos;\n\n        if (current.dist > dist[pos.r][pos.c]) continue;\n        if (pos == goal) break;\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = pos.r + dr[i];\n            int nc = pos.c + dc[i];\n            if (!is_valid(nr, nc)) continue;\n\n            double edge_cost;\n            int updates_count;\n            if (i == 0) { // Up\n                edge_cost = model_v[nr][nc]; updates_count = updates_v[nr][nc];\n            } else if (i == 1) { // Down\n                edge_cost = model_v[pos.r][pos.c]; updates_count = updates_v[pos.r][pos.c];\n            } else if (i == 2) { // Left\n                edge_cost = model_h[nr][nc]; updates_count = updates_h[nr][nc];\n            } else { // Right\n                edge_cost = model_h[pos.r][pos.c]; updates_count = updates_h[pos.r][pos.c];\n            }\n            \n            double noisy_cost = edge_cost * dist_expl(rng);\n            double ucb_bonus = lambda_k / std::sqrt(updates_count + 1.0);\n            noisy_cost -= ucb_bonus;\n            \n            if (dist[pos.r][pos.c] + std::max(1.0, noisy_cost) < dist[nr][nc]) {\n                dist[nr][nc] = dist[pos.r][pos.c] + std::max(1.0, noisy_cost);\n                parent[nr][nc] = pos;\n                move_char[nr][nc] = moves[i];\n                pq.push({{nr, nc}, dist[nr][nc]});\n            }\n        }\n    }\n\n    std::string path_str = \"\";\n    Point current = goal;\n    while (current != start) {\n        path_str += move_char[current.r][current.c];\n        current = parent[current.r][current.c];\n    }\n    std::reverse(path_str.begin(), path_str.end());\n    return path_str;\n}\n\nvoid update_estimates(const std::string& path_str, Point start, long long noisy_path_length, int k) {\n    if (path_str.empty()) return;\n\n    double estimated_length = 0;\n    double Z = 0.0;\n    \n    Point current = start;\n    for (char move : path_str) {\n        Point next = current;\n        if (move == 'U') {\n            next.r--; estimated_length += est_v[next.r][next.c]; Z += 1.0 / (updates_v[next.r][next.c] + 1.0);\n        } else if (move == 'D') {\n            estimated_length += est_v[current.r][current.c]; Z += 1.0 / (updates_v[current.r][current.c] + 1.0); next.r++;\n        } else if (move == 'L') {\n            next.c--; estimated_length += est_h[next.r][next.c]; Z += 1.0 / (updates_h[next.r][next.c] + 1.0);\n        } else {\n            estimated_length += est_h[current.r][current.c]; Z += 1.0 / (updates_h[current.r][current.c] + 1.0); next.c++;\n        }\n        current = next;\n    }\n    \n    if (Z < 1e-9) return;\n\n    double error = static_cast<double>(noisy_path_length) - estimated_length;\n    double alpha_k = 0.5 * std::pow(0.01, static_cast<double>(k) / (NUM_QUERIES - 1));\n    double base_update = alpha_k * error / Z;\n\n    current = start;\n    for (char move : path_str) {\n        Point next = current;\n        if (move == 'U') {\n            next.r--; double w = 1.0 / (updates_v[next.r][next.c] + 1.0);\n            est_v[next.r][next.c] = std::clamp(est_v[next.r][next.c] + base_update * w, 500.0, 10000.0);\n            updates_v[next.r][next.c]++;\n        } else if (move == 'D') {\n            double w = 1.0 / (updates_v[current.r][current.c] + 1.0);\n            est_v[current.r][current.c] = std::clamp(est_v[current.r][current.c] + base_update * w, 500.0, 10000.0);\n            updates_v[current.r][current.c]++; next.r++;\n        } else if (move == 'L') {\n            next.c--; double w = 1.0 / (updates_h[next.r][next.c] + 1.0);\n            est_h[next.r][next.c] = std::clamp(est_h[next.r][next.c] + base_update * w, 500.0, 10000.0);\n            updates_h[next.r][next.c]++;\n        } else {\n            double w = 1.0 / (updates_h[current.r][current.c] + 1.0);\n            est_h[current.r][current.c] = std::clamp(est_h[current.r][current.c] + base_update * w, 500.0, 10000.0);\n            updates_h[current.r][current.c]++; next.c++;\n        }\n        current = next;\n    }\n}\n\nModelFitResult calculate_ss(const std::vector<std::pair<int, double>>& indexed_vals, int row_or_col_size) {\n    ModelFitResult res;\n    res.n_pts = indexed_vals.size();\n    if (res.n_pts == 0) return res;\n\n    double total_sum = 0, total_sq_sum = 0;\n    for (const auto& p : indexed_vals) {\n        total_sum += p.second; total_sq_sum += p.second * p.second;\n    }\n\n    res.mean1 = total_sum / res.n_pts;\n    res.sse1 = total_sq_sum - total_sum * res.mean1;\n    res.split_point = -1;\n    res.sse2 = res.sse1;\n\n    if (res.n_pts >= 4) {\n        double current_best_sse2 = 1e18;\n        \n        double sum_l = 0, sq_sum_l = 0;\n        int count_l = 0;\n        int val_idx = 0;\n        \n        for (int split = 1; split < row_or_col_size; ++split) {\n            while(val_idx < res.n_pts && indexed_vals[val_idx].first < split) {\n                sum_l += indexed_vals[val_idx].second;\n                sq_sum_l += indexed_vals[val_idx].second * indexed_vals[val_idx].second;\n                count_l++;\n                val_idx++;\n            }\n            \n            int count_r = res.n_pts - count_l;\n            if (count_l < 2 || count_r < 2) continue;\n\n            double mean_l = sum_l / count_l;\n            double sse_l = sq_sum_l - sum_l * mean_l;\n            \n            double sum_r = total_sum - sum_l;\n            double sq_sum_r = total_sq_sum - sq_sum_l;\n            double mean_r = sum_r / count_r;\n            double sse_r = sq_sum_r - sum_r * mean_r;\n            \n            if (sse_l + sse_r < current_best_sse2) {\n                current_best_sse2 = sse_l + sse_r;\n                res.split_point = split;\n                res.mean_l = mean_l;\n                res.mean_r = mean_r;\n            }\n        }\n        if (res.split_point != -1) res.sse2 = current_best_sse2;\n    }\n    return res;\n}\n\n\nvoid update_model(int k) {\n    if (k == 150) {\n        double total_bic_m1 = 0, total_bic_m2 = 0;\n        for (int i = 0; i < GRID_SIZE; ++i) {\n            std::vector<std::pair<int, double>> indexed_vals;\n            for(int j=0; j<GRID_SIZE-1; ++j) if(updates_h[i][j]>0) indexed_vals.push_back({j, est_h[i][j]});\n            auto res = calculate_ss(indexed_vals, GRID_SIZE - 1);\n            if (res.n_pts <= 1) continue;\n            total_bic_m1 += res.n_pts * log(std::max(1e-9, res.sse1 / res.n_pts)) + 1.0 * log(res.n_pts);\n            total_bic_m2 += res.n_pts * log(std::max(1e-9, res.sse2 / res.n_pts)) + 3.0 * log(res.n_pts);\n        }\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            std::vector<std::pair<int, double>> indexed_vals;\n            for(int i=0; i<GRID_SIZE-1; ++i) if(updates_v[i][j]>0) indexed_vals.push_back({i, est_v[i][j]});\n            auto res = calculate_ss(indexed_vals, GRID_SIZE - 1);\n            if (res.n_pts <= 1) continue;\n            total_bic_m1 += res.n_pts * log(std::max(1e-9, res.sse1 / res.n_pts)) + 1.0 * log(res.n_pts);\n            total_bic_m2 += res.n_pts * log(std::max(1e-9, res.sse2 / res.n_pts)) + 3.0 * log(res.n_pts);\n        }\n        if (total_bic_m2 < total_bic_m1) global_M = 2; else global_M = 1;\n    }\n    \n    for (int i = 0; i < GRID_SIZE; ++i) {\n        std::vector<std::pair<int, double>> indexed_vals;\n        for(int j=0; j<GRID_SIZE-1; ++j) if(updates_h[i][j]>0) indexed_vals.push_back({j, est_h[i][j]});\n        auto res = calculate_ss(indexed_vals, GRID_SIZE - 1);\n        if (res.n_pts == 0) continue;\n        \n        if (global_M == 2 && res.split_point != -1) {\n            for(int j=0; j<res.split_point; ++j) model_h[i][j] = res.mean_l;\n            for(int j=res.split_point; j<GRID_SIZE-1; ++j) model_h[i][j] = res.mean_r;\n        } else {\n            for(int j=0; j<GRID_SIZE-1; ++j) model_h[i][j] = res.mean1;\n        }\n    }\n    for (int j = 0; j < GRID_SIZE; ++j) {\n        std::vector<std::pair<int, double>> indexed_vals;\n        for(int i=0; i<GRID_SIZE-1; ++i) if(updates_v[i][j]>0) indexed_vals.push_back({i, est_v[i][j]});\n        auto res = calculate_ss(indexed_vals, GRID_SIZE - 1);\n        if (res.n_pts == 0) continue;\n\n        if (global_M == 2 && res.split_point != -1) {\n            for(int i=0; i<res.split_point; ++i) model_v[i][j] = res.mean_l;\n            for(int i=res.split_point; i<GRID_SIZE-1; ++i) model_v[i][j] = res.mean_r;\n        } else {\n            for(int i=0; i<GRID_SIZE-1; ++i) model_v[i][j] = res.mean1;\n        }\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE - 1; ++j) {\n            est_h[i][j] = model_h[i][j] = 5000.0; updates_h[i][j] = 0;\n        }\n    }\n    for (int i = 0; i < GRID_SIZE - 1; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            est_v[i][j] = model_v[i][j] = 5000.0; updates_v[i][j] = 0;\n        }\n    }\n\n    for (int k = 0; k < NUM_QUERIES; ++k) {\n        Point start, goal;\n        std::cin >> start.r >> start.c >> goal.r >> goal.c;\n\n        std::string path = find_path(start, goal, k);\n        std::cout << path << std::endl;\n\n        long long noisy_path_length;\n        std::cin >> noisy_path_length;\n\n        update_estimates(path, start, noisy_path_length, k);\n        update_model(k);\n    }\n\n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <chrono>\n#include <random>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <map>\n#include <cstring>\n\n// --- Constants and Globals ---\nconstexpr int N_CONST = 20;\nconstexpr int NUM_CHARS = 8;\nconstexpr long long W_CONFLICT = 10000;\nconst double TIME_LIMIT = 2.95;\n\nint N_in, M;\nstd::vector<std::string> S;\nstd::vector<int> S_len;\nstd::vector<std::vector<int>> S_int;\n\nstd::mt19937 rng;\nstd::chrono::steady_clock::time_point start_time;\n\nstruct Placement {\n    int r, c, dir; // dir=0: horizontal, dir=1: vertical\n    bool operator==(const Placement& other) const {\n        return r == other.r && c == other.c && dir == other.dir;\n    }\n};\n\n// --- State Representation ---\nstd::vector<Placement> current_placements;\nstd::vector<Placement> best_placements;\nlong long current_energy;\nlong long best_energy;\n\nint counts[N_CONST][N_CONST][NUM_CHARS];\nint covered_count[N_CONST][N_CONST];\n\nint best_counts[N_CONST][N_CONST][NUM_CHARS];\nint best_covered_count[N_CONST][N_CONST];\n\n// --- Utilities ---\nint ctoi(char c) { return c - 'A'; }\nchar itoc(int i) { return (char)('A' + i); }\n\n// --- Core Logic ---\nstd::pair<long long, int> get_cell_energy_contrib(int r, int c) {\n    if (covered_count[r][c] == 0) return {0, 0};\n    int max_c = 0;\n    for (int k = 0; k < NUM_CHARS; ++k) max_c = std::max(max_c, counts[r][c][k]);\n    long long conflict_contrib = covered_count[r][c] - max_c;\n    return {conflict_contrib, 1};\n}\n\nvoid update_state_for_move(int str_idx, const Placement& p, int sign) {\n    const auto& s = S_int[str_idx];\n    int len = S_len[str_idx];\n    if (p.dir == 0) { // Horizontal\n        for (int i = 0; i < len; ++i) {\n            counts[p.r][(p.c + i) % N_CONST][s[i]] += sign;\n            covered_count[p.r][(p.c + i) % N_CONST] += sign;\n        }\n    } else { // Vertical\n        for (int i = 0; i < len; ++i) {\n            counts[(p.r + i) % N_CONST][p.c][s[i]] += sign;\n            covered_count[(p.r + i) % N_CONST][p.c] += sign;\n        }\n    }\n}\n\nlong long calculate_delta_energy(int str_idx, const Placement& old_p, const Placement& new_p) {\n    long long delta = 0;\n    const auto& s = S_int[str_idx];\n    int len = S_len[str_idx];\n    \n    std::vector<std::pair<int, int>> affected_coords;\n    if (old_p.dir == 0) for (int i=0; i<len; ++i) affected_coords.push_back({old_p.r, (old_p.c+i)%N_CONST});\n    else for (int i=0; i<len; ++i) affected_coords.push_back({(old_p.r+i)%N_CONST, old_p.c});\n    \n    if (new_p.dir == 0) for (int i=0; i<len; ++i) affected_coords.push_back({new_p.r, (new_p.c+i)%N_CONST});\n    else for (int i=0; i<len; ++i) affected_coords.push_back({(new_p.r+i)%N_CONST, new_p.c});\n\n    std::sort(affected_coords.begin(), affected_coords.end());\n    affected_coords.erase(std::unique(affected_coords.begin(), affected_coords.end()), affected_coords.end());\n\n    for (const auto& cell : affected_coords) {\n        int r = cell.first;\n        int c = cell.second;\n        auto [conflicts_before, covered_before] = get_cell_energy_contrib(r, c);\n        delta -= (conflicts_before * W_CONFLICT + covered_before);\n\n        int old_p_char = -1, new_p_char = -1;\n        if (old_p.dir == 0) { if (r == old_p.r && (c - old_p.c + N_CONST)%N_CONST < len) old_p_char = s[(c-old_p.c+N_CONST)%N_CONST]; }\n        else { if (c == old_p.c && (r - old_p.r + N_CONST)%N_CONST < len) old_p_char = s[(r-old_p.r+N_CONST)%N_CONST]; }\n        if (new_p.dir == 0) { if (r == new_p.r && (c - new_p.c + N_CONST)%N_CONST < len) new_p_char = s[(c-new_p.c+N_CONST)%N_CONST]; }\n        else { if (c == new_p.c && (r - new_p.r + N_CONST)%N_CONST < len) new_p_char = s[(r-new_p.r+N_CONST)%N_CONST]; }\n        \n        int new_covered_total = covered_count[r][c];\n        if(old_p_char != -1) new_covered_total--;\n        if(new_p_char != -1) new_covered_total++;\n\n        if (new_covered_total > 0) {\n            int max_c = 0;\n            for (int k=0; k<NUM_CHARS; ++k) {\n                int current_cnt = counts[r][c][k];\n                if(k == old_p_char) current_cnt--;\n                if(k == new_p_char) current_cnt++;\n                max_c = std::max(max_c, current_cnt);\n            }\n            long long conflicts_after = new_covered_total - max_c;\n            delta += (conflicts_after * W_CONFLICT + 1);\n        }\n    }\n    return delta;\n}\n\nPlacement find_best_move(int str_idx) {\n    Placement old_p = current_placements[str_idx];\n    Placement best_p = old_p;\n    long long min_delta = 1e18;\n    for (int r = 0; r < N_CONST; ++r) for (int c = 0; c < N_CONST; ++c) for (int dir = 0; dir < 2; ++dir) {\n        Placement p_candidate = {r, c, dir};\n        long long delta = calculate_delta_energy(str_idx, old_p, p_candidate);\n        if (delta < min_delta) {\n            min_delta = delta;\n            best_p = p_candidate;\n        }\n    }\n    return best_p;\n}\n\nvoid greedy_initialization() {\n    current_placements.resize(M);\n    std::vector<int> p(M);\n    std::iota(p.begin(), p.end(), 0);\n    std::sort(p.begin(), p.end(), [&](int i, int j){ return S_len[i] > S_len[j]; });\n    std::vector<std::vector<int>> grid(N_CONST, std::vector<int>(N_CONST, -1));\n    for (int str_idx : p) {\n        Placement best_p; int min_conflicts = 1e9;\n        for (int r=0;r<N_CONST;++r) for(int c=0;c<N_CONST;++c) for(int dir=0;dir<2;++dir) {\n            int current_conflicts = 0; const auto& s = S_int[str_idx]; int len = S_len[str_idx];\n            if(dir==0) for(int i=0;i<len;++i) if (grid[r][(c+i)%N_CONST]!=-1 && grid[r][(c+i)%N_CONST]!=s[i]) current_conflicts++;\n            else for(int i=0;i<len;++i) if (grid[(r+i)%N_CONST][c]!=-1 && grid[(r+i)%N_CONST][c]!=s[i]) current_conflicts++;\n            if(current_conflicts < min_conflicts) { min_conflicts=current_conflicts; best_p={r,c,dir}; }\n        }\n        current_placements[str_idx] = best_p; const auto& s = S_int[str_idx]; int len = S_len[str_idx];\n        if (best_p.dir == 0) for(int i=0; i<len; ++i) grid[best_p.r][(best_p.c+i)%N_CONST] = s[i];\n        else for(int i=0; i<len; ++i) grid[(best_p.r+i)%N_CONST][best_p.c] = s[i];\n    }\n}\n\nvoid solve() {\n    start_time = std::chrono::steady_clock::now();\n    rng.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());\n    S_int.resize(M); S_len.resize(M);\n    for (int i=0; i<M; ++i) {\n        S_len[i]=S[i].length(); S_int[i].resize(S_len[i]);\n        for(int j=0; j<S_len[i]; ++j) S_int[i][j]=ctoi(S[i][j]);\n    }\n\n    greedy_initialization();\n    for (int i=0; i<M; ++i) update_state_for_move(i, current_placements[i], +1);\n    \n    for (int iter = 0; iter < 2; ++iter) {\n        for (int i = 0; i < M; ++i) {\n            Placement old_p = current_placements[i];\n            Placement best_p = find_best_move(i);\n            if (!(best_p == old_p)) {\n                update_state_for_move(i, old_p, -1); update_state_for_move(i, best_p, +1);\n                current_placements[i] = best_p;\n            }\n        }\n    }\n    \n    current_energy = 0;\n    for (int r=0;r<N_CONST;++r) for (int c=0;c<N_CONST;++c){\n        auto [conf, cov] = get_cell_energy_contrib(r,c); current_energy += conf*W_CONFLICT + cov;\n    }\n    best_energy = current_energy; best_placements = current_placements;\n    memcpy(best_counts, counts, sizeof(counts)); memcpy(best_covered_count, covered_count, sizeof(covered_count));\n\n    double start_temp=5000.0, end_temp=0.1;\n    int iters_since_best = 0;\n    const int STAGNATION_LIMIT = M * 75;\n    \n    while (true) {\n        auto now = std::chrono::steady_clock::now();\n        double elapsed_time = std::chrono::duration_cast<std::chrono::duration<double>>(now - start_time).count();\n        if (elapsed_time > TIME_LIMIT) break;\n\n        double temp = start_temp * std::pow(end_temp / start_temp, elapsed_time / TIME_LIMIT);\n        int str_idx;\n        \n        // Phase 2: If current state has no conflicts, optimize coverage by picking random strings\n        if (current_energy / W_CONFLICT == 0) {\n            str_idx = std::uniform_int_distribution<int>(0, M - 1)(rng);\n        } \n        // Phase 1: If conflicts exist, focus on resolving them\n        else {\n            if (std::uniform_real_distribution<>(0.0, 1.0)(rng) < 0.05) { // Small chance for random exploration\n                str_idx = std::uniform_int_distribution<int>(0, M - 1)(rng);\n            } else { // Hyper-focused selection\n                std::vector<std::pair<int, int>> conflicted_cells;\n                for(int r=0; r<N_CONST; ++r) for(int c=0; c<N_CONST; ++c) if(get_cell_energy_contrib(r,c).first > 0) conflicted_cells.emplace_back(r, c);\n                if (!conflicted_cells.empty()) {\n                    auto [r0,c0] = conflicted_cells[std::uniform_int_distribution<int>(0, conflicted_cells.size()-1)(rng)];\n                    std::vector<int> candidates;\n                    for(int i=0; i<M; ++i) {\n                        const auto& p=current_placements[i]; int len=S_len[i];\n                        if((p.dir==0&&p.r==r0&&(c0-p.c+N_CONST)%N_CONST<len)||(p.dir==1&&p.c==c0&&(r0-p.r+N_CONST)%N_CONST<len)) candidates.push_back(i);\n                    }\n                    if (!candidates.empty()) str_idx = candidates[std::uniform_int_distribution<int>(0, candidates.size()-1)(rng)];\n                    else str_idx = std::uniform_int_distribution<int>(0, M-1)(rng);\n                } else str_idx = std::uniform_int_distribution<int>(0, M-1)(rng);\n            }\n        }\n\n        Placement old_p = current_placements[str_idx]; Placement new_p;\n        double p_powerful = 0.2 + 0.6*(elapsed_time/TIME_LIMIT);\n        if (std::uniform_real_distribution<>(0.0,1.0)(rng) < p_powerful) new_p = find_best_move(str_idx);\n        else {\n            double p_local = 0.1 + 0.8 * (elapsed_time/TIME_LIMIT);\n            if (std::uniform_real_distribution<>(0.0, 1.0)(rng) < p_local) {\n                 new_p = old_p;\n                 int move_type = std::uniform_int_distribution<int>(0,2)(rng);\n                 if (move_type==0) new_p.r=(new_p.r+std::uniform_int_distribution<int>(-2,2)(rng)+N_CONST)%N_CONST;\n                 else if (move_type==1) new_p.c=(new_p.c+std::uniform_int_distribution<int>(-2,2)(rng)+N_CONST)%N_CONST;\n                 else new_p.dir=1-new_p.dir;\n            } else new_p = {std::uniform_int_distribution<int>(0,N_CONST-1)(rng), std::uniform_int_distribution<int>(0,N_CONST-1)(rng), std::uniform_int_distribution<int>(0,1)(rng)};\n        }\n        \n        if (old_p == new_p) continue;\n        long long delta_energy = calculate_delta_energy(str_idx, old_p, new_p);\n        if (delta_energy <= 0 || std::uniform_real_distribution<double>(0.0,1.0)(rng) < std::exp(-delta_energy/temp)) {\n            current_energy += delta_energy;\n            update_state_for_move(str_idx, old_p, -1); update_state_for_move(str_idx, new_p, +1);\n            current_placements[str_idx] = new_p;\n            if (current_energy < best_energy) {\n                best_energy = current_energy; best_placements = current_placements;\n                memcpy(best_counts, counts, sizeof(counts)); memcpy(best_covered_count, covered_count, sizeof(covered_count));\n                iters_since_best = 0;\n            }\n        }\n        iters_since_best++;\n        if (best_energy >= W_CONFLICT && iters_since_best > STAGNATION_LIMIT) {\n            current_placements = best_placements; memcpy(counts, best_counts, sizeof(counts)); memcpy(covered_count, best_covered_count, sizeof(covered_count));\n            current_energy = best_energy;\n            std::vector<int> conflicted_strings; std::vector<bool> is_conflicted_str(M, false);\n            for(int r=0;r<N_CONST;++r) for(int c=0;c<N_CONST;++c) if(get_cell_energy_contrib(r,c).first > 0)\n                for(int i=0;i<M;++i) if(!is_conflicted_str[i]){\n                    const auto& p=current_placements[i]; int len=S_len[i];\n                    if((p.dir==0&&p.r==r&&(c-p.c+N_CONST)%N_CONST<len)||(p.dir==1&&p.c==c&&(r-p.r+N_CONST)%N_CONST<len)){\n                        conflicted_strings.push_back(i); is_conflicted_str[i]=true;\n                    }\n                }\n            if(!conflicted_strings.empty()){\n                std::shuffle(conflicted_strings.begin(), conflicted_strings.end(), rng);\n                int num_to_kick = std::max(3, M / 50);\n                for (int i=0; i<num_to_kick && i<conflicted_strings.size(); ++i) {\n                    int kick_idx = conflicted_strings[i];\n                    Placement kick_old_p = current_placements[kick_idx];\n                    Placement kick_best_p = find_best_move(kick_idx);\n                    if(!(kick_old_p == kick_best_p)){\n                        long long kick_delta = calculate_delta_energy(kick_idx, kick_old_p, kick_best_p);\n                        update_state_for_move(kick_idx, kick_old_p, -1); update_state_for_move(kick_idx, kick_best_p, +1);\n                        current_placements[kick_idx] = kick_best_p; current_energy += kick_delta;\n                    }\n                }\n            }\n            if(current_energy < best_energy) {\n                best_energy = current_energy; best_placements = current_placements;\n                memcpy(best_counts, counts, sizeof(counts)); memcpy(best_covered_count, covered_count, sizeof(covered_count));\n            }\n            iters_since_best = 0;\n        }\n    }\n\n    std::vector<std::string> final_grid(N_CONST, std::string(N_CONST, '.'));\n    for (int r=0;r<N_CONST;++r) for(int c=0;c<N_CONST;++c) if(best_covered_count[r][c] > 0) {\n        int max_k=-1, max_cnt=0;\n        for (int k=0;k<NUM_CHARS;++k) if (best_counts[r][c][k]>max_cnt) {max_cnt=best_counts[r][c][k]; max_k=k;}\n        if (max_k != -1) final_grid[r][c]=itoc(max_k);\n    }\n    for (int i=0;i<N_CONST;++i) std::cout<<final_grid[i]<<std::endl;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false); std::cin.tie(NULL);\n    std::cin >> N_in >> M;\n    S.resize(M);\n    for (int i=0; i<M; ++i) std::cin >> S[i];\n    solve();\n    return 0;\n}","ahc005":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <map>\n#include <set>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <cmath>\n\nusing namespace std;\n\n// Timer\nchrono::high_resolution_clock::time_point start_time;\nconst double TIME_LIMIT_MS = 2900.0;\n\n// PRNG\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// Constants\nconst int INF = 1e9;\nconst int DR[] = {-1, 1, 0, 0};\nconst int DC[] = {0, 0, -1, 1};\n\n// Globals\nint N, si, sj;\nvector<string> grid;\nvector<pair<int, int>> road_squares;\nmap<pair<int, int>, int> coord_to_id;\nvector<vector<pair<int, int>>> adj;\n\nstruct Segment {\n    int id;\n    vector<pair<int, int>> squares;\n};\nvector<Segment> segments;\n\n// Pre-computation functions\nvoid find_road_squares_and_build_graph() {\n    int current_id = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != '#') {\n                road_squares.push_back({i, j});\n                coord_to_id[{i, j}] = current_id++;\n            }\n        }\n    }\n\n    adj.resize(road_squares.size());\n    for (size_t i = 0; i < road_squares.size(); ++i) {\n        auto [r, c] = road_squares[i];\n        for (int move = 0; move < 4; ++move) {\n            int nr = r + DR[move];\n            int nc = c + DC[move];\n            if (nr >= 0 && nr < N && nc >= 0 && nc < N && grid[nr][nc] != '#') {\n                int neighbor_id = coord_to_id.at({nr, nc});\n                int cost = grid[nr][nc] - '0';\n                adj[i].push_back({neighbor_id, cost});\n            }\n        }\n    }\n}\n\nvoid find_segments() {\n    set<pair<int, int>> visited_horz, visited_vert;\n    int seg_id_counter = 0;\n    for (const auto& p : road_squares) {\n        if (!visited_horz.count(p)) {\n            Segment seg;\n            seg.id = seg_id_counter++;\n            int r = p.first, c = p.second;\n            int c_start = c;\n            while (c_start > 0 && grid[r][c_start - 1] != '#') c_start--;\n            int c_end = c;\n            while (c_end < N - 1 && grid[r][c_end + 1] != '#') c_end++;\n            for (int j = c_start; j <= c_end; ++j) {\n                seg.squares.push_back({r, j});\n                visited_horz.insert({r, j});\n            }\n            segments.push_back(seg);\n        }\n        if (!visited_vert.count(p)) {\n            Segment seg;\n            seg.id = seg_id_counter++;\n            int r = p.first, c = p.second;\n            int r_start = r;\n            while (r_start > 0 && grid[r_start - 1][c] != '#') r_start--;\n            int r_end = r;\n            while (r_end < N - 1 && grid[r_end + 1][c] != '#') r_end++;\n            for (int i = r_start; i <= r_end; ++i) {\n                seg.squares.push_back({i, c});\n                visited_vert.insert({i, c});\n            }\n            segments.push_back(seg);\n        }\n    }\n}\n\npair<vector<int>, vector<int>> dijkstra(int start_node_id) {\n    int n = road_squares.size();\n    vector<int> dist(n, INF);\n    vector<int> parent(n, -1);\n    dist[start_node_id] = 0;\n\n    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;\n    pq.push({0, start_node_id});\n\n    while (!pq.empty()) {\n        auto [d, u] = pq.top();\n        pq.pop();\n        if (d > dist[u]) continue;\n        for (auto& edge : adj[u]) {\n            int v = edge.first;\n            int weight = edge.second;\n            if (dist[u] + weight < dist[v]) {\n                dist[v] = dist[u] + weight;\n                parent[v] = u;\n                pq.push({dist[v], v});\n            }\n        }\n    }\n    return {dist, parent};\n}\n\nlong long calculate_tour_cost(const vector<int>& tour, const vector<vector<int>>& dist_matrix) {\n    if (tour.empty()) return 0;\n    long long cost = 0;\n    for (size_t i = 0; i < tour.size(); ++i) {\n        cost += dist_matrix[tour[i]][tour[(i + 1) % tour.size()]];\n    }\n    return cost;\n}\n\nvoid two_opt_local_search(vector<int>& tour, int n, const vector<vector<int>>& dist_matrix) {\n    if (n < 4) return;\n    bool improved = true;\n    int check_counter = 0;\n    while(improved) {\n        improved = false;\n        for (int i = 0; i <= n - 2; ++i) {\n            for (int j = i + 2; j < n; ++j) {\n                 if ((++check_counter & 1023) == 0) { // Check time every 1024 iterations\n                    if (chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count() > TIME_LIMIT_MS - 50) {\n                        return; // Exit if time is up\n                    }\n                 }\n\n                 if (i == 0 && j == n - 1) continue; \n                 int u1 = tour[i];\n                 int v1 = tour[i+1];\n                 int u2 = tour[j];\n                 int v2 = tour[(j+1)%n];\n                 \n                 if((long long)dist_matrix[u1][v1] + dist_matrix[u2][v2] > (long long)dist_matrix[u1][u2] + dist_matrix[v1][v2]) {\n                     reverse(tour.begin() + i + 1, tour.begin() + j + 1);\n                     improved = true;\n                     goto next_two_opt_iteration;\n                 }\n            }\n        }\n        next_two_opt_iteration:;\n    }\n}\n\nvoid double_bridge_perturbation(vector<int>& tour, int n) {\n    if (n < 8) return;\n    \n    vector<int> p(3);\n    p[0] = uniform_int_distribution<int>(0, n-1)(rng);\n    p[1] = uniform_int_distribution<int>(0, n-1)(rng);\n    p[2] = uniform_int_distribution<int>(0, n-1)(rng);\n\n    sort(p.begin(), p.end());\n    p.erase(unique(p.begin(), p.end()), p.end());\n    if (p.size() != 3) return; // Need 3 distinct cut points\n\n    int pos1 = p[0], pos2 = p[1], pos3 = p[2];\n    \n    // Ensure segments are not empty, not strictly needed but good practice.\n    if (pos1 + 1 >= pos2 || pos2 + 1 >= pos3) return;\n\n    vector<int> next_tour;\n    next_tour.reserve(n);\n    \n    // Segments: 0..pos1, pos1+1..pos2, pos2+1..pos3, pos3+1..n-1\n    // Reorder: 0..pos1, pos3+1..n-1, pos2+1..pos3, pos1+1..pos2\n    for (int i = 0; i <= pos1; ++i) next_tour.push_back(tour[i]);\n    for (int i = pos3 + 1; i < n; ++i) next_tour.push_back(tour[i]);\n    for (int i = pos2 + 1; i <= pos3; ++i) next_tour.push_back(tour[i]);\n    for (int i = pos1 + 1; i <= pos2; ++i) next_tour.push_back(tour[i]);\n    \n    tour = next_tour;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    start_time = chrono::high_resolution_clock::now();\n\n    cin >> N >> si >> sj;\n    grid.resize(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n\n    find_road_squares_and_build_graph();\n    find_segments();\n    \n    set<pair<int, int>> key_points_set;\n    key_points_set.insert({si, sj});\n    for (const auto& seg : segments) {\n        key_points_set.insert(seg.squares.front());\n        key_points_set.insert(seg.squares.back());\n    }\n    for (size_t i = 0; i < road_squares.size(); ++i) {\n        if (adj[i].size() > 2) key_points_set.insert(road_squares[i]);\n    }\n    \n    vector<pair<int, int>> key_points(key_points_set.begin(), key_points_set.end());\n    map<pair<int, int>, int> kp_to_idx;\n    for(size_t i=0; i<key_points.size(); ++i) kp_to_idx[key_points[i]] = i;\n\n    vector<vector<int>> kp_covers(key_points.size());\n    for(size_t i=0; i<key_points.size(); ++i) {\n        for(const auto& seg : segments) {\n            for(const auto& sq : seg.squares) {\n                if(sq == key_points[i]) { kp_covers[i].push_back(seg.id); break; }\n            }\n        }\n    }\n    \n    set<int> uncovered_segments;\n    for (const auto& seg : segments) uncovered_segments.insert(seg.id);\n    set<int> selected_kp_indices;\n\n    while(!uncovered_segments.empty()) {\n        int best_kp_idx = -1; int max_covered = -1;\n        for(size_t i=0; i<key_points.size(); ++i) {\n            if (selected_kp_indices.count(i)) continue;\n            int current_covered = 0;\n            for(int seg_id : kp_covers[i]) if (uncovered_segments.count(seg_id)) current_covered++;\n            if(current_covered > max_covered) { max_covered = current_covered; best_kp_idx = i; }\n        }\n        if (best_kp_idx == -1) break;\n        selected_kp_indices.insert(best_kp_idx);\n        for(int seg_id : kp_covers[best_kp_idx]) uncovered_segments.erase(seg_id);\n    }\n    \n    map<int, int> coverage_count;\n    for(const auto& seg : segments) coverage_count[seg.id] = 0;\n    for(int kp_idx : selected_kp_indices) for(int seg_id : kp_covers[kp_idx]) coverage_count[seg_id]++;\n    vector<int> selected_kp_vec(selected_kp_indices.begin(), selected_kp_indices.end());\n    bool changed = true;\n    while(changed) {\n        changed = false;\n        shuffle(selected_kp_vec.begin(), selected_kp_vec.end(), rng);\n        auto it = selected_kp_vec.begin();\n        while(it != selected_kp_vec.end()) {\n            int kp_to_remove = *it;\n            bool is_redundant = true;\n            for (int seg_id : kp_covers[kp_to_remove]) {\n                if (coverage_count[seg_id] == 1) { is_redundant = false; break; }\n            }\n            if (is_redundant) {\n                for (int seg_id : kp_covers[kp_to_remove]) coverage_count[seg_id]--;\n                it = selected_kp_vec.erase(it);\n                changed = true;\n            } else { ++it; }\n        }\n    }\n    \n    set<pair<int, int>> target_kps_set;\n    for(int idx : selected_kp_vec) target_kps_set.insert(key_points[idx]);\n    target_kps_set.insert({si, sj});\n\n    vector<pair<int, int>> V_tsp_coords(target_kps_set.begin(), target_kps_set.end());\n    int num_tsp_nodes = V_tsp_coords.size();\n    map<pair<int, int>, int> tsp_coord_to_idx;\n    for(int i=0; i<num_tsp_nodes; ++i) tsp_coord_to_idx[V_tsp_coords[i]] = i;\n\n    vector<vector<int>> dist_matrix(num_tsp_nodes, vector<int>(num_tsp_nodes));\n    vector<vector<int>> parents_matrix(num_tsp_nodes, vector<int>(road_squares.size()));\n    for(int i=0; i<num_tsp_nodes; ++i) {\n        int start_node_id = coord_to_id.at(V_tsp_coords[i]);\n        auto [dist, parent] = dijkstra(start_node_id);\n        parents_matrix[i] = parent;\n        for(int j=0; j<num_tsp_nodes; ++j) {\n            dist_matrix[i][j] = dist[coord_to_id.at(V_tsp_coords[j])];\n        }\n    }\n\n    int start_tsp_idx = tsp_coord_to_idx.at({si, sj});\n    vector<int> best_tour;\n    if(num_tsp_nodes > 0){\n        vector<int> tour;\n        tour.push_back(start_tsp_idx);\n        vector<bool> visited(num_tsp_nodes, false);\n        visited[start_tsp_idx] = true;\n        int current_idx = start_tsp_idx;\n        while(tour.size() < (size_t)num_tsp_nodes) {\n            int next_idx = -1, min_dist = INF;\n            for(int i=0; i<num_tsp_nodes; ++i) {\n                if(!visited[i] && dist_matrix[current_idx][i] < min_dist) {\n                    min_dist = dist_matrix[current_idx][i]; next_idx = i;\n                }\n            }\n            if (next_idx == -1) break;\n            tour.push_back(next_idx); visited[next_idx] = true; current_idx = next_idx;\n        }\n        best_tour = tour;\n    }\n    \n    vector<int> current_tour = best_tour;\n    two_opt_local_search(current_tour, num_tsp_nodes, dist_matrix);\n    \n    best_tour = current_tour;\n    long long best_cost = calculate_tour_cost(best_tour, dist_matrix);\n\n    while(true) {\n        if (chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count() > TIME_LIMIT_MS) break;\n\n        vector<int> next_tour = current_tour;\n        double_bridge_perturbation(next_tour, num_tsp_nodes);\n        two_opt_local_search(next_tour, num_tsp_nodes, dist_matrix);\n        long long next_cost = calculate_tour_cost(next_tour, dist_matrix);\n        \n        if (next_cost < best_cost) {\n            best_tour = next_tour;\n            best_cost = next_cost;\n        }\n        current_tour = next_tour;\n    }\n\n    auto it = find(best_tour.begin(), best_tour.end(), start_tsp_idx);\n    if (it != best_tour.end()) rotate(best_tour.begin(), it, best_tour.end());\n\n    string path_str = \"\";\n    if (!best_tour.empty()) {\n        for(size_t i=0; i<best_tour.size(); ++i) {\n            int u_idx = best_tour[i], v_idx = best_tour[(i+1)%best_tour.size()];\n            int u_id = coord_to_id.at(V_tsp_coords[u_idx]), v_id = coord_to_id.at(V_tsp_coords[v_idx]);\n            vector<int> path;\n            for(int curr=v_id; curr!=-1 && curr!=u_id; curr=parents_matrix[u_idx][curr]) path.push_back(curr);\n            reverse(path.begin(), path.end());\n            pair<int, int> last_coord = V_tsp_coords[u_idx];\n            for(int node_id : path) {\n                auto [r, c] = road_squares[node_id];\n                if(r < last_coord.first) path_str += 'U'; else if(r > last_coord.first) path_str += 'D';\n                else if(c < last_coord.second) path_str += 'L'; else path_str += 'R';\n                last_coord = {r, c};\n            }\n        }\n    }\n    cout << path_str << endl;\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <string>\n#include <sstream>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <functional>\n#include <limits>\n\n#include <atcoder/mincostflow>\n\n// Constants\nconstexpr int N_TASKS = 1000;\nconstexpr int M_MEMBERS = 20;\nconstexpr int MAX_DAYS = 2000;\n\n// Hyperparameters\nconst double INITIAL_SKILL_ESTIMATE = 0.0;\nconst double SKILL_UPDATE_LEARNING_RATE = 0.15;\nconst double EXPLORATION_DECAY_DAYS = 450.0; // Tuned\nconst double EXPLORATION_LAMBDA_0 = 0.5;\nconst double OVERESTIMATE_CORRECTION_FACTOR = 0.1;\nconst int CANDIDATE_TASK_POOL_SIZE = 3 * M_MEMBERS;\nconst double NOVELTY_WEIGHT = 200.0; // Tuned\nconst double UNCERTAINTY_WEIGHT = 300.0; // Tuned\n\n// Problem data\nint K, R;\nstd::vector<std::vector<int>> D; // Task difficulties\nstd::vector<std::vector<int>> adj; // Task dependencies (u -> v means u must be done before v)\nstd::vector<std::vector<int>> rev_adj; // Reverse dependencies\n\n// State\nenum class TaskStatus { NOT_STARTED, IN_PROGRESS, COMPLETED };\nstd::vector<TaskStatus> task_status;\nint completed_task_count;\n\nstruct Member {\n    bool is_busy = false;\n    int task_id = -1;\n    int start_day = -1;\n};\nstd::vector<Member> members;\n\nstd::vector<std::vector<double>> estimated_skills;\nstd::vector<std::vector<int>> skill_lower_bounds;\nstd::vector<std::vector<int>> max_d_seen;\nstd::vector<std::vector<int>> skill_update_counts;\n\n// --- Function Declarations ---\ndouble estimate_work(int task_id, int member_id);\ndouble estimate_time(int task_id, int member_id);\nvoid read_initial_input();\nvoid initialize_state();\nvoid update_skills(int member_id, int task_id, int duration);\n\n// --- Main Logic ---\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int N_dummy, M_dummy;\n    std::cin >> N_dummy >> M_dummy;\n    \n    read_initial_input();\n    initialize_state();\n\n    for (int day = 1; day <= MAX_DAYS; ++day) {\n        std::vector<int> free_members_ids;\n        for (int i = 0; i < M_MEMBERS; ++i) {\n            if (!members[i].is_busy) {\n                free_members_ids.push_back(i);\n            }\n        }\n\n        std::vector<std::pair<int, int>> assignments;\n        if (!free_members_ids.empty()) {\n            std::vector<int> schedulable_tasks_ids;\n            for (int i = 0; i < N_TASKS; ++i) {\n                if (task_status[i] == TaskStatus::NOT_STARTED) {\n                    bool all_deps_done = true;\n                    for (int dep : rev_adj[i]) {\n                        if (task_status[dep] != TaskStatus::COMPLETED) {\n                            all_deps_done = false;\n                            break;\n                        }\n                    }\n                    if (all_deps_done) {\n                        schedulable_tasks_ids.push_back(i);\n                    }\n                }\n            }\n            if (!schedulable_tasks_ids.empty()) {\n                std::vector<double> best_time_for_task(N_TASKS);\n                for (int i = 0; i < N_TASKS; ++i) {\n                    if (task_status[i] == TaskStatus::COMPLETED) {\n                        best_time_for_task[i] = 0;\n                    } else {\n                        double min_t = 1e9;\n                        // STABILITY IMPROVEMENT: Use all members for a stable heuristic\n                        for (int member_id = 0; member_id < M_MEMBERS; ++member_id) {\n                            min_t = std::min(min_t, estimate_time(i, member_id));\n                        }\n                        best_time_for_task[i] = min_t;\n                    }\n                }\n                std::vector<double> dlp(N_TASKS, 0.0);\n                for (int i = N_TASKS - 1; i >= 0; --i) {\n                    double max_succ_dlp = 0.0;\n                    for (int neighbor : adj[i]) {\n                        max_succ_dlp = std::max(max_succ_dlp, dlp[neighbor]);\n                    }\n                    dlp[i] = best_time_for_task[i] + max_succ_dlp;\n                }\n\n                std::sort(schedulable_tasks_ids.begin(), schedulable_tasks_ids.end(), [&](int a, int b) {\n                    if (std::abs(dlp[a] - dlp[b]) > 1e-9) return dlp[a] > dlp[b];\n                    return a < b;\n                });\n                if (schedulable_tasks_ids.size() > CANDIDATE_TASK_POOL_SIZE) {\n                    schedulable_tasks_ids.resize(CANDIDATE_TASK_POOL_SIZE);\n                }\n\n                int num_free_members = free_members_ids.size();\n                int num_cand_tasks = schedulable_tasks_ids.size();\n                \n                std::vector<std::vector<long long>> costs(num_free_members, std::vector<long long>(num_cand_tasks));\n                long long min_cost = std::numeric_limits<long long>::max();\n                double lambda = EXPLORATION_LAMBDA_0 * exp(-(double)day / EXPLORATION_DECAY_DAYS);\n\n                for (int i = 0; i < num_free_members; ++i) {\n                    int member_id = free_members_ids[i];\n                    for (int j = 0; j < num_cand_tasks; ++j) {\n                        int task_id = schedulable_tasks_ids[j];\n                        double t_est = estimate_time(task_id, member_id);\n                        double novelty_bonus = 0;\n                        for (int k = 0; k < K; ++k) {\n                            novelty_bonus += std::max(0, D[task_id][k] - max_d_seen[member_id][k]);\n                        }\n                        double uncertainty_bonus = 0;\n                        for(int k=0; k<K; ++k){\n                            if(D[task_id][k] > 0){\n                                uncertainty_bonus += 1.0 / (1.0 + skill_update_counts[member_id][k]);\n                            }\n                        }\n                        long long current_cost = static_cast<long long>(round(100.0 * t_est - lambda * (NOVELTY_WEIGHT * novelty_bonus + UNCERTAINTY_WEIGHT * uncertainty_bonus)));\n                        costs[i][j] = current_cost;\n                        min_cost = std::min(min_cost, current_cost);\n                    }\n                }\n\n                long long cost_shift = (min_cost < 0) ? -min_cost : 0;\n\n                atcoder::mcf_graph<int, long long> graph(num_free_members + num_cand_tasks + 2);\n                int s = num_free_members + num_cand_tasks;\n                int t = s + 1;\n                for (int i = 0; i < num_free_members; ++i) graph.add_edge(s, i, 1, 0);\n                for (int i = 0; i < num_cand_tasks; ++i) graph.add_edge(num_free_members + i, t, 1, 0);\n                for (int i = 0; i < num_free_members; ++i) {\n                    for (int j = 0; j < num_cand_tasks; ++j) {\n                        graph.add_edge(i, num_free_members + j, 1, costs[i][j] + cost_shift);\n                    }\n                }\n\n                graph.flow(s, t, std::min(num_free_members, num_cand_tasks));\n                for (const auto& edge : graph.edges()) {\n                    if (edge.from >= 0 && edge.from < num_free_members && \n                        edge.to >= num_free_members && edge.to < s && edge.flow > 0) {\n                        int member_idx = edge.from;\n                        int task_idx = edge.to - num_free_members;\n                        assignments.emplace_back(free_members_ids[member_idx], schedulable_tasks_ids[task_idx]);\n                    }\n                }\n            }\n        }\n        \n        std::cout << assignments.size();\n        for (const auto& p : assignments) {\n            int member_id = p.first;\n            int task_id = p.second;\n            std::cout << \" \" << member_id + 1 << \" \" << task_id + 1;\n            members[member_id] = {true, task_id, day};\n            task_status[task_id] = TaskStatus::IN_PROGRESS;\n        }\n        std::cout << std::endl;\n\n        int n_finished;\n        std::cin >> n_finished;\n        if (n_finished == -1) break;\n        \n        for (int i = 0; i < n_finished; ++i) {\n            int finished_member_id;\n            std::cin >> finished_member_id;\n            --finished_member_id;\n\n            int task_id = members[finished_member_id].task_id;\n            int start_day = members[finished_member_id].start_day;\n            int duration = day - start_day + 1;\n\n            members[finished_member_id] = {false, -1, -1};\n            task_status[task_id] = TaskStatus::COMPLETED;\n            completed_task_count++;\n            \n            update_skills(finished_member_id, task_id, duration);\n        }\n    }\n    return 0;\n}\n\n// --- Function Implementations ---\ndouble estimate_work(int task_id, int member_id) {\n    double work = 0;\n    for (int k = 0; k < K; ++k) {\n        work += std::max(0.0, (double)D[task_id][k] - estimated_skills[member_id][k]);\n    }\n    return work;\n}\n\ndouble estimate_time(int task_id, int member_id) {\n    double work = estimate_work(task_id, member_id);\n    if (work < 1e-9) {\n        return 1.0;\n    }\n    double expected_time = 0;\n    for (int r = -3; r <= 3; ++r) {\n        expected_time += std::max(1.0, work + r);\n    }\n    return expected_time / 7.0;\n}\n\nvoid read_initial_input() {\n    std::cin >> K >> R;\n    D.resize(N_TASKS, std::vector<int>(K));\n    for (int i = 0; i < N_TASKS; ++i) {\n        for (int j = 0; j < K; ++j) {\n            std::cin >> D[i][j];\n        }\n    }\n    adj.assign(N_TASKS, std::vector<int>());\n    rev_adj.assign(N_TASKS, std::vector<int>());\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        std::cin >> u >> v;\n        --u; --v;\n        adj[u].push_back(v);\n        rev_adj[v].push_back(u);\n    }\n}\n\nvoid initialize_state() {\n    task_status.assign(N_TASKS, TaskStatus::NOT_STARTED);\n    completed_task_count = 0;\n    members.resize(M_MEMBERS);\n    estimated_skills.assign(M_MEMBERS, std::vector<double>(K, INITIAL_SKILL_ESTIMATE));\n    skill_lower_bounds.assign(M_MEMBERS, std::vector<int>(K, 0));\n    max_d_seen.assign(M_MEMBERS, std::vector<int>(K, 0));\n    skill_update_counts.assign(M_MEMBERS, std::vector<int>(K, 0));\n}\n\nvoid update_skills(int member_id, int task_id, int duration) {\n    for (int k = 0; k < K; ++k) {\n        max_d_seen[member_id][k] = std::max(max_d_seen[member_id][k], D[task_id][k]);\n        if (D[task_id][k] > 0) {\n            skill_update_counts[member_id][k]++;\n        }\n    }\n\n    double predicted_w = estimate_work(task_id, member_id);\n    \n    if (duration == 1) {\n        for (int k = 0; k < K; ++k) {\n            skill_lower_bounds[member_id][k] = std::max(skill_lower_bounds[member_id][k], D[task_id][k]);\n            estimated_skills[member_id][k] = std::max(estimated_skills[member_id][k], (double)skill_lower_bounds[member_id][k]);\n        }\n    } else {\n        double observed_w = duration;\n        \n        if (predicted_w < 1e-6) { // Predicted T=1, but was wrong\n            std::vector<int> candidate_k;\n            for(int k=0; k<K; ++k) if(D[task_id][k] > 0) candidate_k.push_back(k);\n            if (!candidate_k.empty()) {\n                std::vector<double> blame_weights;\n                double total_blame = 0;\n                for (int k : candidate_k) {\n                    double weight = exp(-OVERESTIMATE_CORRECTION_FACTOR * (estimated_skills[member_id][k] - D[task_id][k]));\n                    blame_weights.push_back(weight);\n                    total_blame += weight;\n                }\n                if (total_blame > 1e-9) {\n                    for (size_t i = 0; i < candidate_k.size(); ++i) {\n                        int k = candidate_k[i];\n                        double blamed_deficiency = observed_w * blame_weights[i] / total_blame;\n                        double target_s_k = (double)D[task_id][k] - blamed_deficiency;\n                        \n                        double adaptive_lr_factor = (1.0 + 1.0 / (1.0 + skill_update_counts[member_id][k]));\n                        double effective_lr = std::min(0.99, SKILL_UPDATE_LEARNING_RATE * adaptive_lr_factor);\n                        \n                        estimated_skills[member_id][k] = (1.0 - effective_lr) * estimated_skills[member_id][k] + effective_lr * target_s_k;\n                    }\n                }\n            }\n        } else { // Standard update\n            double error = observed_w - predicted_w;\n            double total_predicted_deficiency = 0;\n            for (int k = 0; k < K; ++k) {\n                if (D[task_id][k] > estimated_skills[member_id][k]) {\n                    total_predicted_deficiency += (D[task_id][k] - estimated_skills[member_id][k]);\n                }\n            }\n            if (total_predicted_deficiency > 1e-9) {\n                 for (int k = 0; k < K; ++k) {\n                     if (D[task_id][k] > estimated_skills[member_id][k]) {\n                        double current_deficiency = D[task_id][k] - estimated_skills[member_id][k];\n                        double adjustment = error * (current_deficiency / total_predicted_deficiency);\n\n                        double adaptive_lr_factor = (1.0 + 1.0 / (1.0 + skill_update_counts[member_id][k]));\n                        double effective_lr = SKILL_UPDATE_LEARNING_RATE * adaptive_lr_factor;\n\n                        estimated_skills[member_id][k] -= effective_lr * adjustment;\n                    }\n                }\n            }\n        }\n    }\n\n    for (int k = 0; k < K; ++k) {\n        estimated_skills[member_id][k] = std::max((double)skill_lower_bounds[member_id][k], estimated_skills[member_id][k]);\n        estimated_skills[member_id][k] = std::max(0.0, estimated_skills[member_id][k]);\n    }\n    \n    std::cout << \"#s \" << member_id + 1;\n    for (int k = 0; k < K; ++k) {\n        std::cout << \" \" << static_cast<int>(round(estimated_skills[member_id][k]));\n    }\n    std::cout << std::endl;\n}","ahc006":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n#include <chrono>\n#include <random>\n\n// A fast random number generator\nclass Xoshiro256pp {\npublic:\n    using result_type = uint64_t;\n    static constexpr result_type min() { return std::numeric_limits<result_type>::min(); }\n    static constexpr result_type max() { return std::numeric_limits<result_type>::max(); }\n\n    Xoshiro256pp() : Xoshiro256pp(std::random_device{}()) {}\n    explicit Xoshiro256pp(uint64_t seed) {\n        s[0] = seed; s[1] = 0; s[2] = 0; s[3] = 0;\n    }\n\n    result_type operator()() {\n        const uint64_t result = rotl(s[0] + s[3], 23) + s[0];\n        const uint64_t t = s[1] << 17;\n        s[2] ^= s[0]; s[3] ^= s[1]; s[1] ^= s[2]; s[0] ^= s[3];\n        s[2] ^= t; s[3] = rotl(s[3], 45);\n        return result;\n    }\n\n    int next_int(int min, int max) {\n        if (min > max) return min;\n        return min + operator()() % (uint64_t)(max - min + 1);\n    }\n\n    double next_double() {\n        return (operator()() >> 11) * (1.0 / (1ULL << 53));\n    }\n\nprivate:\n    static inline uint64_t rotl(const uint64_t x, int k) {\n        return (x << k) | (x >> (64 - k));\n    }\n    uint64_t s[4];\n};\n\nXoshiro256pp rng;\n\nstruct Point {\n    int x, y;\n};\n\nstruct Order {\n    int id;\n    Point p, d;\n};\n\nconst int NUM_ORDERS_TOTAL = 1000;\nconst int ORDERS_TO_DELIVER = 50;\nconst int PATH_LEN = ORDERS_TO_DELIVER * 2;\nconst Point OFFICE = {400, 400};\nstd::vector<Order> ALL_ORDERS;\n\nint manhattan(Point p1, Point p2) {\n    return std::abs(p1.x - p2.x) + std::abs(p1.y - p2.y);\n}\n\nstruct State {\n    std::vector<int> selected_g_indices;\n    std::vector<int> path;\n    std::vector<int> pos;\n    long long cost;\n\n    State() : pos(PATH_LEN) {}\n\n    void update_pos() {\n        for (int i = 0; i < PATH_LEN; ++i) {\n            pos[path[i]] = i;\n        }\n    }\n};\n\nPoint get_coord(int node_id, const std::vector<int>& selected_g_indices) {\n    if (node_id < ORDERS_TO_DELIVER) {\n        return ALL_ORDERS[selected_g_indices[node_id]].p;\n    } else {\n        return ALL_ORDERS[selected_g_indices[node_id - ORDERS_TO_DELIVER]].d;\n    }\n}\n\nlong long calculate_full_cost(const std::vector<int>& path, const std::vector<int>& selected_g_indices) {\n    if (path.empty()) return 0;\n    long long total_dist = 0;\n    total_dist += manhattan(OFFICE, get_coord(path[0], selected_g_indices));\n    for (size_t i = 0; i < path.size() - 1; ++i) {\n        total_dist += manhattan(get_coord(path[i], selected_g_indices), get_coord(path[i+1], selected_g_indices));\n    }\n    total_dist += manhattan(get_coord(path.back(), selected_g_indices), OFFICE);\n    return total_dist;\n}\n\nlong long calculate_replace_delta(int local_idx, int new_g_idx, const State& state) {\n    int g_idx_to_remove = state.selected_g_indices[local_idx];\n    int p_node = local_idx;\n    int d_node = local_idx + ORDERS_TO_DELIVER;\n    int p_pos = state.pos[p_node];\n    int d_pos = state.pos[d_node];\n\n    Point p_old = ALL_ORDERS[g_idx_to_remove].p;\n    Point d_old = ALL_ORDERS[g_idx_to_remove].d;\n    Point p_new = ALL_ORDERS[new_g_idx].p;\n    Point d_new = ALL_ORDERS[new_g_idx].d;\n    long long delta = 0;\n    \n    Point p_prev_coord = (p_pos == 0) ? OFFICE : get_coord(state.path[p_pos-1], state.selected_g_indices);\n    Point p_next_coord = get_coord(state.path[p_pos+1], state.selected_g_indices);\n    Point d_prev_coord = get_coord(state.path[d_pos-1], state.selected_g_indices);\n    Point d_next_coord = (d_pos == PATH_LEN-1) ? OFFICE : get_coord(state.path[d_pos+1], state.selected_g_indices);\n\n    if (d_pos == p_pos + 1) { // adjacent\n        delta -= manhattan(p_prev_coord, p_old) + manhattan(p_old, d_old) + manhattan(d_old, d_next_coord);\n        delta += manhattan(p_prev_coord, p_new) + manhattan(p_new, d_new) + manhattan(d_new, d_next_coord);\n    } else {\n        delta -= manhattan(p_prev_coord, p_old) + manhattan(p_old, p_next_coord);\n        delta += manhattan(p_prev_coord, p_new) + manhattan(p_new, p_next_coord);\n        delta -= manhattan(d_prev_coord, d_old) + manhattan(d_old, d_next_coord);\n        delta += manhattan(d_prev_coord, d_new) + manhattan(d_new, d_next_coord);\n    }\n    return delta;\n}\n\nvoid solve() {\n    auto start_time = std::chrono::steady_clock::now();\n\n    ALL_ORDERS.resize(NUM_ORDERS_TOTAL);\n    for (int i = 0; i < NUM_ORDERS_TOTAL; ++i) {\n        ALL_ORDERS[i].id = i + 1;\n        std::cin >> ALL_ORDERS[i].p.x >> ALL_ORDERS[i].p.y >> ALL_ORDERS[i].d.x >> ALL_ORDERS[i].d.y;\n    }\n\n    // --- Initial Solution ---\n    State current_state;\n    std::vector<int> order_indices(NUM_ORDERS_TOTAL);\n    std::iota(order_indices.begin(), order_indices.end(), 0);\n    std::sort(order_indices.begin(), order_indices.end(), [&](int a, int b) {\n        Point center_a = {(ALL_ORDERS[a].p.x + ALL_ORDERS[a].d.x) / 2, (ALL_ORDERS[a].p.y + ALL_ORDERS[a].d.y) / 2};\n        Point center_b = {(ALL_ORDERS[b].p.x + ALL_ORDERS[b].d.x) / 2, (ALL_ORDERS[b].p.y + ALL_ORDERS[b].d.y) / 2};\n        return manhattan(OFFICE, center_a) < manhattan(OFFICE, center_b);\n    });\n    current_state.selected_g_indices.assign(order_indices.begin(), order_indices.begin() + ORDERS_TO_DELIVER);\n\n    for (int i = 0; i < ORDERS_TO_DELIVER; ++i) { // Greedy Insertion\n        int p_node = i;\n        int d_node = i + ORDERS_TO_DELIVER;\n        \n        long long min_p_cost_increase = -1; int best_p_pos = 0;\n        for (int j = 0; j <= (int)current_state.path.size(); ++j) {\n            Point prev = (j == 0) ? OFFICE : get_coord(current_state.path[j-1], current_state.selected_g_indices);\n            Point next = (j == (int)current_state.path.size()) ? OFFICE : get_coord(current_state.path[j], current_state.selected_g_indices);\n            Point current = get_coord(p_node, current_state.selected_g_indices);\n            long long cost_increase = manhattan(prev, current) + manhattan(current, next) - manhattan(prev, next);\n            if (min_p_cost_increase == -1 || cost_increase < min_p_cost_increase) {\n                min_p_cost_increase = cost_increase; best_p_pos = j;\n            }\n        }\n        current_state.path.insert(current_state.path.begin() + best_p_pos, p_node);\n\n        long long min_d_cost_increase = -1; int best_d_pos = 0;\n        for (int j = best_p_pos + 1; j <= (int)current_state.path.size(); ++j) {\n            Point prev = get_coord(current_state.path[j-1], current_state.selected_g_indices);\n            Point next = (j == (int)current_state.path.size()) ? OFFICE : get_coord(current_state.path[j], current_state.selected_g_indices);\n            Point current = get_coord(d_node, current_state.selected_g_indices);\n            long long cost_increase = manhattan(prev, current) + manhattan(current, next) - manhattan(prev, next);\n            if (min_d_cost_increase == -1 || cost_increase < min_d_cost_increase) {\n                min_d_cost_increase = cost_increase; best_d_pos = j;\n            }\n        }\n        current_state.path.insert(current_state.path.begin() + best_d_pos, d_node);\n    }\n    \n    current_state.cost = calculate_full_cost(current_state.path, current_state.selected_g_indices);\n    current_state.update_pos();\n    State best_state = current_state;\n\n    std::vector<int> not_selected_g_indices;\n    {\n        std::vector<bool> is_selected_flags(NUM_ORDERS_TOTAL, false);\n        for(int g_idx : current_state.selected_g_indices) is_selected_flags[g_idx] = true;\n        not_selected_g_indices.reserve(NUM_ORDERS_TOTAL - ORDERS_TO_DELIVER);\n        for(int i=0; i<NUM_ORDERS_TOTAL; ++i) if(!is_selected_flags[i]) not_selected_g_indices.push_back(i);\n    }\n    \n    // --- Simulated Annealing ---\n    double T_start = 5000;\n    double T_end = 2;\n    double time_limit = 1.95;\n    \n    while (true) {\n        auto current_time = std::chrono::steady_clock::now();\n        double elapsed_time = std::chrono::duration<double>(current_time - start_time).count();\n        if (elapsed_time > time_limit) break;\n        double T = T_start * std::pow(T_end / T_start, elapsed_time / time_limit);\n        \n        double move_type = rng.next_double();\n        \n        if (move_type < 0.4) { // Move 1: Smart Replace Order\n            int local_idx_to_remove = rng.next_int(0, ORDERS_TO_DELIVER - 1);\n            int g_idx_to_remove = current_state.selected_g_indices[local_idx_to_remove];\n\n            int best_not_selected_vec_idx = -1;\n            int best_new_g_idx = -1;\n            long long best_delta = -1;\n            const int K = 10;\n            for (int k = 0; k < K; ++k) {\n                int not_selected_vec_idx = rng.next_int(0, not_selected_g_indices.size() - 1);\n                int new_g_idx = not_selected_g_indices[not_selected_vec_idx];\n                long long current_delta = calculate_replace_delta(local_idx_to_remove, new_g_idx, current_state);\n                if (best_delta == -1 || current_delta < best_delta) {\n                    best_delta = current_delta;\n                    best_not_selected_vec_idx = not_selected_vec_idx;\n                    best_new_g_idx = new_g_idx;\n                }\n            }\n            if (best_delta < 0 || rng.next_double() < std::exp(-best_delta / T)) {\n                current_state.selected_g_indices[local_idx_to_remove] = best_new_g_idx;\n                not_selected_g_indices[best_not_selected_vec_idx] = g_idx_to_remove;\n                current_state.cost += best_delta;\n                if (current_state.cost < best_state.cost) best_state = current_state;\n            }\n        } else if (move_type < 0.65) { // Move 2: 2-opt\n            int i = rng.next_int(0, PATH_LEN - 1);\n            int j = rng.next_int(0, PATH_LEN - 1);\n            if (i >= j) std::swap(i, j);\n            if (j <= i) continue;\n            \n            bool possible = true;\n            for (int k = 0; k < ORDERS_TO_DELIVER; ++k) {\n                if (current_state.pos[k] >= i && current_state.pos[k] <= j && current_state.pos[k + ORDERS_TO_DELIVER] >= i && current_state.pos[k + ORDERS_TO_DELIVER] <= j) {\n                    possible = false; break;\n                }\n            }\n            if (!possible) continue;\n            \n            Point pi = get_coord(current_state.path[i], current_state.selected_g_indices);\n            Point pj = get_coord(current_state.path[j], current_state.selected_g_indices);\n            Point pi_prev = (i > 0) ? get_coord(current_state.path[i-1], current_state.selected_g_indices) : OFFICE;\n            Point pj_next = (j < PATH_LEN-1) ? get_coord(current_state.path[j+1], current_state.selected_g_indices) : OFFICE;\n            long long delta = manhattan(pi_prev, pj) + manhattan(pi, pj_next) - manhattan(pi_prev, pi) - manhattan(pj, pj_next);\n\n            if (delta < 0 || rng.next_double() < std::exp(-delta / T)) {\n                std::reverse(current_state.path.begin() + i, current_state.path.begin() + j + 1);\n                for(int k=i; k<=j; ++k) current_state.pos[current_state.path[k]] = k;\n                current_state.cost += delta;\n                if (current_state.cost < best_state.cost) best_state = current_state;\n            }\n        } else if (move_type < 0.9) { // Move 3: Relocate\n            int i = rng.next_int(0, PATH_LEN - 1);\n            int node_to_move = current_state.path[i];\n\n            int order_idx = node_to_move % ORDERS_TO_DELIVER;\n            int min_j, max_j;\n            if (node_to_move < ORDERS_TO_DELIVER) {\n                min_j = 0; max_j = current_state.pos[order_idx + ORDERS_TO_DELIVER];\n            } else {\n                min_j = current_state.pos[order_idx] + 1; max_j = PATH_LEN;\n            }\n            if (max_j - min_j <= 1) continue;\n            \n            int j = rng.next_int(min_j, max_j);\n            if (j == i || j == i + 1) continue;\n\n            Point pi = get_coord(current_state.path[i], current_state.selected_g_indices);\n            Point pi_prev = (i > 0) ? get_coord(current_state.path[i-1], current_state.selected_g_indices) : OFFICE;\n            Point pi_next = (i < PATH_LEN-1) ? get_coord(current_state.path[i+1], current_state.selected_g_indices) : OFFICE;\n            \n            long long delta = (manhattan(pi_prev, pi_next) - manhattan(pi_prev, pi) - manhattan(pi, pi_next));\n            \n            int temp_path_len = PATH_LEN - 1;\n            int insert_idx_in_temp = (j > i) ? j - 1 : j;\n            Point pj_prev = (insert_idx_in_temp > 0) ? get_coord(current_state.path[insert_idx_in_temp -1 + (i < insert_idx_in_temp)], current_state.selected_g_indices) : OFFICE;\n            Point pj = (insert_idx_in_temp < temp_path_len) ? get_coord(current_state.path[insert_idx_in_temp + (i < insert_idx_in_temp)], current_state.selected_g_indices) : OFFICE;\n            delta += (manhattan(pj_prev, pi) + manhattan(pi, pj) - manhattan(pj_prev, pj));\n\n            if (delta < 0 || rng.next_double() < std::exp(-delta / T)) {\n                current_state.path.erase(current_state.path.begin() + i);\n                current_state.path.insert(current_state.path.begin() + (j > i ? j - 1 : j), node_to_move);\n                current_state.update_pos();\n                current_state.cost += delta;\n                if (current_state.cost < best_state.cost) best_state = current_state;\n            }\n        } else { // Move 4: Swap\n            int i = rng.next_int(0, PATH_LEN - 1);\n            int j = rng.next_int(0, PATH_LEN - 1);\n            if (i >= j) std::swap(i,j);\n            if (i == j) continue;\n            \n            int u = current_state.path[i], v = current_state.path[j];\n            if (u % ORDERS_TO_DELIVER == v % ORDERS_TO_DELIVER) continue;\n            \n            if (u < ORDERS_TO_DELIVER) { if (j > current_state.pos[u + ORDERS_TO_DELIVER]) continue; } \n            else { if (j < current_state.pos[u - ORDERS_TO_DELIVER]) continue; }\n            if (v < ORDERS_TO_DELIVER) { if (i > current_state.pos[v + ORDERS_TO_DELIVER]) continue; }\n            else { if (i < current_state.pos[v - ORDERS_TO_DELIVER]) continue; }\n\n            long long delta = 0;\n            Point Pu = get_coord(u, current_state.selected_g_indices);\n            Point Pv = get_coord(v, current_state.selected_g_indices);\n            Point Pu_prev = (i > 0) ? get_coord(current_state.path[i-1], current_state.selected_g_indices) : OFFICE;\n            Point Pv_next = (j < PATH_LEN-1) ? get_coord(current_state.path[j+1], current_state.selected_g_indices) : OFFICE;\n            \n            if (j == i + 1) {\n                delta = manhattan(Pu_prev, Pv) + manhattan(Pu, Pv_next) - manhattan(Pu_prev, Pu) - manhattan(Pv, Pv_next);\n            } else {\n                Point Pu_next = get_coord(current_state.path[i+1], current_state.selected_g_indices);\n                Point Pv_prev = get_coord(current_state.path[j-1], current_state.selected_g_indices);\n                delta -= manhattan(Pu_prev, Pu) + manhattan(Pu, Pu_next);\n                delta -= manhattan(Pv_prev, Pv) + manhattan(Pv, Pv_next);\n                delta += manhattan(Pu_prev, Pv) + manhattan(Pv, Pu_next);\n                delta += manhattan(Pv_prev, Pu) + manhattan(Pu, Pv_next);\n            }\n\n            if (delta < 0 || rng.next_double() < std::exp(-delta / T)) {\n                std::swap(current_state.path[i], current_state.path[j]);\n                current_state.pos[u] = j; current_state.pos[v] = i;\n                current_state.cost += delta;\n                if (current_state.cost < best_state.cost) best_state = current_state;\n            }\n        }\n    }\n    \n    // Output\n    std::cout << ORDERS_TO_DELIVER;\n    for (int g_idx : best_state.selected_g_indices) std::cout << \" \" << ALL_ORDERS[g_idx].id;\n    std::cout << std::endl;\n\n    std::cout << best_state.path.size() + 2;\n    std::cout << \" \" << OFFICE.x << \" \" << OFFICE.y;\n    for (int node_id : best_state.path) {\n        Point p = get_coord(node_id, best_state.selected_g_indices);\n        std::cout << \" \" << p.x << \" \" << p.y;\n    }\n    std::cout << \" \" << OFFICE.x << \" \" << OFFICE.y << std::endl;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <map>\n#include <tuple>\n#include <iterator> // For std::make_move_iterator\n#include <utility>  // For std::pair\n\n// Using AtCoder Library's DSU\n#include <atcoder/dsu>\n\nstruct Point {\n    int x, y;\n};\n\nstruct Edge {\n    int u, v, id;\n    int original_d;\n};\n\nlong long dist_sq(const Point& p1, const Point& p2) {\n    long long dx = p1.x - p2.x;\n    long long dy = p1.y - p2.y;\n    return dx * dx + dy * dy;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    const int N = 400;\n    const int M = 1995;\n\n    std::vector<Point> vertices(N);\n    for (int i = 0; i < N; ++i) {\n        std::cin >> vertices[i].x >> vertices[i].y;\n    }\n\n    std::vector<Edge> edges(M);\n    std::map<std::pair<int, int>, int> edge_to_id;\n    for (int i = 0; i < M; ++i) {\n        edges[i].id = i;\n        std::cin >> edges[i].u >> edges[i].v;\n        edges[i].original_d = std::round(std::sqrt(dist_sq(vertices[edges[i].u], vertices[edges[i].v])));\n        edge_to_id[{edges[i].u, edges[i].v}] = i;\n    }\n\n    // --- Preprocessing ---\n    std::vector<int> importance(M, 0);\n    {\n        std::vector<std::tuple<int, int, int>> all_possible_edges;\n        all_possible_edges.reserve(N * (N - 1) / 2);\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) {\n                int d = std::round(std::sqrt(dist_sq(vertices[i], vertices[j])));\n                all_possible_edges.emplace_back(d, i, j);\n            }\n        }\n        std::sort(all_possible_edges.begin(), all_possible_edges.end());\n\n        std::vector<bool> used_in_mst(all_possible_edges.size(), false);\n        for (int k = 1; k <= 5; ++k) {\n            atcoder::dsu dsu_mst(N);\n            int edges_in_tree = 0;\n            for (size_t i = 0; i < all_possible_edges.size(); ++i) {\n                if (used_in_mst[i]) continue;\n                auto [d, u, v] = all_possible_edges[i];\n                if (dsu_mst.same(u, v)) continue;\n                dsu_mst.merge(u, v);\n                used_in_mst[i] = true;\n                if (edge_to_id.count({u, v})) {\n                    int original_id = edge_to_id.at({u, v});\n                    if (importance[original_id] == 0) {\n                        importance[original_id] = k;\n                    }\n                }\n                edges_in_tree++;\n                if (edges_in_tree == N - 1) break;\n            }\n        }\n    }\n\n    std::map<std::pair<int, int>, int> edge_id_by_pair;\n    for (int i = 0; i < M; ++i) {\n        edge_id_by_pair[{edges[i].u, edges[i].v}] = i;\n    }\n\n    // --- Main Loop ---\n    atcoder::dsu dsu_main(N);\n    std::vector<std::vector<int>> component_members(N);\n    for(int i = 0; i < N; ++i) {\n        component_members[i] = {i};\n    }\n\n    for (int i = 0; i < M; ++i) {\n        int l;\n        std::cin >> l;\n\n        int u = edges[i].u;\n        int v = edges[i].v;\n\n        if (dsu_main.same(u, v)) {\n            std::cout << 0 << std::endl;\n            continue;\n        }\n\n        int root_u = dsu_main.leader(u);\n        int root_v = dsu_main.leader(v);\n\n        auto find_top2_d_alternatives = \n            [&](const std::vector<int>& comp1, const std::vector<int>& comp2, int current_edge_id) {\n            int min_d1 = -1, min_d2 = -1;\n            for (int member1 : comp1) {\n                for (int member2 : comp2) {\n                    int p1 = std::min(member1, member2);\n                    int p2 = std::max(member1, member2);\n                    auto it = edge_id_by_pair.find({p1, p2});\n                    if (it != edge_id_by_pair.end()) {\n                        int edge_idx = it->second;\n                        if (edge_idx > current_edge_id) {\n                            int d_val = edges[edge_idx].original_d;\n                            if (min_d1 == -1 || d_val < min_d1) {\n                                min_d2 = min_d1;\n                                min_d1 = d_val;\n                            } else if (min_d2 == -1 || d_val < min_d2) {\n                                min_d2 = d_val;\n                            }\n                        }\n                    }\n                }\n            }\n            return std::pair{min_d1, min_d2};\n        };\n        \n        std::pair<int, int> top2_alts;\n        if (component_members[root_u].size() < component_members[root_v].size()) {\n            top2_alts = find_top2_d_alternatives(component_members[root_u], component_members[root_v], i);\n        } else {\n            top2_alts = find_top2_d_alternatives(component_members[root_v], component_members[root_u], i);\n        }\n        auto [min_d1, min_d2] = top2_alts;\n\n        bool take_edge = false;\n        if (min_d1 == -1) {\n            take_edge = true;\n        } else {\n            double risk_factor;\n            if (min_d2 == -1) {\n                risk_factor = 1.15; // Only one alternative, high risk, be more lenient.\n            } else {\n                double ratio = std::min(static_cast<double>(min_d2) / min_d1, 3.0);\n                // If backup is good (ratio~1), be pickier (risk_factor < 1).\n                // If backup is bad (ratio>1), be more lenient (risk_factor > 1).\n                risk_factor = 0.9 + 0.2 * (ratio - 1.0); \n            }\n            \n            int imp = importance[i];\n            if (imp == 0) imp = 6;\n            \n            double alpha_k;\n            switch(imp) {\n                case 1: alpha_k = 1.4; break;\n                case 2: alpha_k = 1.2; break;\n                case 3: alpha_k = 1.0; break;\n                case 4: alpha_k = 0.85; break;\n                case 5: alpha_k = 0.7; break;\n                default: alpha_k = 0.6; break;\n            }\n\n            double progress = static_cast<double>(i) / (M - 1);\n            double time_factor = 0.7 + 1.1 * progress * progress;\n\n            double expected_alt_cost = 2.0 * min_d1;\n            double threshold = alpha_k * time_factor * risk_factor * expected_alt_cost;\n\n            if (l < threshold) {\n                take_edge = true;\n            }\n        }\n        \n        if (take_edge) {\n            std::cout << 1 << std::endl;\n            int old_root_u = dsu_main.leader(u);\n            int old_root_v = dsu_main.leader(v);\n            dsu_main.merge(u, v);\n            int new_root = dsu_main.leader(u);\n            if (new_root == old_root_u) {\n                component_members[old_root_u].insert(component_members[old_root_u].end(),\n                    std::make_move_iterator(component_members[old_root_v].begin()),\n                    std::make_move_iterator(component_members[old_root_v].end()));\n                component_members[old_root_v].clear();\n            } else {\n                component_members[old_root_v].insert(component_members[old_root_v].end(),\n                    std::make_move_iterator(component_members[old_root_u].begin()),\n                    std::make_move_iterator(component_members[old_root_u].end()));\n                component_members[old_root_u].clear();\n            }\n        } else {\n            std::cout << 0 << std::endl;\n        }\n    }\n\n    return 0;\n}","ahc008":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <queue>\n#include <map>\n#include <chrono>\n#include <tuple>\n#include <numeric>\n\nusing namespace std;\n\n// --- Utilities ---\nstruct Point {\n    int r, c;\n\n    bool operator==(const Point& other) const { return r == other.r && c == other.c; }\n    bool operator!=(const Point& other) const { return !(*this == other); }\n    bool operator<(const Point& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n};\n\nnamespace std {\n    template <> struct hash<Point> {\n        size_t operator()(const Point& p) const { return hash<int>()(p.r * 31 + p.c); }\n    };\n}\n\nconst int H = 30, W = 30;\nconst int DR[] = {-1, 1, 0, 0};\nconst int DC[] = {0, 0, -1, 1};\nconst char MOVE_CH[] = {'U', 'D', 'L', 'R'};\nconst char BUILD_CH[] = {'u', 'd', 'l', 'r'};\n\nint N, M;\nvector<Point> pet_pos;\nvector<int> pet_type;\nvector<Point> human_pos;\nbool is_impassable[H][W];\n\nint dist(Point p1, Point p2) {\n    return abs(p1.r - p2.r) + abs(p1.c - p2.c);\n}\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < H && c >= 0 && c < W;\n}\n\n// --- Game State & Strategy ---\nPoint rendezvous_point;\nbool is_safe[H][W];\nvector<double> danger_map(H * W, 0.0);\nint current_turn = 0;\n\nenum Phase { EXPANSION, SEALING, CONSOLIDATION };\n\n// --- A* Pathfinder ---\nstruct Node {\n    Point p;\n    int g;\n    double h;\n    double cost;\n    bool operator>(const Node& other) const { return cost > other.cost; }\n};\n\nvector<Point> find_path(Point start, Point end, const vector<Point>& temp_impassable) {\n    priority_queue<Node, vector<Node>, greater<Node>> pq;\n    map<Point, Point> parent;\n    map<Point, int> g_score;\n\n    g_score[start] = 0;\n    pq.push({start, 0, (double)dist(start, end), (double)dist(start, end)});\n\n    bool found = false;\n    while (!pq.empty()) {\n        Node current = pq.top();\n        pq.pop();\n\n        if (current.p == end) {\n            found = true;\n            break;\n        }\n\n        if (g_score.count(current.p) && current.g > g_score[current.p]) continue;\n\n        for (int i = 0; i < 4; ++i) {\n            Point next_p = {current.p.r + DR[i], current.p.c + DC[i]};\n\n            if (!is_valid(next_p.r, next_p.c) || is_impassable[next_p.r][next_p.c]) continue;\n            bool is_temp_impassable = false;\n            for(const auto& obs : temp_impassable) if(obs == next_p) is_temp_impassable = true;\n            if(is_temp_impassable) continue;\n\n            int new_g = current.g + 1;\n            if (!g_score.count(next_p) || new_g < g_score[next_p]) {\n                g_score[next_p] = new_g;\n                parent[next_p] = current.p;\n                double h_val = dist(next_p, end);\n                const double DANGER_WEIGHT = 10.0;\n                double cost = new_g + h_val + DANGER_WEIGHT * danger_map[next_p.r * W + next_p.c];\n                pq.push({next_p, new_g, h_val, cost});\n            }\n        }\n    }\n\n    if (!found) return {};\n    vector<Point> path;\n    Point curr = end;\n    while (curr != start) {\n        path.push_back(curr);\n        curr = parent[curr];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nvoid initial_plan() {\n    double pet_com_r = 0, pet_com_c = 0;\n    for (const auto& p : pet_pos) { pet_com_r += p.r; pet_com_c += p.c; }\n    pet_com_r /= N;\n    pet_com_c /= N;\n\n    vector<Point> corners = {{0, 0}, {0, W - 1}, {H - 1, 0}, {H - 1, W - 1}};\n    double max_dist = -1;\n    for (const auto& corner : corners) {\n        double d = pow(corner.r - pet_com_r, 2) + pow(corner.c - pet_com_c, 2);\n        if (d > max_dist) {\n            max_dist = d;\n            rendezvous_point = corner;\n        }\n    }\n    fill(&is_safe[0][0], &is_safe[0][0] + H * W, false);\n}\n\nvoid update_danger_map() {\n    fill(danger_map.begin(), danger_map.end(), 0.0);\n    int pet_moves[] = {0, 1, 2, 3, 2, 2}; \n    for (int i = 0; i < N; ++i) {\n        int radius = pet_moves[pet_type[i]] + 1;\n        for (int r = 0; r < H; ++r) {\n            for (int c = 0; c < W; ++c) {\n                if (dist(pet_pos[i], {r, c}) < radius) {\n                    danger_map[r * W + c] += 1.0;\n                }\n            }\n        }\n    }\n}\n\nvoid update_safe_zone() {\n    bool new_safe[H][W];\n    fill(&new_safe[0][0], &new_safe[0][0] + H * W, false);\n    queue<Point> q;\n    \n    Point start_node = rendezvous_point;\n    if(is_impassable[start_node.r][start_node.c]) {\n        bool found_any_passable = false;\n        for(int r=0; r<H && !found_any_passable; ++r) for(int c=0; c<W; ++c) {\n            if(!is_impassable[r][c]) {\n                start_node = {r,c};\n                found_any_passable = true;\n                break;\n            }\n        }\n        if(!found_any_passable) {\n            copy(&new_safe[0][0], &new_safe[0][0] + H*W, &is_safe[0][0]);\n            return;\n        }\n    }\n    q.push(start_node);\n    new_safe[start_node.r][start_node.c] = true;\n\n    while (!q.empty()) {\n        Point curr = q.front(); q.pop();\n        for (int i = 0; i < 4; ++i) {\n            Point next_p = {curr.r + DR[i], curr.c + DC[i]};\n            if (is_valid(next_p.r, next_p.c) && !is_impassable[next_p.r][next_p.c] && !new_safe[next_p.r][next_p.c]) {\n                new_safe[next_p.r][next_p.c] = true;\n                q.push(next_p);\n            }\n        }\n    }\n    copy(&new_safe[0][0], &new_safe[0][0] + H*W, &is_safe[0][0]);\n}\n\nvoid check_and_reset_plan() {\n    if (current_turn > 50 && current_turn % 20 == 0) {\n        int safe_zone_size = 0;\n        for(int r=0; r<H; ++r) for(int c=0; c<W; ++c) if(is_safe[r][c]) safe_zone_size++;\n\n        bool pet_in_safe_zone = false;\n        for (const auto& p_pos : pet_pos) {\n            if (is_safe[p_pos.r][p_pos.c]) {\n                pet_in_safe_zone = true;\n                break;\n            }\n        }\n        if (pet_in_safe_zone && safe_zone_size > 20) initial_plan();\n    }\n}\n\nstring solve() {\n    const int PHASE1_END = 260;\n    const int PHASE2_END = 290;\n    \n    if (current_turn == 0) initial_plan();\n    else check_and_reset_plan();\n\n    Phase current_phase = EXPANSION;\n    if (current_turn >= PHASE1_END) current_phase = SEALING;\n    if (current_turn >= PHASE2_END) current_phase = CONSOLIDATION;\n\n    update_danger_map();\n    update_safe_zone();\n    \n    vector<bool> can_build(H * W, true);\n    for(int r=0; r<H; ++r) for(int c=0; c<W; ++c) {\n        if (is_impassable[r][c]) can_build[r*W+c] = false;\n    }\n    for (const auto& p : human_pos) can_build[p.r*W+p.c] = false;\n    for (const auto& p : pet_pos) {\n        can_build[p.r*W+p.c] = false;\n        for (int i=0; i<4; ++i) {\n            Point adj = {p.r+DR[i], p.c+DC[i]};\n            if (is_valid(adj.r, adj.c)) can_build[adj.r*W+adj.c] = false;\n        }\n    }\n\n    vector<Point> tasks;\n    if (current_phase == EXPANSION || current_phase == SEALING) {\n        for (int r=0; r<H; ++r) for (int c=0; c<W; ++c) {\n            if (!is_safe[r][c] && !is_impassable[r][c]) {\n                for (int i=0; i<4; ++i) {\n                    Point adj = {r+DR[i], c+DC[i]};\n                    if (is_valid(adj.r, adj.c) && is_safe[adj.r][adj.c]) {\n                        tasks.push_back({r,c});\n                        break;\n                    }\n                }\n            }\n        }\n    } else { // CONSOLIDATION\n        double center_r=0, center_c=0; int count=0;\n        for (int r=0; r<H; ++r) for (int c=0; c<W; ++c) if (is_safe[r][c]) { center_r+=r; center_c+=c; count++; }\n        if (count > 0) tasks.push_back({(int)round(center_r/count), (int)round(center_c/count)});\n        else tasks.push_back(rendezvous_point);\n    }\n    \n    vector<int> human_task(M, -1);\n    using AssignmentCand = tuple<int, int, int>;\n    vector<AssignmentCand> candidates;\n    if (!tasks.empty()){\n        for (int i=0; i<M; ++i) {\n            for (int j=0; j<(int)tasks.size(); ++j) {\n                if (current_phase == CONSOLIDATION) {\n                    candidates.emplace_back(dist(human_pos[i], tasks[j]), i, j);\n                } else {\n                    int min_build_site_dist = 1e9;\n                    for(int k=0; k<4; ++k) {\n                        Point site = {tasks[j].r+DR[k], tasks[j].c+DC[k]};\n                        if(is_valid(site.r, site.c) && is_safe[site.r][site.c])\n                             min_build_site_dist = min(min_build_site_dist, dist(human_pos[i], site));\n                    }\n                    if(min_build_site_dist != 1e9) candidates.emplace_back(min_build_site_dist, i, j);\n                }\n            }\n        }\n    }\n    sort(candidates.begin(), candidates.end());\n    vector<bool> task_assigned(tasks.size(), false); vector<bool> human_assigned(M, false);\n    for(const auto& cand : candidates){\n        int d, h_id, t_id; tie(d, h_id, t_id) = cand;\n        if(!human_assigned[h_id] && !task_assigned[t_id]){\n            human_task[h_id] = t_id; human_assigned[h_id] = true; task_assigned[t_id] = true;\n        }\n    }\n    \n    string actions_str(M, '.'); vector<Point> planned_walls;\n    for (int i=0; i<M; ++i) {\n        Point current_pos = human_pos[i];\n        if (!is_safe[current_pos.r][current_pos.c] && current_phase != CONSOLIDATION) {\n            Point closest_safe_spot = {-1,-1}; int min_dist_to_safe = 1e9;\n            for(int r=0; r<H; ++r) for(int c=0; c<W; ++c) if(is_safe[r][c]) {\n                int d = dist(current_pos, {r,c});\n                if(d < min_dist_to_safe) {min_dist_to_safe = d; closest_safe_spot = {r,c};}\n            }\n            if(closest_safe_spot.r != -1) {\n                vector<Point> path = find_path(current_pos, closest_safe_spot, planned_walls);\n                if (!path.empty()) {\n                    Point next_pos = path[0];\n                    for (int d=0; d<4; ++d) if (current_pos.r+DR[d]==next_pos.r && current_pos.c+DC[d]==next_pos.c) { actions_str[i] = MOVE_CH[d]; break; }\n                }\n            }\n            continue;\n        }\n\n        if (human_task[i] == -1) continue;\n        Point task_pos = tasks[human_task[i]];\n        \n        if (current_phase == CONSOLIDATION) {\n            vector<Point> path = find_path(current_pos, task_pos, planned_walls);\n            if (!path.empty()) {\n                Point next_pos = path[0];\n                for (int d=0; d<4; ++d) if (current_pos.r+DR[d]==next_pos.r && current_pos.c+DC[d]==next_pos.c) { actions_str[i] = MOVE_CH[d]; break;}\n            }\n        } else {\n            Point best_build_site = {-1,-1}; int min_dist = 1e9;\n            for (int d=0; d<4; ++d) {\n                Point site = {task_pos.r+DR[d], task_pos.c+DC[d]};\n                if (is_valid(site.r, site.c) && is_safe[site.r][site.c]) {\n                    if (dist(current_pos, site) < min_dist) { min_dist = dist(current_pos, site); best_build_site = site;}\n                }\n            }\n            if(best_build_site.r == -1) continue;\n            \n            if (current_pos == best_build_site) {\n                if (can_build[task_pos.r*W+task_pos.c]) {\n                    for (int d=0; d<4; ++d) if (current_pos.r+DR[d]==task_pos.r && current_pos.c+DC[d]==task_pos.c) {\n                        actions_str[i] = BUILD_CH[d]; planned_walls.push_back(task_pos); break;\n                    }\n                } else {\n                    double max_flee_score = -1e9; int best_dir = -1;\n                    for (int d=0; d<4; ++d) {\n                        Point next_p = {current_pos.r+DR[d], current_pos.c+DC[d]};\n                        if (is_valid(next_p.r, next_p.c) && !is_impassable[next_p.r][next_p.c] && is_safe[next_p.r][next_p.c]) {\n                            double min_dist_to_pet = 1e9;\n                            for(const auto& p : pet_pos) min_dist_to_pet = min(min_dist_to_pet, (double)dist(p, next_p));\n                            double score = min_dist_to_pet - danger_map[next_p.r * W + next_p.c];\n                            if (score > max_flee_score) { max_flee_score = score; best_dir = d; }\n                        }\n                    }\n                    if (best_dir != -1) actions_str[i] = MOVE_CH[best_dir];\n                }\n            } else {\n                vector<Point> path = find_path(current_pos, best_build_site, planned_walls);\n                if (!path.empty()) {\n                    Point next_pos = path[0];\n                    for (int d=0; d<4; ++d) if (current_pos.r+DR[d]==next_pos.r && current_pos.c+DC[d]==next_pos.c) { actions_str[i] = MOVE_CH[d]; break;}\n                }\n            }\n        }\n    }\n    return actions_str;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false); cin.tie(NULL);\n    cin >> N;\n    pet_pos.resize(N); pet_type.resize(N);\n    for (int i=0; i<N; ++i) { cin >> pet_pos[i].r >> pet_pos[i].c >> pet_type[i]; pet_pos[i].r--; pet_pos[i].c--; }\n    cin >> M;\n    human_pos.resize(M);\n    for (int i=0; i<M; ++i) { cin >> human_pos[i].r >> human_pos[i].c; human_pos[i].r--; human_pos[i].c--; }\n    fill(&is_impassable[0][0], &is_impassable[0][0]+H*W, false);\n\n    for (int t=0; t<300; ++t) {\n        current_turn = t;\n        string actions = solve();\n        cout << actions << endl;\n        \n        vector<Point> planned_walls;\n        for(int i=0; i<M; ++i) {\n            char act = actions[i]; Point p = human_pos[i];\n            if (act == 'u') planned_walls.push_back({p.r-1, p.c}); else if (act == 'd') planned_walls.push_back({p.r+1, p.c});\n            else if (act == 'l') planned_walls.push_back({p.r, p.c-1}); else if (act == 'r') planned_walls.push_back({p.r, p.c+1});\n        }\n        for(int i=0; i<M; ++i) {\n            char act = actions[i]; Point& p = human_pos[i]; Point next_p = p;\n            if (act == 'U') next_p.r--; else if (act == 'D') next_p.r++; else if (act == 'L') next_p.c--; else if (act == 'R') next_p.c++;\n            bool blocked = false; for(const auto& w : planned_walls) if(next_p == w) blocked = true;\n            if (act >= 'A' && act <= 'Z' && !blocked) p = next_p;\n            else if (act >= 'a' && act <= 'z') {\n                if (act == 'u') is_impassable[p.r-1][p.c] = true; else if (act == 'd') is_impassable[p.r+1][p.c] = true;\n                else if (act == 'l') is_impassable[p.r][p.c-1] = true; else if (act == 'r') is_impassable[p.r][p.c+1] = true;\n            }\n        }\n        for (int i=0; i<N; ++i) {\n            string move_str; cin >> move_str;\n            for (char move : move_str) {\n                if (move == 'U') pet_pos[i].r--; else if (move == 'D') pet_pos[i].r++;\n                else if (move == 'L') pet_pos[i].c--; else if (move == 'R') pet_pos[i].c++;\n            }\n        }\n    }\n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <array>\n#include <algorithm>\n#include <cmath>\n#include <utility>\n#include <functional>\n\nusing namespace std;\n\n// Using long double for better precision\nusing ld = long double;\n\nconstexpr int N = 20;\nconstexpr int MAX_TURNS = 200;\nconstexpr int BEAM_WIDTH = 200; // Maximized beam width after reverting slow heuristic\nconstexpr int K_FOR_CENTER_OF_MASS = 10;\nconstexpr ld PROB_PRUNING_THRESH = 1e-30L;\nconstexpr ld TOTAL_PROB_THRESH = 1e-20L;\n\nstruct State {\n    int r, c;\n    bool operator==(const State& other) const {\n        return r == other.r && c == other.c;\n    }\n};\n\nstruct ProbEntry {\n    State s;\n    ld p;\n};\n\nState start_pos, target_pos;\nld forget_prob;\narray<array<bool, N - 1>, N> h_walls;\narray<array<bool, N>, N - 1> v_walls;\narray<array<int, N>, N> dist_to_target;\narray<array<array<State, 4>, N>, N> next_pos_cache;\n\nconst int DR[] = {-1, 1, 0, 0}; // U, D, L, R\nconst int DC[] = {0, 0, -1, 1};\nconst char DIRS[] = \"UDLR\";\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N;\n}\n\nState internal_move_state(State s, int dir_idx) {\n    int nr = s.r + DR[dir_idx];\n    int nc = s.c + DC[dir_idx];\n\n    if (!is_valid(nr, nc)) return s;\n    if (DR[dir_idx] == -1 && v_walls[s.r - 1][s.c]) return s;\n    if (DR[dir_idx] == 1 && v_walls[s.r][s.c]) return s;\n    if (DC[dir_idx] == -1 && h_walls[s.r][s.c - 1]) return s;\n    if (DC[dir_idx] == 1 && h_walls[s.r][s.c]) return s;\n    \n    return {nr, nc};\n}\n\nvoid precompute_moves() {\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            for (int i = 0; i < 4; ++i) {\n                next_pos_cache[r][c][i] = internal_move_state({r, c}, i);\n            }\n        }\n    }\n}\n\nState move_state(State s, int dir_idx) {\n    return next_pos_cache[s.r][s.c][dir_idx];\n}\n\nvoid bfs_from_target() {\n    for (auto& row : dist_to_target) row.fill(-1);\n    queue<State> q;\n    q.push(target_pos);\n    dist_to_target[target_pos.r][target_pos.c] = 0;\n    \n    while (!q.empty()) {\n        State u = q.front();\n        q.pop();\n        \n        for (int i = 0; i < 4; ++i) {\n            State predecessor = {u.r - DR[i], u.c - DC[i]};\n            if (!is_valid(predecessor.r, predecessor.c)) continue;\n            \n            State moved_from_predecessor = move_state(predecessor, i);\n            if (moved_from_predecessor.r == u.r && moved_from_predecessor.c == u.c) {\n                 if (dist_to_target[predecessor.r][predecessor.c] == -1) {\n                    dist_to_target[predecessor.r][predecessor.c] = dist_to_target[u.r][u.c] + 1;\n                    q.push(predecessor);\n                }\n            }\n        }\n    }\n}\n\nstruct Candidate {\n    string moves;\n    vector<ProbEntry> prob_dist;\n    ld accumulated_score;\n    ld heuristic_score;\n\n    void calculate_heuristic_score(int turn) {\n        ld future_score = 0;\n        for (const auto& entry : prob_dist) {\n            int d = dist_to_target[entry.s.r][entry.s.c];\n            if (d <= 0) continue;\n            ld expected_turns_to_reach = (ld)d / (1.0L - forget_prob);\n            if (turn + expected_turns_to_reach <= 400) {\n               future_score += entry.p * (401.0L - (turn + expected_turns_to_reach));\n            }\n        }\n        heuristic_score = accumulated_score + future_score;\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> start_pos.r >> start_pos.c >> target_pos.r >> target_pos.c;\n    double p_double;\n    cin >> p_double;\n    forget_prob = p_double;\n\n    for (int i = 0; i < N; ++i) {\n        string row; cin >> row;\n        for (int j = 0; j < N - 1; ++j) h_walls[i][j] = (row[j] == '1');\n    }\n    for (int i = 0; i < N - 1; ++i) {\n        string row; cin >> row;\n        for (int j = 0; j < N; ++j) v_walls[i][j] = (row[j] == '1');\n    }\n    \n    precompute_moves();\n    bfs_from_target();\n\n    vector<Candidate> beam;\n    {\n        Candidate initial_candidate;\n        initial_candidate.moves = \"\";\n        initial_candidate.prob_dist.push_back({start_pos, 1.0L});\n        initial_candidate.accumulated_score = 0.0L;\n        initial_candidate.calculate_heuristic_score(1);\n        beam.push_back(initial_candidate);\n    }\n    \n    array<ld, N*N> next_prob_map;\n\n    for (int t = 1; t <= MAX_TURNS; ++t) {\n        vector<Candidate> next_candidates;\n        next_candidates.reserve(beam.size() * 4);\n\n        for (const auto& cand : beam) {\n            ld total_prob_mass = 0;\n            for (const auto& entry : cand.prob_dist) {\n                total_prob_mass += entry.p;\n            }\n            if(total_prob_mass < TOTAL_PROB_THRESH) {\n                next_candidates.push_back(cand);\n                continue;\n            }\n\n            // --- DYNAMIC MOVE ORDERING ---\n            vector<ProbEntry> current_probs = cand.prob_dist;\n\n            ld dr, dc;\n            if (current_probs.empty()) {\n                dr = target_pos.r - start_pos.r;\n                dc = target_pos.c - start_pos.c;\n            } else {\n                int k_actual = min((int)current_probs.size(), K_FOR_CENTER_OF_MASS);\n                partial_sort(current_probs.begin(), current_probs.begin() + k_actual, current_probs.end(),\n                             [](const ProbEntry& a, const ProbEntry& b) {\n                                 return a.p > b.p;\n                             });\n\n                ld total_top_prob = 0;\n                ld avg_r = 0, avg_c = 0;\n                for(int i = 0; i < k_actual; ++i) {\n                    total_top_prob += current_probs[i].p;\n                    avg_r += current_probs[i].p * current_probs[i].s.r;\n                    avg_c += current_probs[i].p * current_probs[i].s.c;\n                }\n                avg_r /= total_top_prob;\n                avg_c /= total_top_prob;\n                \n                dr = target_pos.r - avg_r;\n                dc = target_pos.c - avg_c;\n            }\n            \n            vector<pair<ld, int>> move_scores;\n            move_scores.push_back({-dr, 0}); move_scores.push_back({dr, 1});\n            move_scores.push_back({-dc, 2}); move_scores.push_back({dc, 3});\n            sort(move_scores.rbegin(), move_scores.rend());\n            \n            array<int, 4> dynamic_dirs_order;\n            for(int i = 0; i < 4; ++i) dynamic_dirs_order[i] = move_scores[i].second;\n            // --- END DYNAMIC MOVE ORDERING ---\n\n            for (int dir_idx : dynamic_dirs_order) {\n                next_prob_map.fill(0.0L);\n                ld prob_reaching_this_turn = 0.0L;\n\n                for (const auto& entry : cand.prob_dist) {\n                    const State& current_pos = entry.s;\n                    const ld& current_p = entry.p;\n                    \n                    next_prob_map[current_pos.r * N + current_pos.c] += current_p * forget_prob;\n\n                    State next_pos = move_state(current_pos, dir_idx);\n                    if (next_pos == target_pos) {\n                        prob_reaching_this_turn += current_p * (1.0L - forget_prob);\n                    } else {\n                        next_prob_map[next_pos.r * N + next_pos.c] += current_p * (1.0L - forget_prob);\n                    }\n                }\n                \n                Candidate next_cand;\n                next_cand.moves = cand.moves + DIRS[dir_idx];\n                next_cand.prob_dist.reserve(cand.prob_dist.size() * 2);\n                for(int i=0; i<N*N; ++i) {\n                    if (next_prob_map[i] > PROB_PRUNING_THRESH) {\n                        next_cand.prob_dist.push_back({{i/N, i%N}, next_prob_map[i]});\n                    }\n                }\n\n                next_cand.accumulated_score = cand.accumulated_score + prob_reaching_this_turn * (401 - t);\n                next_cand.calculate_heuristic_score(t + 1);\n                \n                next_candidates.push_back(move(next_cand));\n            }\n        }\n\n        sort(next_candidates.begin(), next_candidates.end(), [](const Candidate& a, const Candidate& b) {\n            return a.heuristic_score > b.heuristic_score;\n        });\n\n        if (next_candidates.size() > BEAM_WIDTH) {\n            next_candidates.resize(BEAM_WIDTH);\n        }\n        beam = move(next_candidates);\n    }\n\n    Candidate best_candidate;\n    ld max_score = -1.0;\n    for (const auto& cand : beam) {\n        if (cand.accumulated_score > max_score) {\n            max_score = cand.accumulated_score;\n            best_candidate = cand;\n        }\n    }\n\n    cout << best_candidate.moves << endl;\n\n    return 0;\n}","ahc010":"#include <iostream>\n#include <vector>\n#include <string>\n#include <array>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <cmath>\n#include <tuple>\n\n// --- Utilities ---\nclass Timer {\n    std::chrono::time_point<std::chrono::high_resolution_clock> start_time;\npublic:\n    Timer() {\n        start_time = std::chrono::high_resolution_clock::now();\n    }\n    double get_elapsed_sec() {\n        auto now = std::chrono::high_resolution_clock::now();\n        return std::chrono::duration<double>(now - start_time).count();\n    }\n};\n\nstruct Rng {\n    std::mt19937 mt;\n    Rng() : mt(std::chrono::high_resolution_clock::now().time_since_epoch().count()) {}\n    int get_int(int min, int max) {\n        std::uniform_int_distribution<int> dist(min, max);\n        return dist(mt);\n    }\n    double get_double(double min, double max) {\n        std::uniform_real_distribution<double> dist(min, max);\n        return dist(mt);\n    }\n};\n\n// --- Problem Constants & Globals ---\nconstexpr int N = 30;\nconstexpr int di[] = {0, -1, 0, 1}; // L, U, R, D\nconstexpr int dj[] = {-1, 0, 1, 0};\nconst int to[8][4] = {\n\t{1, 0, -1, -1}, {3, -1, -1, 0}, {-1, -1, 3, 2}, {-1, 2, 1, -1},\n\t{1, 0, 3, 2},   {3, 2, 1, 0},   {2, -1, 0, -1}, {-1, 3, -1, 1},\n};\nint t_rot[8][4];\nstd::array<std::array<int, N>, N> initial_tiles;\n\nvoid precompute_rotations() {\n    for (int i = 0; i < 8; ++i) t_rot[i][0] = i;\n    for (int r = 1; r < 4; ++r) {\n        for (int i = 0; i < 8; ++i) {\n            int prev_t = t_rot[i][r - 1];\n            int next_t;\n            if (0 <= prev_t && prev_t <= 3) next_t = (prev_t + 1) % 4;\n            else if (prev_t == 4) next_t = 5;\n            else if (prev_t == 5) next_t = 4;\n            else if (prev_t == 6) next_t = 7;\n            else next_t = 6;\n            t_rot[i][r] = next_t;\n        }\n    }\n}\n\n// --- Core Logic ---\nusing RotationsGrid = std::array<std::array<int, N>, N>;\n\nstruct ScoreInfo {\n    long long product_score = 0;\n    long long total_len_score = 0;\n};\n\nScoreInfo calculate_scores(const RotationsGrid& rotations) {\n    std::array<std::array<int, N>, N> tiles;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            tiles[i][j] = t_rot[initial_tiles[i][j]][rotations[i][j]];\n        }\n    }\n\n    bool visited_edge[N][N][4] = {};\n    std::vector<int> loop_lengths;\n    long long total_path_len_sum = 0;\n\n    for (int si = 0; si < N; ++si) {\n        for (int sj = 0; sj < N; ++sj) {\n            for (int sd = 0; sd < 4; ++sd) {\n                if (visited_edge[si][sj][sd]) continue;\n\n                int ci = si, cj = sj, cd = sd;\n                int length = 0;\n                std::vector<std::tuple<int, int, int>> path_history;\n                bool is_loop = false;\n\n                for(int k=0; k < N*N*2 + 5; ++k) {\n                    path_history.emplace_back(ci, cj, cd);\n                    \n                    int d_out = to[tiles[ci][cj]][cd];\n                    if (d_out == -1) break;\n\n                    int ni = ci + di[d_out];\n                    int nj = cj + dj[d_out];\n                    \n                    if (ni < 0 || ni >= N || nj < 0 || nj >= N) break;\n                    \n                    length++;\n                    ci = ni; cj = nj; cd = (d_out + 2) % 4;\n\n                    if (ci == si && cj == sj && cd == sd) {\n                        is_loop = true;\n                        break;\n                    }\n                    if (visited_edge[ci][cj][cd]) break;\n                }\n\n                if (length > 0) {\n                    total_path_len_sum += length;\n                }\n                \n                if (is_loop) {\n                    loop_lengths.push_back(length);\n                }\n                \n                for (const auto& [pi, pj, pd] : path_history) {\n                    visited_edge[pi][pj][pd] = true;\n                }\n            }\n        }\n    }\n\n    ScoreInfo info;\n    \n    long long loop_len_sum = 0;\n    for(int len : loop_lengths) {\n        loop_len_sum += len;\n    }\n    long long open_path_len_doubled = total_path_len_sum - loop_len_sum;\n    info.total_len_score = loop_len_sum + open_path_len_doubled / 2;\n\n    if (loop_lengths.size() >= 2) {\n        std::sort(loop_lengths.rbegin(), loop_lengths.rend());\n        info.product_score = static_cast<long long>(loop_lengths[0]) * loop_lengths[1];\n    }\n\n    return info;\n}\n\n\nvoid solve() {\n    Timer timer;\n    Rng rng;\n    \n    for (int i = 0; i < N; ++i) {\n        std::string row;\n        std::cin >> row;\n        for (int j = 0; j < N; ++j) {\n            initial_tiles[i][j] = row[j] - '0';\n        }\n    }\n    precompute_rotations();\n\n    RotationsGrid current_rotations;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            current_rotations[i][j] = rng.get_int(0, 3);\n        }\n    }\n\n    RotationsGrid best_rotations_ever = current_rotations;\n    ScoreInfo current_scores = calculate_scores(current_rotations);\n    long long best_prod_score_ever = current_scores.product_score;\n\n    const double time_limit = 1.95;\n    const double phase1_time_limit = time_limit * 0.50;\n\n    // --- Phase 1: Optimize for total path length ---\n    double T_start1 = 20, T_end1 = 0.5;\n    long long current_eval_score = current_scores.total_len_score;\n    \n    while (timer.get_elapsed_sec() < phase1_time_limit) {\n        double progress = timer.get_elapsed_sec() / phase1_time_limit;\n        double T = T_start1 * std::pow(T_end1 / T_start1, progress);\n        \n        RotationsGrid next_rotations = current_rotations;\n        if (rng.get_double(0.0, 1.0) < 0.2) { \n            int r = rng.get_int(0, N - 2); int c = rng.get_int(0, N - 2);\n            for(int i=0; i<2; ++i) for(int j=0; j<2; ++j) next_rotations[r+i][c+j] = rng.get_int(0,3);\n        } else {\n            int r = rng.get_int(0, N - 1); int c = rng.get_int(0, N - 1);\n            int old_rot = next_rotations[r][c];\n            int new_rot; do { new_rot = rng.get_int(0, 3); } while (new_rot == old_rot);\n            next_rotations[r][c] = new_rot;\n        }\n\n        ScoreInfo new_scores = calculate_scores(next_rotations);\n        long long new_eval_score = new_scores.total_len_score;\n        double delta = static_cast<double>(new_eval_score - current_eval_score);\n        \n        if (delta >= 0 || rng.get_double(0.0, 1.0) < std::exp(delta / T)) {\n            current_rotations = next_rotations;\n            current_eval_score = new_eval_score;\n            current_scores = new_scores;\n        }\n        \n        if (current_scores.product_score > best_prod_score_ever) {\n            best_prod_score_ever = current_scores.product_score;\n            best_rotations_ever = current_rotations;\n        }\n    }\n    \n    // --- Phase 2: Optimize for L1 * L2 ---\n    current_rotations = best_rotations_ever;\n    current_scores = calculate_scores(current_rotations);\n    current_eval_score = current_scores.product_score;\n    \n    double T_start2 = 5000, T_end2 = 10;\n    while (timer.get_elapsed_sec() < time_limit) {\n        double elapsed_in_phase2 = timer.get_elapsed_sec() - phase1_time_limit;\n        double phase2_duration = time_limit - phase1_time_limit;\n        double progress = elapsed_in_phase2 / phase2_duration;\n        double T = T_start2 * std::pow(T_end2 / T_start2, progress);\n\n        RotationsGrid next_rotations = current_rotations;\n        if (rng.get_double(0.0, 1.0) < 0.05) {\n            int r = rng.get_int(0, N - 2); int c = rng.get_int(0, N - 2);\n            for(int i=0; i<2; ++i) for(int j=0; j<2; ++j) next_rotations[r+i][c+j] = rng.get_int(0,3);\n        } else {\n            int r = rng.get_int(0, N - 1); int c = rng.get_int(0, N - 1);\n            int old_rot = next_rotations[r][c];\n            int new_rot; do { new_rot = rng.get_int(0, 3); } while (new_rot == old_rot);\n            next_rotations[r][c] = new_rot;\n        }\n        \n        ScoreInfo new_scores = calculate_scores(next_rotations);\n        long long new_eval_score = new_scores.product_score;\n        double delta = static_cast<double>(new_eval_score - current_eval_score);\n        \n        if (delta >= 0 || rng.get_double(0.0, 1.0) < std::exp(delta / T)) {\n            current_rotations = next_rotations;\n            current_eval_score = new_eval_score;\n            if (current_eval_score > best_prod_score_ever) {\n                best_prod_score_ever = current_eval_score;\n                best_rotations_ever = current_rotations;\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            std::cout << best_rotations_ever[i][j];\n        }\n    }\n    std::cout << std::endl;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc011":"#include <iostream>\n#include <vector>\n#include <string>\n#include <array>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <cmath>\n#include <map>\n#include <queue>\n#include <unordered_map>\n#include <functional>\n\n#include <atcoder/mincostflow>\n\nusing namespace std;\n\n// --- Timer ---\nusing namespace std::chrono;\nauto start_time = high_resolution_clock::now();\ndouble time_limit = 2.85; // More conservative time limit\n\nbool is_time_over() {\n    auto current_time = high_resolution_clock::now();\n    duration<double> elapsed = current_time - start_time;\n    return elapsed.count() > time_limit;\n}\n\n// --- Random Number Generator ---\nmt19937 rng(time(0));\n\n// --- Constants and Type Definitions ---\nconstexpr int MAX_N = 10;\nconstexpr int MAX_N2 = MAX_N * MAX_N;\n\nint N, T;\narray<int, 4> dr = {-1, 1, 0, 0}; // U, D, L, R\narray<int, 4> dc = {0, 0, -1, 1};\nstring move_chars = \"UDLR\";\narray<int, 4> opposite_move_idx = {1, 0, 3, 2}; // U->D, D->U, L->R, R->L\n\nstruct Board {\n    array<int, MAX_N2> grid;\n    int empty_pos = -1;\n    void find_empty() {\n        for (int i = 0; i < N * N; ++i) {\n            if (grid[i] == 0) {\n                empty_pos = i;\n                return;\n            }\n        }\n    }\n};\n\nint char_to_hex(char c) {\n    if (c >= '0' && c <= '9') return c - '0';\n    return c - 'a' + 10;\n}\n\nstruct DSU {\n    vector<int> parent;\n    vector<int> sz;\n    DSU(int n) {\n        parent.resize(n);\n        sz.resize(n);\n        for (int i = 0; i < n; i++) {\n            parent[i] = i;\n            sz[i] = 1;\n        }\n    }\n    int find(int i) {\n        if (parent[i] == i) return i;\n        return parent[i] = find(parent[i]);\n    }\n    void unite(int i, int j) {\n        int root_i = find(i);\n        int root_j = find(j);\n        if (root_i != root_j) {\n            if (sz[root_i] < sz[root_j]) swap(root_i, root_j);\n            parent[root_j] = root_i;\n            sz[root_i] += sz[root_j];\n        }\n    }\n};\n\n// --- Global State for Solver ---\nBoard initial_board;\narray<int, 16> initial_tile_counts{};\nvector<pair<int, int>> initial_pos_by_type[16];\narray<int, MAX_N2> best_target_grid;\nlong long best_dist_score = -1;\narray<int, MAX_N2> dest_of_tile_id;\nstring ida_solution;\nconst int IDA_FOUND = -1;\nconst int IDA_TIMEOUT = -2;\n\nvoid evaluate_target(const array<int, MAX_N2>& target_grid, long long& connectivity_score, long long& dist_score) {\n    DSU dsu(N * N);\n    int edges = 0;\n    connectivity_score = 0;\n\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int pos = r * N + c;\n            if (target_grid[pos] == 0) continue;\n            if (r + 1 < N && target_grid[(r+1)*N+c] != 0 && (target_grid[pos] & 8) && (target_grid[(r+1)*N+c] & 2)) {\n                if (dsu.find(pos) == dsu.find((r+1)*N+c)) connectivity_score -= 10000000;\n                else { dsu.unite(pos, (r+1)*N+c); edges++; }\n            }\n            if (c + 1 < N && target_grid[r*N+c+1] != 0 && (target_grid[pos] & 4) && (target_grid[r*N+c+1] & 1)) {\n                if (dsu.find(pos) == dsu.find(r*N+c+1)) connectivity_score -= 10000000;\n                else { dsu.unite(pos, r*N+c+1); edges++; }\n            }\n        }\n    }\n    \n    int non_empty_cells = N * N - 1;\n    int max_comp_size = 0;\n    for(int i = 0; i < N * N; ++i) {\n        if(target_grid[i] != 0 && dsu.parent[i] == i) max_comp_size = max(max_comp_size, dsu.sz[i]);\n    }\n    \n    connectivity_score += (long long)max_comp_size * 100000;\n    if (max_comp_size == non_empty_cells && edges == non_empty_cells - 1) connectivity_score += 100000000;\n\n    vector<int> target_pos_by_type[16];\n    for(int i=0; i<N*N; ++i) if(target_grid[i] != 0) target_pos_by_type[target_grid[i]].push_back(i);\n    \n    dist_score = 0;\n    for (int type = 1; type <= 15; ++type) {\n        if (initial_tile_counts[type] == 0) continue;\n        vector<pair<int, int>> s_coords, d_coords;\n        for (auto p : initial_pos_by_type[type]) s_coords.push_back(p);\n        for (auto pos : target_pos_by_type[type]) d_coords.push_back({pos / N, pos % N});\n        sort(s_coords.begin(), s_coords.end());\n        sort(d_coords.begin(), d_coords.end());\n        for (size_t i = 0; i < s_coords.size(); ++i) dist_score += abs(s_coords[i].first - d_coords[i].first) + abs(s_coords[i].second - d_coords[i].second);\n    }\n}\n\n\n// --- IDA* Solver ---\nint calculate_h(const array<uint8_t, MAX_N2>& board_ids) {\n    int h = 0;\n    for (int i = 0; i < N * N; ++i) {\n        if (board_ids[i] != 255) { // 255 represents empty\n            int tile_id = board_ids[i];\n            int dest_pos = dest_of_tile_id[tile_id];\n            h += abs(i / N - dest_pos / N) + abs(i % N - dest_pos % N);\n        }\n    }\n    return h;\n}\n\nint ida_dfs(array<uint8_t, MAX_N2>& board_ids, int empty_pos, int g, int f_limit, int last_move_idx, string& path) {\n    int h = calculate_h(board_ids);\n    int f = g + h;\n    if (f > f_limit) return f;\n    if (h == 0) {\n        ida_solution = path;\n        return IDA_FOUND;\n    }\n    if (is_time_over()) return IDA_TIMEOUT;\n\n    int r = empty_pos / N, c = empty_pos % N;\n    int next_min_f = 1e9;\n\n    for (int i = 0; i < 4; ++i) {\n        if (g > 0 && i == opposite_move_idx[last_move_idx]) continue;\n        int nr = r + dr[i], nc = c + dc[i];\n        if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n        \n        int next_empty_pos = nr * N + nc;\n        swap(board_ids[empty_pos], board_ids[next_empty_pos]);\n        path.push_back(move_chars[i]);\n\n        int res = ida_dfs(board_ids, next_empty_pos, g + 1, f_limit, i, path);\n        \n        swap(board_ids[empty_pos], board_ids[next_empty_pos]);\n        path.pop_back();\n\n        if (res == IDA_FOUND || res == IDA_TIMEOUT) return res;\n        next_min_f = min(next_min_f, res);\n    }\n    return next_min_f;\n}\n\nstring solve_puzzle_ida() {\n    array<uint8_t, MAX_N2> initial_board_ids; // maps pos -> tile_id\n    array<int, MAX_N2> initial_pos_of_id;   // maps tile_id -> initial_pos\n    int current_id = 0;\n    for(int i = 0; i < N * N; ++i) {\n        if (initial_board.grid[i] != 0) {\n            initial_board_ids[i] = current_id;\n            initial_pos_of_id[current_id] = i;\n            current_id++;\n        } else {\n            initial_board_ids[i] = 255; // empty\n        }\n    }\n\n    for (int type = 1; type <= 15; ++type) {\n        int count = initial_tile_counts[type];\n        if (count == 0) continue;\n        \n        vector<int> type_initial_ids;\n        for(int id = 0; id < N*N-1; ++id) {\n            if (initial_board.grid[initial_pos_of_id[id]] == type) {\n                type_initial_ids.push_back(id);\n            }\n        }\n\n        vector<int> target_pos_for_type;\n        for (int i = 0; i < N * N; ++i) if (best_target_grid[i] == type) target_pos_for_type.push_back(i);\n\n        atcoder::mcf_graph<int, int> graph(2 * count + 2);\n        int s = 2 * count, t = 2 * count + 1;\n\n        for (int i = 0; i < count; ++i) {\n            graph.add_edge(s, i, 1, 0);\n            graph.add_edge(i + count, t, 1, 0);\n            for (int j = 0; j < count; ++j) {\n                int start_pos = initial_pos_of_id[type_initial_ids[i]];\n                int target_pos = target_pos_for_type[j];\n                int dist = abs(start_pos / N - target_pos / N) + abs(start_pos % N - target_pos % N);\n                graph.add_edge(i, j + count, 1, dist);\n            }\n        }\n        graph.flow(s, t, count);\n        for (auto edge : graph.edges()) {\n            if (edge.from < count && edge.to >= count && edge.to < 2 * count && edge.flow > 0) {\n                dest_of_tile_id[type_initial_ids[edge.from]] = target_pos_for_type[edge.to - count];\n            }\n        }\n    }\n    \n    int f_limit = calculate_h(initial_board_ids);\n    string path = \"\";\n    while (f_limit <= T) {\n        if (is_time_over()) break;\n        int res = ida_dfs(initial_board_ids, initial_board.empty_pos, 0, f_limit, -1, path);\n        if (res == IDA_FOUND) return ida_solution;\n        if (res == IDA_TIMEOUT) break;\n        if (res > T) break;\n        f_limit = res;\n    }\n    \n    return \"\";\n}\n\n\nint main() {\n    ios_base::sync_with_stdio(false); cin.tie(NULL);\n    cin >> N >> T;\n    for (int i = 0; i < N; ++i) {\n        string row; cin >> row;\n        for (int j = 0; j < N; ++j) {\n            int type = char_to_hex(row[j]);\n            initial_board.grid[i * N + j] = type;\n            if (type != 0) { initial_tile_counts[type]++; initial_pos_by_type[type].push_back({i, j}); }\n        }\n    }\n    initial_board.find_empty();\n\n    double sa_time_allowed = time_limit * 0.90;\n    auto sa_start_time = high_resolution_clock::now();\n\n    array<int, MAX_N2> current_grid;\n    vector<int> tiles;\n    for (int type = 1; type <= 15; ++type) for (int i = 0; i < initial_tile_counts[type]; ++i) tiles.push_back(type);\n    shuffle(tiles.begin(), tiles.end(), rng);\n    int tile_idx = 0;\n    for(int i=0; i<N*N; ++i) current_grid[i] = (i == N*N-1) ? 0 : tiles[tile_idx++];\n\n    long long current_conn_score=0, current_dist_score=0;\n    evaluate_target(current_grid, current_conn_score, current_dist_score);\n    long long best_conn_score = -1e18;\n    double start_temp = 5000, end_temp = 0.1;\n    \n    while(true) {\n        auto now = high_resolution_clock::now();\n        duration<double> elapsed = now - sa_start_time;\n        if(elapsed.count() > sa_time_allowed) break;\n        double time_progress = elapsed.count() / sa_time_allowed;\n        double temp = start_temp * pow(end_temp / start_temp, time_progress);\n        \n        for (int k=0; k<200; ++k) {\n            int p1 = rng() % (N * N), p2 = rng() % (N * N);\n            if (p1 == p2 || current_grid[p1] == 0 || current_grid[p2] == 0) continue;\n            swap(current_grid[p1], current_grid[p2]);\n            long long new_conn_score=0, new_dist_score=0;\n            evaluate_target(current_grid, new_conn_score, new_dist_score);\n            long long current_score = current_conn_score - current_dist_score * (N > 8 ? 3 : 2);\n            long long new_score = new_conn_score - new_dist_score * (N > 8 ? 3 : 2);\n\n            if (new_score > current_score || (temp > 1e-9 && uniform_real_distribution<>(0.0, 1.0)(rng) < exp((new_score - current_score) / temp))) {\n                current_conn_score = new_conn_score; current_dist_score = new_dist_score;\n                if (current_conn_score > best_conn_score || (current_conn_score == best_conn_score && current_dist_score < best_dist_score)) {\n                    best_conn_score = current_conn_score; best_dist_score = current_dist_score; best_target_grid = current_grid;\n                }\n            } else { swap(current_grid[p1], current_grid[p2]); }\n        }\n    }\n    \n    if (best_conn_score < 100000000) { cout << \"\" << endl; return 0; }\n    cout << solve_puzzle_ida() << endl;\n\n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <map>\n#include <unordered_map>\n\n// --- Utilities ---\nstruct XorShift {\n    unsigned int x, y, z, w;\n\n    XorShift() {\n        std::random_device rd;\n        x = rd();\n        y = rd();\n        z = rd();\n        w = rd();\n    }\n\n    unsigned int next() {\n        unsigned int t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));\n    }\n\n    double next_double() {\n        return next() / 4294967295.0;\n    }\n\n    int next_int(int max_val) { // [0, max_val-1]\n        return next() % max_val;\n    }\n};\n\nXorShift rnd;\nauto start_time = std::chrono::high_resolution_clock::now();\ndouble TIME_LIMIT = 2.95;\n\ndouble get_time() {\n    auto now = std::chrono::high_resolution_clock::now();\n    return std::chrono::duration_cast<std::chrono::duration<double>>(now - start_time).count();\n}\n\n// --- Data Structures ---\nconst long long INF_COORD = 1000000000;\nconst double PI = acos(-1.0L);\n\nstruct Point {\n    long long x, y;\n};\n\nstruct Line {\n    long double a, b, c; // ax+by+c=0\n};\n\nstruct LinePolar {\n    double theta, rho; // rho = x*cos(theta) + y*sin(theta)\n};\n\nstruct VectorHasher {\n    std::size_t operator()(const std::vector<int>& v) const {\n        std::size_t seed = v.size();\n        for (int i : v) {\n            seed ^= (std::size_t)i + 0x9e3779b9 + (seed << 6) + (seed >> 2);\n        }\n        return seed;\n    }\n};\n\n// --- Problem Data ---\nint N, K;\nstd::vector<int> target_a;\nstd::vector<Point> strawberries;\nstd::vector<std::vector<int>> clusters;\n\n// --- Geometry ---\nLine points_to_line(Point p1, Point p2) {\n    long double a = (long double)p1.y - p2.y;\n    long double b = (long double)p2.x - p1.x;\n    long double c = -a * p1.x - b * p1.y;\n    return {a, b, c};\n}\n\nLine perturb_line(Line l, double amount) {\n    l.c += amount;\n    return l;\n}\n\nint get_side(const Line& l, const Point& p) {\n    long double val = l.a * p.x + l.b * p.y + l.c;\n    if (std::abs(val) < 1e-9) return 0;\n    return val > 0 ? 1 : -1;\n}\n\nLine to_cartesian(LinePolar lp) {\n    return {std::cos((long double)lp.theta), std::sin((long double)lp.theta), (long double)-lp.rho};\n}\n\nLinePolar to_polar(Line l) {\n    if (std::abs(l.a) < 1e-12 && std::abs(l.b) < 1e-12) return {0,0};\n    long double norm = std::sqrt(l.a * l.a + l.b * l.b);\n    long double a_ = l.a / norm;\n    long double b_ = l.b / norm;\n    long double c_ = l.c / norm;\n    \n    double rho = -c_;\n    double theta = std::atan2((double)b_, (double)a_);\n\n    if (theta < 0) theta += 2 * PI;\n    theta = fmod(theta, 2*PI);\n    if (theta >= PI) {\n        theta -= PI;\n        rho = -rho;\n    }\n    return {(double)theta, (double)rho};\n}\n\n// --- Candidate Generation ---\nPoint get_centroid(const std::vector<int>& strawberry_indices) {\n    if (strawberry_indices.empty()) return {0, 0};\n    long long sum_x = 0, sum_y = 0;\n    for (int idx : strawberry_indices) {\n        sum_x += strawberries[idx].x;\n        sum_y += strawberries[idx].y;\n    }\n    return {sum_x / (long long)strawberry_indices.size(), sum_y / (long long)strawberry_indices.size()};\n}\n\nLine gen_candidate_p2p() {\n    int c1_idx = rnd.next_int(clusters.size());\n    int c2_idx = rnd.next_int(clusters.size());\n    if (clusters.size() > 1 && c1_idx == c2_idx) {\n        c2_idx = (c1_idx + 1) % clusters.size();\n    }\n    \n    if (clusters[c1_idx].empty() || clusters[c2_idx].empty()) {\n        Point p1 = {(long long)rnd.next_int(20001) - 10000, (long long)rnd.next_int(20001) - 10000};\n        Point p2 = {(long long)rnd.next_int(20001) - 10000, (long long)rnd.next_int(20001) - 10000};\n        if (p1.x == p2.x && p1.y == p2.y) p2.x++;\n        return points_to_line(p1, p2);\n    }\n    \n    int s1_idx = clusters[c1_idx][rnd.next_int(clusters[c1_idx].size())];\n    int s2_idx = clusters[c2_idx][rnd.next_int(clusters[c2_idx].size())];\n    Line l = points_to_line(strawberries[s1_idx], strawberries[s2_idx]);\n    return perturb_line(l, (rnd.next_double() * 2 - 1) * 0.1);\n}\n\nLine gen_candidate_centroid() {\n    int c1_idx = rnd.next_int(clusters.size());\n    int c2_idx = rnd.next_int(clusters.size());\n    if (clusters.size() > 1 && c1_idx == c2_idx) {\n        c2_idx = (c1_idx + 1) % clusters.size();\n    }\n\n    Point centroid1 = get_centroid(clusters[c1_idx]);\n    Point centroid2 = get_centroid(clusters[c2_idx]);\n    \n    if (centroid1.x == centroid2.x && centroid1.y == centroid2.y) {\n        return gen_candidate_p2p();\n    }\n\n    Point mid_point = {(centroid1.x + centroid2.x) / 2, (centroid1.y + centroid2.y) / 2};\n    Point p_on_perp = {mid_point.x - (centroid2.y - centroid1.y), mid_point.y + (centroid2.x - centroid1.x)};\n\n    Line l = points_to_line(mid_point, p_on_perp);\n    double angle = (rnd.next_double() * 2 - 1) * PI / 12.0;\n    long double cosa = cos(angle), sina = sin(angle);\n    long double new_a = l.a * cosa - l.b * sina;\n    long double new_b = l.a * sina + l.b * cosa;\n    long double new_c = -new_a * mid_point.x - new_b * mid_point.y;\n    return {new_a, new_b, new_c};\n}\n\nLine generate_candidate_line() {\n    if (clusters.size() < 2) {\n        Point p1 = {(long long)rnd.next_int(20001) - 10000, (long long)rnd.next_int(20001) - 10000};\n        Point p2 = {(long long)rnd.next_int(20001) - 10000, (long long)rnd.next_int(20001) - 10000};\n        if (p1.x == p2.x && p1.y == p2.y) p2.x++;\n        return points_to_line(p1, p2);\n    }\n    if (rnd.next_double() < 0.5) {\n        return gen_candidate_p2p();\n    } else {\n        return gen_candidate_centroid();\n    }\n}\n\n// --- Clustering ---\nvoid perform_clustering() {\n    std::vector<int> target_sizes;\n    for (int d = 1; d <= 10; ++d) {\n        for (int i = 0; i < target_a[d]; ++i) {\n            target_sizes.push_back(d);\n        }\n    }\n    std::shuffle(target_sizes.begin(), target_sizes.end(), std::mt19937(rnd.next()));\n\n    std::vector<bool> assigned(N, false);\n    int assigned_count = 0;\n\n    for (int d : target_sizes) {\n        if (assigned_count + d > N) continue;\n\n        int seed_idx = -1;\n        int start_node = rnd.next_int(N);\n        for (int i = 0; i < N; ++i) {\n            int current_node = (start_node + i) % N;\n            if (!assigned[current_node]) {\n                seed_idx = current_node;\n                break;\n            }\n        }\n        if (seed_idx == -1) break;\n\n        std::vector<std::pair<long long, int>> dists;\n        for (int i = 0; i < N; ++i) {\n            if (!assigned[i]) {\n                long long dx = strawberries[seed_idx].x - strawberries[i].x;\n                long long dy = strawberries[seed_idx].y - strawberries[i].y;\n                dists.push_back({dx * dx + dy * dy, i});\n            }\n        }\n        \n        if (dists.size() > (size_t)d) {\n            std::nth_element(dists.begin(), dists.begin() + d, dists.end());\n        }\n\n        std::vector<int> new_cluster;\n        for (int i = 0; i < std::min((int)dists.size(), d); ++i) {\n            int strawberry_idx = dists[i].second;\n            new_cluster.push_back(strawberry_idx);\n            assigned[strawberry_idx] = true;\n        }\n        clusters.push_back(new_cluster);\n        assigned_count += d;\n    }\n}\n\n\n// --- Score Calculation ---\nint calculate_score_val(const std::vector<Line>& lines) {\n    if (lines.empty()) return 0;\n    \n    std::unordered_map<std::vector<int>, int, VectorHasher> piece_counts;\n    for (int i = 0; i < N; ++i) {\n        std::vector<int> signature;\n        signature.reserve(lines.size());\n        bool on_line = false;\n        for (const auto& line : lines) {\n            int side = get_side(line, strawberries[i]);\n            if (side == 0) {\n                on_line = true;\n                break;\n            }\n            signature.push_back(side);\n        }\n        if (!on_line) {\n            piece_counts[signature]++;\n        }\n    }\n\n    std::vector<int> b(11, 0);\n    for (const auto& pair : piece_counts) {\n        if (pair.second >= 1 && pair.second <= 10) {\n            b[pair.second]++;\n        }\n    }\n\n    int score = 0;\n    for (int d = 1; d <= 10; ++d) {\n        score += std::min(target_a[d], b[d]);\n    }\n    return score;\n}\n\nstd::unordered_map<std::vector<int>, std::vector<int>, VectorHasher> current_partition;\nstd::vector<int> current_b_dist;\n\nint get_score_from_b(const std::vector<int>& b) {\n    int score = 0;\n    for (int d = 1; d <= 10; ++d) {\n        score += std::min(target_a[d], b[d]);\n    }\n    return score;\n}\n\nint calculate_score_with_new_line(const Line& new_line) {\n    std::vector<int> next_b_dist = current_b_dist;\n    for (auto const& [sig, strawberry_indices] : current_partition) {\n        int old_count = strawberry_indices.size();\n        if (old_count >= 1 && old_count <= 10) {\n            next_b_dist[old_count]--;\n        }\n        \n        int count1 = 0, count2 = 0;\n        for (int idx : strawberry_indices) {\n            int side = get_side(new_line, strawberries[idx]);\n            if (side == 1) count1++;\n            else if (side == -1) count2++;\n        }\n\n        if (count1 >= 1 && count1 <= 10) next_b_dist[count1]++;\n        if (count2 >= 1 && count2 <= 10) next_b_dist[count2]++;\n    }\n    return get_score_from_b(next_b_dist);\n}\n\nvoid add_line_to_state(const Line& new_line) {\n    auto old_partition = current_partition;\n    current_partition.clear();\n    std::vector<int> next_b_dist(11, 0);\n\n    for (auto const& [sig, strawberry_indices] : old_partition) {\n        std::vector<int> group1, group2;\n        for (int idx : strawberry_indices) {\n            int side = get_side(new_line, strawberries[idx]);\n            if (side == 1) group1.push_back(idx);\n            else if (side == -1) group2.push_back(idx);\n        }\n        if (!group1.empty()) {\n            std::vector<int> new_sig = sig; new_sig.push_back(1);\n            current_partition[new_sig] = group1;\n            int new_count = group1.size();\n            if (new_count >= 1 && new_count <= 10) next_b_dist[new_count]++;\n        }\n        if (!group2.empty()) {\n            std::vector<int> new_sig = sig; new_sig.push_back(-1);\n            current_partition[new_sig] = group2;\n            int new_count = group2.size();\n            if (new_count >= 1 && new_count <= 10) next_b_dist[new_count]++;\n        }\n    }\n    current_b_dist = next_b_dist;\n}\n\n// --- Main ---\nvoid output_solution(const std::vector<Line>& lines) {\n    std::cout << lines.size() << std::endl;\n    for (const auto& l : lines) {\n        long long p1x, p1y, p2x, p2y;\n        if (std::abs(l.b) > 1e-9 && (std::abs(l.a / l.b) < 1)) {\n            p1x = -INF_COORD; p1y = std::round(- (l.c + l.a * p1x) / l.b);\n            p2x = INF_COORD; p2y = std::round(- (l.c + l.a * p2x) / l.b);\n        } else if (std::abs(l.a) > 1e-9) {\n            p1y = -INF_COORD; p1x = std::round(- (l.c + l.b * p1y) / l.a);\n            p2y = INF_COORD; p2x = std::round(- (l.c + l.b * p2y) / l.a);\n        } else { // Should not happen with valid lines\n            p1x = 0; p1y = 0; p2x = 1; p2y = 1;\n        }\n        std::cout << p1x << \" \" << p1y << \" \" << p2x << \" \" << p2y << std::endl;\n    }\n}\n\nvoid solve() {\n    std::cin >> N >> K;\n    target_a.resize(11);\n    for (int d = 1; d <= 10; ++d) std::cin >> target_a[d];\n    strawberries.resize(N);\n    for (int i = 0; i < N; ++i) std::cin >> strawberries[i].x >> strawberries[i].y;\n    \n    perform_clustering();\n    \n    // Fast Greedy Construction\n    std::vector<Line> current_lines;\n    current_b_dist.assign(11, 0);\n    std::vector<int> initial_indices(N);\n    std::iota(initial_indices.begin(), initial_indices.end(), 0);\n    current_partition[{}] = initial_indices;\n    if (N >= 1 && N <= 10) current_b_dist[N] = 1;\n    \n    double greedy_time_limit = 1.6;\n    const int T_SEARCH = 40;\n    for (int k = 0; k < K; ++k) {\n        if (get_time() > greedy_time_limit) break;\n        Line best_line = {};\n        int best_score = -1;\n        for (int i = 0; i < T_SEARCH; ++i) {\n            Line candidate_line = generate_candidate_line();\n            int score = calculate_score_with_new_line(candidate_line);\n            if (score > best_score) {\n                best_score = score;\n                best_line = candidate_line;\n            }\n        }\n        if (best_score != -1) {\n            current_lines.push_back(best_line);\n            add_line_to_state(best_line);\n        } else break;\n    }\n    \n    while (current_lines.size() < (size_t)K) {\n        current_lines.push_back(generate_candidate_line());\n    }\n\n    // Simulated Annealing\n    std::vector<LinePolar> polar_lines;\n    polar_lines.reserve(current_lines.size());\n    for(const auto& l : current_lines) polar_lines.push_back(to_polar(l));\n    \n    int current_score = calculate_score_val(current_lines);\n    std::vector<Line> best_lines = current_lines;\n    int best_score = current_score;\n\n    double T_start = 10.0, T_end = 0.01;\n    double time_start_sa = get_time(), time_end_sa = TIME_LIMIT;\n    const double P_REPLACE = 0.1;\n\n    while(true) {\n        double current_time = get_time();\n        if (current_time >= time_end_sa) break;\n\n        double progress = (current_time - time_start_sa) / (time_end_sa - time_start_sa + 1e-9);\n        double T = T_start * std::pow(T_end / T_start, progress);\n\n        if (polar_lines.empty()) break;\n        int line_idx = rnd.next_int(polar_lines.size());\n        \n        std::vector<Line> new_lines = current_lines;\n        \n        if (rnd.next_double() < P_REPLACE) {\n            new_lines[line_idx] = generate_candidate_line();\n        } else {\n            LinePolar new_polar = polar_lines[line_idx];\n            double move_range = (1.0 - progress) * 0.5;\n            new_polar.theta += (rnd.next_double() * 2 - 1) * PI * move_range;\n            new_polar.rho += (rnd.next_double() * 2 - 1) * 10000 * move_range;\n\n            if (new_polar.theta < 0) new_polar.theta += 2*PI;\n            new_polar.theta = fmod(new_polar.theta, 2*PI);\n            if (new_polar.theta >= PI) {\n                new_polar.theta -= PI; new_polar.rho *= -1;\n            }\n            new_lines[line_idx] = to_cartesian(new_polar);\n        }\n        \n        int new_score = calculate_score_val(new_lines);\n        double delta = new_score - current_score;\n\n        if (delta > 0 || std::exp(delta / T) > rnd.next_double()) {\n            current_score = new_score;\n            current_lines = new_lines;\n            polar_lines[line_idx] = to_polar(current_lines[line_idx]);\n            if (new_score > best_score) {\n                best_score = new_score;\n                best_lines = new_lines;\n            }\n        }\n    }\n    output_solution(best_lines);\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <tuple>\n#include <chrono>\n#include <map>\n#include <queue>\n#include <set>\n\nusing namespace std;\n\n// Timer\nauto start_time = chrono::steady_clock::now();\ndouble time_limit = 4.9;\n\nbool is_time_over() {\n    auto now = chrono::steady_clock::now();\n    double elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count() / 1000.0;\n    return elapsed > time_limit;\n}\n\nint N;\nlong long M_initial;\nlong long C;\n\nstruct Point {\n    int x, y;\n\n    bool operator==(const Point& other) const {\n        return x == other.x && y == other.y;\n    }\n    bool operator<(const Point& other) const {\n        if (x != other.x) return x < other.x;\n        return y < other.y;\n    }\n    Point operator+(const Point& other) const {\n        return {x + other.x, y + other.y};\n    }\n    Point operator-(const Point& other) const {\n        return {x - other.x, y - other.y};\n    }\n};\n\nlong long dot_product(const Point& a, const Point& b) {\n    return (long long)a.x * b.x + (long long)a.y * b.y;\n}\n\nlong long get_weight(const Point& p) {\n    long long dx = p.x - C;\n    long long dy = p.y - C;\n    return dx * dx + dy * dy + 1;\n}\n\nstruct Candidate {\n    long long weight;\n    Point p_new, p_adj1, p_corner, p_adj2;\n\n    bool operator>(const Candidate& other) const {\n        return weight < other.weight;\n    }\n};\n\nbool has_dot[62][62];\nvector<Point> dots;\nvector<tuple<Point, Point, Point, Point>> solution_moves;\npriority_queue<Candidate, vector<Candidate>, greater<Candidate>> pq;\n\nmap<int, set<pair<int, int>>> H_segs, V_segs, D1_segs, D2_segs;\n\nbool is_in_bounds(const Point& p) {\n    return p.x >= 0 && p.x < N && p.y >= 0 && p.y < N;\n}\n\nbool check_perimeter_clean(const Point& p_new, const Point& p_adj1, const Point& p_corner, const Point& p_adj2) {\n    auto check_segment = [&](const Point& a, const Point& b) {\n        int dx = b.x - a.x;\n        int dy = b.y - a.y;\n        int common_divisor = std::gcd(abs(dx), abs(dy));\n        if (common_divisor <= 1) return true;\n        int step_x = dx / common_divisor;\n        int step_y = dy / common_divisor;\n        for (int i = 1; i < common_divisor; ++i) {\n            Point p = {a.x + i * step_x, a.y + i * step_y};\n            if (has_dot[p.x][p.y]) return false;\n        }\n        return true;\n    };\n    \n    if (!check_segment(p_corner, p_adj1)) return false;\n    if (!check_segment(p_adj1, p_new)) return false;\n    if (!check_segment(p_new, p_adj2)) return false;\n    if (!check_segment(p_adj2, p_corner)) return false;\n    return true;\n}\n\nbool check_segment_overlap(map<int, set<pair<int, int>>>& seg_map, int line_idx, int c1, int c2) {\n    if (c1 == c2) return false;\n    int min_c = min(c1, c2);\n    int max_c = max(c1, c2);\n\n    if (seg_map.find(line_idx) == seg_map.end()) return false;\n\n    const auto& intervals = seg_map.at(line_idx);\n    auto it = intervals.lower_bound({min_c, 0});\n\n    if (it != intervals.begin()) {\n        auto prev_it = prev(it);\n        if (max(min_c, prev_it->first) < min(max_c, prev_it->second)) return true;\n    }\n    if (it != intervals.end()) {\n        if (max(min_c, it->first) < min(max_c, it->second)) return true;\n    }\n    return false;\n}\n\nvoid add_segment(map<int, set<pair<int, int>>>& seg_map, int line_idx, int c1, int c2) {\n    if (c1 == c2) return;\n    int min_c = min(c1, c2);\n    int max_c = max(c1, c2);\n    seg_map[line_idx].insert({min_c, max_c});\n}\n\nvoid find_and_push_candidates(const Point& p_adj1, const Point& p_corner, const Point& p_adj2) {\n    Point v1 = p_adj1 - p_corner;\n    Point v2 = p_adj2 - p_corner;\n    \n    if ((v1.x == 0 && v1.y == 0) || (v2.x == 0 && v2.y == 0)) return;\n\n    bool is_axis_aligned = (v1.x == 0 || v1.y == 0);\n    bool is_45_tilted = (abs(v1.x) == abs(v1.y));\n    if (!is_axis_aligned && !is_45_tilted) {\n        return;\n    }\n\n    Point p_new = p_adj1 + p_adj2 - p_corner;\n    if (is_in_bounds(p_new) && !has_dot[p_new.x][p_new.y]) {\n        if (check_perimeter_clean(p_new, p_adj1, p_corner, p_adj2)) {\n            pq.push({get_weight(p_new), p_new, p_adj1, p_corner, p_adj2});\n        }\n    }\n}\n\nvoid find_new_candidates(const Point& p_added) {\n    for (size_t i = 0; i < dots.size() - 1; ++i) {\n        for (size_t j = i + 1; j < dots.size() - 1; ++j) {\n            const Point& p_i = dots[i];\n            const Point& p_j = dots[j];\n            \n            if (dot_product(p_i - p_added, p_j - p_added) == 0) find_and_push_candidates(p_i, p_added, p_j);\n            if (dot_product(p_added - p_i, p_j - p_i) == 0) find_and_push_candidates(p_added, p_i, p_j);\n            if (dot_product(p_added - p_j, p_i - p_j) == 0) find_and_push_candidates(p_added, p_j, p_i);\n        }\n    }\n}\n\nvoid find_initial_candidates() {\n    for (size_t i = 0; i < dots.size(); ++i) {\n        for (size_t j = i + 1; j < dots.size(); ++j) {\n            for (size_t k = j + 1; k < dots.size(); ++k) {\n                Point p_i = dots[i], p_j = dots[j], p_k = dots[k];\n                if (dot_product(p_j - p_i, p_k - p_i) == 0) find_and_push_candidates(p_j, p_i, p_k);\n                if (dot_product(p_i - p_j, p_k - p_j) == 0) find_and_push_candidates(p_i, p_j, p_k);\n                if (dot_product(p_i - p_k, p_j - p_k) == 0) find_and_push_candidates(p_i, p_k, p_j);\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N >> M_initial;\n    C = (N - 1) / 2;\n\n    for (int i = 0; i < M_initial; ++i) {\n        int x, y;\n        cin >> x >> y;\n        dots.push_back({x, y});\n        has_dot[x][y] = true;\n    }\n\n    find_initial_candidates();\n\n    while (!pq.empty() && !is_time_over()) {\n        Candidate c = pq.top();\n        pq.pop();\n\n        if (has_dot[c.p_new.x][c.p_new.y]) continue;\n\n        Point p_new = c.p_new, p_corner = c.p_corner, p_adj1 = c.p_adj1, p_adj2 = c.p_adj2;\n        if (!check_perimeter_clean(p_new, p_adj1, p_corner, p_adj2)) continue;\n\n        auto check_s = [&](const Point& u, const Point& v) {\n            if (u.y == v.y) return !check_segment_overlap(H_segs, u.y, u.x, v.x);\n            if (u.x == v.x) return !check_segment_overlap(V_segs, u.x, u.y, v.y);\n            if (u.x + u.y == v.x + v.y) return !check_segment_overlap(D1_segs, u.x + u.y, u.x, v.x);\n            return !check_segment_overlap(D2_segs, u.x - u.y, u.x, v.x);\n        };\n\n        if (!check_s(p_corner, p_adj1)) continue;\n        if (!check_s(p_adj1, p_new)) continue;\n        if (!check_s(p_new, p_adj2)) continue;\n        if (!check_s(p_adj2, p_corner)) continue;\n        \n        auto add_s = [&](const Point& u, const Point& v){\n            if (u.y == v.y) add_segment(H_segs, u.y, u.x, v.x);\n            else if (u.x == v.x) add_segment(V_segs, u.x, u.y, v.y);\n            else if (u.x + u.y == v.x + v.y) add_segment(D1_segs, u.x + u.y, u.x, v.x);\n            else add_segment(D2_segs, u.x - u.y, u.x, v.x);\n        };\n\n        add_s(p_corner, p_adj1);\n        add_s(p_adj1, p_new);\n        add_s(p_new, p_adj2);\n        add_s(p_adj2, p_corner);\n\n        solution_moves.emplace_back(p_new, p_adj1, p_corner, p_adj2);\n        dots.push_back(p_new);\n        has_dot[p_new.x][p_new.y] = true;\n        \n        find_new_candidates(p_new);\n    }\n\n    cout << solution_moves.size() << endl;\n    for (const auto& move : solution_moves) {\n        cout << get<0>(move).x << \" \" << get<0>(move).y << \" \"\n             << get<1>(move).x << \" \" << get<1>(move).y << \" \"\n             << get<2>(move).x << \" \" << get<2>(move).y << \" \"\n             << get<3>(move).x << \" \" << get<3>(move).y << endl;\n    }\n\n    return 0;\n}","ahc015":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <algorithm>\n#include <map>\n#include <cmath>\n\nconst int GRID_SIZE = 10;\n\n// Represents the state of the 10x10 grid.\nstruct Grid {\n    std::vector<std::vector<int>> board;\n\n    Grid() : board(GRID_SIZE, std::vector<int>(GRID_SIZE, 0)) {}\n\n    // Places a candy of a given flavor at the p-th empty cell (1-indexed).\n    void place(int p, int flavor) {\n        int empty_count = 0;\n        for (int i = 0; i < GRID_SIZE; ++i) {\n            for (int j = 0; j < GRID_SIZE; ++j) {\n                if (board[i][j] == 0) {\n                    empty_count++;\n                    if (empty_count == p) {\n                        board[i][j] = flavor;\n                        return;\n                    }\n                }\n            }\n        }\n    }\n};\n\n// Simulates a tilt operation on the grid and returns the new grid state.\nGrid simulate_tilt(const Grid& current_grid, char dir) {\n    Grid next_grid; // Initializes to an empty board.\n    \n    if (dir == 'F') { // Move Up\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            int current_row = 0;\n            for (int i = 0; i < GRID_SIZE; ++i) {\n                if (current_grid.board[i][j] != 0) {\n                    next_grid.board[current_row++][j] = current_grid.board[i][j];\n                }\n            }\n        }\n    } else if (dir == 'B') { // Move Down\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            int current_row = GRID_SIZE - 1;\n            for (int i = GRID_SIZE - 1; i >= 0; --i) {\n                if (current_grid.board[i][j] != 0) {\n                    next_grid.board[current_row--][j] = current_grid.board[i][j];\n                }\n            }\n        }\n    } else if (dir == 'L') { // Move Left\n        for (int i = 0; i < GRID_SIZE; ++i) {\n            int current_col = 0;\n            for (int j = 0; j < GRID_SIZE; ++j) {\n                if (current_grid.board[i][j] != 0) {\n                    next_grid.board[i][current_col++] = current_grid.board[i][j];\n                }\n            }\n        }\n    } else if (dir == 'R') { // Move Right\n        for (int i = 0; i < GRID_SIZE; ++i) {\n            int current_col = GRID_SIZE - 1;\n            for (int j = GRID_SIZE - 1; j >= 0; --j) {\n                if (current_grid.board[i][j] != 0) {\n                    next_grid.board[i][current_col--] = current_grid.board[i][j];\n                }\n            }\n        }\n    }\n    return next_grid;\n}\n\n// Calculates the sum of squares of connected component sizes using BFS.\nlong long calculate_conn_score(const Grid& grid) {\n    long long total_score = 0;\n    std::vector<std::vector<bool>> visited(GRID_SIZE, std::vector<bool>(GRID_SIZE, false));\n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            if (grid.board[i][j] != 0 && !visited[i][j]) {\n                int flavor = grid.board[i][j];\n                long long component_size = 0;\n                std::vector<std::pair<int, int>> q;\n                q.push_back({i, j});\n                visited[i][j] = true;\n                \n                size_t head = 0;\n                while(head < q.size()){\n                    auto [r, c] = q[head++];\n                    component_size++;\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 < GRID_SIZE && nc >= 0 && nc < GRID_SIZE &&\n                            !visited[nr][nc] && grid.board[nr][nc] == flavor) {\n                            visited[nr][nc] = true;\n                            q.push_back({nr, nc});\n                        }\n                    }\n                }\n                total_score += component_size * component_size;\n            }\n        }\n    }\n    return total_score;\n}\n\n// Global map from flavor to its target side.\nstd::map<int, int> target_side_map; // 0: Top, 1: Left, 3: Bottom\n\n// Calculates positioning score (negative sum of squared distances to target sides).\nlong long calculate_position_score(const Grid& grid) {\n    long long total_sq_dist = 0;\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            if (grid.board[i][j] != 0) {\n                int flavor = grid.board[i][j];\n                int target_side = target_side_map.at(flavor);\n                long long dist = 0;\n                if (target_side == 0) { // Top\n                    dist = i;\n                } else if (target_side == 1) { // Left\n                    dist = j;\n                } else { // Bottom (target_side == 3)\n                    dist = (GRID_SIZE - 1 - i);\n                }\n                total_sq_dist += dist * dist;\n            }\n        }\n    }\n    return -total_sq_dist;\n}\n\n// Calculates a penalty for adjacent (orthogonal and diagonal) different-flavor candies.\nlong long calculate_adj_penalty_score(const Grid& grid) {\n    long long penalty = 0;\n    for (int r = 0; r < GRID_SIZE; ++r) {\n        for (int c = 0; c < GRID_SIZE; ++c) {\n            if (grid.board[r][c] == 0) continue;\n            int current_flavor = grid.board[r][c];\n            \n            // Check neighbors to the right, down, and bottom-diagonals to avoid double counting.\n            if (c + 1 < GRID_SIZE && grid.board[r][c+1] != 0 && grid.board[r][c+1] != current_flavor) {\n                penalty--;\n            }\n            if (r + 1 < GRID_SIZE) {\n                if (grid.board[r+1][c] != 0 && grid.board[r+1][c] != current_flavor) {\n                    penalty--;\n                }\n                if (c + 1 < GRID_SIZE && grid.board[r+1][c+1] != 0 && grid.board[r+1][c+1] != current_flavor) {\n                    penalty--;\n                }\n                if (c - 1 >= 0 && grid.board[r+1][c-1] != 0 && grid.board[r+1][c-1] != current_flavor) {\n                    penalty--;\n                }\n            }\n        }\n    }\n    return penalty;\n}\n\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    std::vector<int> f(100);\n    std::map<int, int> flavor_counts;\n    for (int i = 0; i < 100; ++i) {\n        std::cin >> f[i];\n        flavor_counts[f[i]]++;\n    }\n    \n    std::vector<std::pair<int, int>> sorted_flavors;\n    for (int i = 1; i <= 3; ++i) {\n        sorted_flavors.push_back({flavor_counts.count(i) ? flavor_counts[i] : 0, i});\n    }\n    std::sort(sorted_flavors.rbegin(), sorted_flavors.rend());\n\n    // Target assignment: Top, Left, Bottom\n    // 0: Top, 1: Left, 3: Bottom\n    std::vector<int> target_sides = {0, 1, 3}; \n    for (size_t i = 0; i < 3; ++i) {\n        target_side_map[sorted_flavors[i].second] = target_sides[i];\n    }\n\n    Grid current_grid;\n\n    for (int t = 1; t <= 100; ++t) {\n        int p;\n        std::cin >> p;\n        current_grid.place(p, f[t - 1]);\n\n        if (t == 100) {\n            break;\n        }\n\n        char best_dir = 'F';\n        double best_score = -1e18;\n\n        const char dirs[] = {'F', 'B', 'L', 'R'};\n        for (char dir : dirs) {\n            Grid next_grid = simulate_tilt(current_grid, dir);\n            \n            long long conn_score = calculate_conn_score(next_grid);\n            long long position_score = calculate_position_score(next_grid);\n            long long adj_penalty_score = calculate_adj_penalty_score(next_grid);\n\n            double t_double = static_cast<double>(t);\n            double w_conn = t_double * t_double;\n            double w_pos = 0.5 * (101.0 - t_double) * (101.0 - t_double);\n            double w_adj = 8.0 * t_double * t_double;\n            \n            double current_total_score = w_conn * conn_score + w_pos * position_score + w_adj * adj_penalty_score;\n            \n            if (current_total_score > best_score) {\n                best_score = current_total_score;\n                best_dir = dir;\n            }\n        }\n        \n        std::cout << best_dir << std::endl;\n        current_grid = simulate_tilt(current_grid, best_dir);\n    }\n\n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <set>\n\n// Globals\nint M;\ndouble EPS;\nint N;\nstd::vector<int> clique_sizes;\nstd::vector<std::vector<bool>> H_adj;\n\n// --- Helper Functions ---\n\n// Creates the 0/1 string representation of a graph with a clique.\nstd::string clique_graph_to_string(int n, int clique_size) {\n    std::string s(n * (n - 1) / 2, '0');\n    int k = 0;\n    for (int i = 0; i < n; ++i) {\n        for (int j = i + 1; j < n; ++j) {\n            if (i < clique_size && j < clique_size) {\n                s[k] = '1';\n            }\n            k++;\n        }\n    }\n    return s;\n}\n\n// Calculates binary entropy for channel capacity calculation.\ndouble binary_entropy(double p) {\n    if (p <= 0.0 || p >= 1.0) return 0.0;\n    return -p * std::log2(p) - (1.0 - p) * std::log2(1.0 - p);\n}\n\n// A simpler, more robust heuristic for finding the dense core: sort vertices by degree.\n// This replaces the more complex and potentially buggy degeneracy ordering implementation.\nstd::vector<int> get_degree_order(int n, const std::vector<int>& initial_degrees) {\n    std::vector<int> order(n);\n    std::iota(order.begin(), order.end(), 0);\n    std::sort(order.begin(), order.end(), [&](int a, int b) {\n        return initial_degrees[a] > initial_degrees[b];\n    });\n    return order;\n}\n\n// --- Main Logic ---\n\n// Determines the number of vertices, N, based on M and epsilon.\nvoid determine_N() {\n    double alpha = 2.0 + 10.0 * EPS;\n    double capacity = std::max(0.01, 1.0 - binary_entropy(EPS));\n    double bits_needed = std::log2(M) * alpha;\n    double edges_needed = bits_needed / capacity;\n    double n_theory = (1.0 + std::sqrt(std::max(0.0, 1.0 + 8.0 * edges_needed))) / 2.0;\n    \n    N = static_cast<int>(lround(n_theory));\n    N = std::max(N, M);\n    N = std::min(100, std::max(4, N));\n}\n\n// Generates M distinct, well-spaced base graphs (cliques).\nvoid generate_base_graphs() {\n    std::set<int> st_clique_sizes;\n    if (M <= 1) {\n        st_clique_sizes.insert(0);\n    } else {\n        for (int i = 0; i < M; ++i) {\n            st_clique_sizes.insert(lround((double)i * N / (M - 1.0)));\n        }\n    }\n    \n    // A 1-clique is just an isolated vertex, indistinguishable from a 0-clique's components.\n    if (st_clique_sizes.count(1)) {\n        st_clique_sizes.erase(1);\n    }\n    \n    // Ensure we have exactly M distinct sizes.\n    for (int i = 0; i <= N && st_clique_sizes.size() < M; ++i) {\n        if (i == 1) continue;\n        st_clique_sizes.insert(i);\n    }\n    \n    clique_sizes.assign(st_clique_sizes.begin(), st_clique_sizes.end());\n    \n    std::cout << N << std::endl;\n    for (int k = 0; k < M; ++k) {\n        std::cout << clique_graph_to_string(N, clique_sizes[k]) << std::endl;\n    }\n}\n\n\nvoid solve() {\n    determine_N();\n    generate_base_graphs();\n    std::cout.flush();\n\n    H_adj.resize(N, std::vector<bool>(N));\n\n    for (int q = 0; q < 100; ++q) {\n        std::string H_str;\n        std::cin >> H_str;\n\n        int H_edges = 0;\n        int k_str_idx = 0;\n        std::vector<int> initial_degrees(N, 0);\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) {\n                H_adj[i][j] = H_adj[j][i] = (H_str[k_str_idx] == '1');\n                if (H_adj[i][j]) {\n                    H_edges++;\n                    initial_degrees[i]++;\n                    initial_degrees[j]++;\n                }\n                k_str_idx++;\n            }\n        }\n        \n        // Use the simpler degree-sort heuristic for the initial guess.\n        std::vector<int> initial_guess_order = get_degree_order(N, initial_degrees);\n\n        int best_idx = -1;\n        double min_flips = 1e18;\n\n        for (int i = 0; i < M; ++i) {\n            int C = clique_sizes[i];\n            \n            if (C <= 1) {\n                double flips = H_edges; // Flips to get an empty graph\n                if (flips < min_flips) {\n                    min_flips = flips;\n                    best_idx = i;\n                }\n                continue;\n            }\n\n            std::vector<int> S_nodes; S_nodes.reserve(C);\n            std::vector<bool> in_S(N, false);\n            for (int j = 0; j < C; ++j) {\n                S_nodes.push_back(initial_guess_order[j]);\n                in_S[initial_guess_order[j]] = true;\n            }\n\n            // Local search to refine the clique candidate set\n            const int MAX_ITERS = (EPS < 0.2) ? 5 : 10;\n            for (int iter = 0; iter < MAX_ITERS; ++iter) {\n                std::vector<int> d_S(N, 0);\n                for (int u = 0; u < N; ++u) {\n                    for (int v_node : S_nodes) {\n                        if (H_adj[u][v_node]) d_S[u]++;\n                    }\n                }\n\n                int u_to_swap = -1, min_d_in = N + 1;\n                for (int u_node : S_nodes) {\n                    if (d_S[u_node] < min_d_in) {\n                        min_d_in = d_S[u_node];\n                        u_to_swap = u_node;\n                    }\n                }\n                \n                int v_to_swap = -1, max_d_out = -1;\n                for (int v = 0; v < N; ++v) {\n                    if (!in_S[v]) {\n                        if (d_S[v] > max_d_out) {\n                            max_d_out = d_S[v];\n                            v_to_swap = v;\n                        }\n                    }\n                }\n\n                if (u_to_swap == -1 || v_to_swap == -1) break;\n                \n                int gain = max_d_out - min_d_in - (H_adj[u_to_swap][v_to_swap] ? 1 : 0);\n\n                if (gain > 0) {\n                    in_S[u_to_swap] = false;\n                    in_S[v_to_swap] = true;\n                    S_nodes.erase(std::remove(S_nodes.begin(), S_nodes.end(), u_to_swap), S_nodes.end());\n                    S_nodes.push_back(v_to_swap);\n                } else {\n                    break;\n                }\n            }\n\n            long long E_star = 0;\n            for(size_t u_idx = 0; u_idx < S_nodes.size(); ++u_idx) {\n                for(size_t v_idx = u_idx + 1; v_idx < S_nodes.size(); ++v_idx) {\n                    if(H_adj[S_nodes[u_idx]][S_nodes[v_idx]]) E_star++;\n                }\n            }\n            \n            long long E_clique = (long long)C * (C - 1) / 2;\n            double estimated_flips = (double)(E_clique - E_star) + (H_edges - E_star);\n\n            if (estimated_flips < min_flips) {\n                min_flips = estimated_flips;\n                best_idx = i;\n            }\n        }\n        \n        if (best_idx == -1) best_idx = 0; // Defensive coding, should not be needed.\n        std::cout << best_idx << std::endl;\n        std::cout.flush();\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    std::cin >> M >> EPS;\n    solve();\n    return 0;\n}","ahc017":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <iomanip>\n#include <functional>\n#include <queue>\n#include <tuple>\n\nusing namespace std;\n\n// Constants and Typedefs\nconst long long INF = 1e18;\n\n// Structs\nstruct Edge {\n    int id;\n    int u, v, w;\n};\n\nstruct Point {\n    int x, y;\n};\n\n// Utilities\nauto start_time = chrono::high_resolution_clock::now();\ndouble get_time() {\n    auto now = chrono::high_resolution_clock::now();\n    return chrono::duration_cast<chrono::duration<double>>(now - start_time).count();\n}\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// Bridge Finder for detecting 2-edge-cuts\nnamespace BridgeFinder {\n    vector<int> tin, low;\n    int timer;\n    vector<bool> visited;\n    const vector<vector<tuple<int, int, int>>>* adj_ptr;\n    vector<pair<int, int>> critical_pairs_buffer;\n    int current_ignored_edge;\n\n    void dfs(int u, int p_edge_id) {\n        visited[u] = true;\n        tin[u] = low[u] = timer++;\n        for (const auto& edge_tuple : (*adj_ptr)[u]) {\n            int v = get<0>(edge_tuple);\n            int edge_id = get<2>(edge_tuple);\n\n            if (edge_id == p_edge_id || edge_id == current_ignored_edge) continue;\n\n            if (visited[v]) {\n                low[u] = min(low[u], tin[v]);\n            } else {\n                dfs(v, edge_id);\n                low[u] = min(low[u], low[v]);\n                if (low[v] > tin[u]) {\n                    critical_pairs_buffer.emplace_back(current_ignored_edge, edge_id);\n                }\n            }\n        }\n    }\n\n    void find_bridges_in_subgraph(int ignored_edge, int N) {\n        current_ignored_edge = ignored_edge;\n        timer = 0;\n        visited.assign(N, false);\n        tin.assign(N, -1);\n        low.assign(N, -1);\n        for (int i = 0; i < N; ++i) {\n            if (!visited[i]) {\n                dfs(i, -1);\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // --- Input Reading ---\n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n\n    vector<Edge> edges(M);\n    vector<vector<tuple<int, int, int>>> adj(N);\n    for (int i = 0; i < M; ++i) {\n        edges[i].id = i;\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\n        edges[i].u--; \n        edges[i].v--;\n        adj[edges[i].u].emplace_back(edges[i].v, edges[i].w, i);\n        adj[edges[i].v].emplace_back(edges[i].u, edges[i].w, i);\n    }\n\n    vector<Point> coords(N);\n    for (int i = 0; i < N; ++i) cin >> coords[i].x >> coords[i].y;\n    \n    // --- Phase 1: Precomputation and Heuristics (Time Budget: ~2.0s) ---\n    \n    // 1a. Path Centrality\n    vector<long long> edge_path_counts(M, 0);\n    int SAMPLES = 50;\n    vector<int> sample_nodes(N);\n    iota(sample_nodes.begin(), sample_nodes.end(), 0);\n    shuffle(sample_nodes.begin(), sample_nodes.end(), rng);\n    for (int i = 0; i < min((int)sample_nodes.size(), SAMPLES); ++i) {\n        int start_node = sample_nodes[i];\n        vector<long long> dist(N, INF); vector<int> parent_edge(N, -1); dist[start_node] = 0;\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<>> pq; pq.push({0, start_node});\n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop(); if (d > dist[u]) continue;\n            for (const auto& edge_tuple : adj[u]) {\n                auto [v, w, edge_id] = edge_tuple;\n                if (dist[u] != INF && dist[u] + w < dist[v]) {\n                    dist[v] = dist[u] + w; parent_edge[v] = edge_id; pq.push({dist[v], v});\n                }\n            }\n        }\n        vector<vector<int>> tree_adj(N);\n        for(int j=0; j<N; ++j) if (parent_edge[j] != -1) {int u = (edges[parent_edge[j]].u == j) ? edges[parent_edge[j]].v : edges[parent_edge[j]].u; tree_adj[u].push_back(j);}\n        vector<int> subtree_size(N, 0); function<void(int)> dfs_size = [&](int u) {subtree_size[u] = 1; for(int v : tree_adj[u]) {dfs_size(v); subtree_size[u] += subtree_size[v];}}; dfs_size(start_node);\n        for(int j=0; j<N; ++j) if(parent_edge[j] != -1) edge_path_counts[parent_edge[j]] += (long long)subtree_size[j] * (N - subtree_size[j]);\n    }\n\n    // 1b. Edge Importance Score\n    vector<double> edge_importance(M);\n    for(int i = 0; i < M; ++i) {\n        edge_importance[i] = (double)edges[i].w * edge_path_counts[i];\n    }\n\n    // 1c. Limited Structural Analysis (Find some 2-edge-cuts)\n    vector<int> sorted_by_importance(M);\n    iota(sorted_by_importance.begin(), sorted_by_importance.end(), 0);\n    sort(sorted_by_importance.begin(), sorted_by_importance.end(), [&](int a, int b){\n        return edge_importance[a] > edge_importance[b];\n    });\n\n    BridgeFinder::adj_ptr = &adj;\n    vector<pair<int, int>> critical_pairs;\n    int C = 30; // Number of important edges to check\n    for (int i = 0; i < min(M, C); ++i) {\n        int edge_to_ignore = sorted_by_importance[i];\n        BridgeFinder::find_bridges_in_subgraph(edge_to_ignore, N);\n        for(auto& p : BridgeFinder::critical_pairs_buffer) {\n            if (p.first > p.second) swap(p.first, p.second);\n            critical_pairs.push_back(p);\n        }\n        BridgeFinder::critical_pairs_buffer.clear();\n    }\n    sort(critical_pairs.begin(), critical_pairs.end());\n    critical_pairs.erase(unique(critical_pairs.begin(), critical_pairs.end()), critical_pairs.end());\n    \n    // 1d. Interaction Matrix\n    vector<vector<float>> interactions(M, vector<float>(M));\n    vector<pair<double, double>> midpoints(M);\n    for(int i=0; i<M; ++i) midpoints[i] = {(coords[edges[i].u].x + coords[edges[i].v].x)/2.0, (coords[edges[i].u].y + coords[edges[i].v].y)/2.0};\n    const float ADJ_PENALTY = 50.0f;\n    const float CRITICAL_PENALTY = 5000.0f;\n    for(int i=0; i<M; ++i) {\n        for(int j=i+1; j<M; ++j) {\n            double dx = midpoints[i].first - midpoints[j].first;\n            double dy = midpoints[i].second - midpoints[j].second;\n            float val = 10000.0f / (dx*dx + dy*dy + 100.0f);\n            if (edges[i].u == edges[j].u || edges[i].u == edges[j].v || edges[i].v == edges[j].u || edges[i].v == edges[j].v) {\n                val += ADJ_PENALTY;\n            }\n            interactions[i][j] = interactions[j][i] = val;\n        }\n    }\n    for(const auto& p : critical_pairs) {\n        interactions[p.first][p.second] += CRITICAL_PENALTY;\n        interactions[p.second][p.first] += CRITICAL_PENALTY;\n    }\n\n    // --- Phase 2: Greedy Initial Solution ---\n    vector<vector<int>> days(D);\n    vector<int> edge_to_day(M);\n    for (int edge_idx : sorted_by_importance) {\n        int best_day = -1; float min_cost_increase = 1e18;\n        for (int d = 0; d < D; ++d) {\n            if (days[d].size() >= K) continue;\n            float cost_increase = 0;\n            for (int other_edge_idx : days[d]) cost_increase += interactions[edge_idx][other_edge_idx];\n            if (cost_increase < min_cost_increase) {\n                min_cost_increase = cost_increase; best_day = d;\n            } else if (abs(cost_increase - min_cost_increase) < 1e-6) {\n                if (best_day == -1 || days[d].size() < days[best_day].size()) best_day = d;\n            }\n        }\n        days[best_day].push_back(edge_idx); edge_to_day[edge_idx] = best_day;\n    }\n    \n    // --- Phase 3: Simulated Annealing Optimization ---\n    double start_temp = 50.0, end_temp = 0.1;\n    long long iter_count = 0;\n    double time_limit = 5.9;\n    double temp = start_temp;\n    double precompute_time = get_time();\n\n    while (true) {\n        iter_count++;\n        if ((iter_count & 255) == 0) {\n            double elapsed = get_time();\n            if (elapsed > time_limit) break;\n            double sa_progress = (elapsed - precompute_time) / (time_limit - precompute_time);\n            if (sa_progress >= 1.0) break;\n            temp = start_temp * pow(end_temp / start_temp, sa_progress);\n        }\n\n        if (uniform_int_distribution<>(0, 1)(rng) == 0) { // Move\n            int e_idx = uniform_int_distribution<>(0, M - 1)(rng);\n            int d1 = edge_to_day[e_idx]; int d2 = uniform_int_distribution<>(0, D - 1)(rng);\n            if (d1 == d2 || days[d2].size() >= K) continue;\n            \n            float cost_d1_old = 0; for(int other_e : days[d1]) if(other_e != e_idx) cost_d1_old += interactions[e_idx][other_e];\n            float cost_d2_new = 0; for(int other_e : days[d2]) cost_d2_new += interactions[e_idx][other_e];\n            double delta = cost_d2_new - cost_d1_old;\n\n            if (delta < 0 || (temp > 1e-9 && uniform_real_distribution<>(0.0, 1.0)(rng) < exp(-delta / temp))) {\n                auto& d1_edges = days[d1]; d1_edges.erase(remove(d1_edges.begin(), d1_edges.end(), e_idx), d1_edges.end());\n                days[d2].push_back(e_idx); edge_to_day[e_idx] = d2;\n            }\n        } else { // Swap\n            int e1_idx = uniform_int_distribution<>(0, M - 1)(rng);\n            int e2_idx = uniform_int_distribution<>(0, M - 1)(rng);\n            if (e1_idx == e2_idx) continue;\n            int d1 = edge_to_day[e1_idx], d2 = edge_to_day[e2_idx];\n            if (d1 == d2) continue;\n\n            float cost1_in_d1 = 0, cost2_in_d2 = 0, cost1_in_d2 = 0, cost2_in_d1 = 0;\n            for(int e : days[d1]) if (e != e1_idx) { cost1_in_d1 += interactions[e1_idx][e]; cost2_in_d1 += interactions[e2_idx][e]; }\n            for(int e : days[d2]) if (e != e2_idx) { cost2_in_d2 += interactions[e2_idx][e]; cost1_in_d2 += interactions[e1_idx][e]; }\n            double delta = (cost2_in_d1 + cost1_in_d2) - (cost1_in_d1 + cost2_in_d2);\n            \n            if (delta < 0 || (temp > 1e-9 && uniform_real_distribution<>(0.0, 1.0)(rng) < exp(-delta / temp))) {\n                auto& d1_edges = days[d1]; auto& d2_edges = days[d2];\n                *find(d1_edges.begin(), d1_edges.end(), e1_idx) = e2_idx;\n                *find(d2_edges.begin(), d2_edges.end(), e2_idx) = e1_idx;\n                edge_to_day[e1_idx] = d2; edge_to_day[e2_idx] = d1;\n            }\n        }\n    }\n\n    // --- Output ---\n    vector<int> result(M);\n    for (int i = 0; i < M; ++i) {\n        // edges[i] is the i-th edge in my internal list\n        // edges[i].id is its original ID from the input\n        // edge_to_day[i] is the day for my internal edge i\n        result[edges[i].id] = edge_to_day[i] + 1;\n    }\n    for (int i = 0; i < M; ++i) {\n        cout << result[i] << (i == M - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n\n    return 0;\n}","ahc019":"#include <iostream>\n#include <vector>\n#include <string>\n#include <tuple>\n#include <numeric>\n#include <algorithm>\n#include <set>\n#include <map>\n#include <chrono>\n#include <cmath>\n\nusing namespace std;\n\nint D;\nchrono::high_resolution_clock::time_point T_START;\n\nstruct Point3D {\n    int x, y, z;\n    bool operator<(const Point3D& other) const {\n        if (x != other.x) return x < other.x;\n        if (y != other.y) return y < other.y;\n        return z < other.z;\n    }\n    bool operator==(const Point3D& other) const {\n        return x == other.x && y == other.y && z == other.z;\n    }\n};\n\nPoint3D operator+(const Point3D& a, const Point3D& b) { return {a.x + b.x, a.y + b.y, a.z + b.z}; }\nPoint3D operator-(const Point3D& a, const Point3D& b) { return {a.x - b.x, a.y - b.y, a.z - b.z}; }\n\nusing Shape = vector<Point3D>;\n\nconst vector<vector<int>> ROTS = {\n    {1,0,0,0,1,0,0,0,1}, {1,0,0,0,0,-1,0,1,0}, {1,0,0,0,-1,0,0,0,-1}, {1,0,0,0,0,1,0,-1,0},\n    {-1,0,0,0,-1,0,0,0,1}, {-1,0,0,0,0,1,0,1,0}, {-1,0,0,0,1,0,0,0,-1}, {-1,0,0,0,0,-1,0,-1,0},\n    {0,1,0,1,0,0,0,0,-1}, {0,1,0,0,0,1,1,0,0}, {0,1,0,-1,0,0,0,0,1}, {0,1,0,0,0,-1,-1,0,0},\n    {0,-1,0,-1,0,0,0,0,-1}, {0,-1,0,0,0,-1,1,0,0}, {0,-1,0,1,0,0,0,0,1}, {0,-1,0,0,0,1,-1,0,0},\n    {0,0,1,0,1,0,-1,0,0}, {0,0,1,1,0,0,0,1,0}, {0,0,1,0,-1,0,1,0,0}, {0,0,1,-1,0,0,0,-1,0},\n    {0,0,-1,0,-1,0,-1,0,0}, {0,0,-1,-1,0,0,0,1,0}, {0,0,-1,0,1,0,1,0,0}, {0,0,-1,1,0,0,0,-1,0}\n};\n\nPoint3D rotate(const Point3D& p, const vector<int>& R) {\n    return {R[0]*p.x+R[1]*p.y+R[2]*p.z, R[3]*p.x+R[4]*p.y+R[5]*p.z, R[6]*p.x+R[7]*p.y+R[8]*p.z};\n}\n\nShape normalize_shape(Shape s) {\n    if (s.empty()) return {};\n    Point3D min_p = s[0];\n    for (size_t i = 1; i < s.size(); ++i) {\n        min_p.x = min(min_p.x, s[i].x); min_p.y = min(min_p.y, s[i].y); min_p.z = min(min_p.z, s[i].z);\n    }\n    for (auto& p : s) { p = p - min_p; }\n    sort(s.begin(), s.end());\n    return s;\n}\n\nShape get_canonical_shape(const Shape& s) {\n    if (s.empty()) return {};\n    Shape canonical = normalize_shape(s);\n    for (const auto& R : ROTS) {\n        Shape rotated_s;\n        for (const auto& p : s) { rotated_s.push_back(rotate(p, R)); }\n        Shape normalized_rotated = normalize_shape(rotated_s);\n        if (normalized_rotated < canonical) { canonical = normalized_rotated; }\n    }\n    return canonical;\n}\n\nstruct ProtoBlock { Shape points; int id = 0; };\nstruct PlacedBlock { Shape points; int original_idx; int id = 0; };\n\nstruct Solution {\n    long long score = -1;\n    int n = 0;\n    vector<vector<vector<int>>> b1;\n    vector<vector<vector<int>>> b2;\n    bool is_valid() const { return score != -1; }\n};\n\nbool time_limit_exceeded(int limit_ms) {\n    auto now = chrono::high_resolution_clock::now();\n    auto dur = chrono::duration_cast<chrono::milliseconds>(now - T_START).count();\n    return dur > limit_ms;\n}\n\nauto is_valid_coord = [](int x, int y, int z) { return x >= 0 && x < D && y >= 0 && y < D && z >= 0 && z < D; };\n\nSolution solve(const vector<string>& f_start_in, const vector<string>& r_start_in,\n               const vector<string>& f_target_in, const vector<string>& r_target_in, int time_limit_ms)\n{\n    vector<vector<vector<bool>>> C_start(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    vector<vector<vector<bool>>> C_target(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    vector<vector<vector<bool>>> C_common(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    for (int x=0; x<D; ++x) for (int y=0; y<D; ++y) for (int z=0; z<D; ++z) {\n        if (f_start_in[z][x] == '1' && r_start_in[z][y] == '1') C_start[x][y][z] = true;\n        if (f_target_in[z][x] == '1' && r_target_in[z][y] == '1') C_target[x][y][z] = true;\n        if (C_start[x][y][z] && C_target[x][y][z]) C_common[x][y][z] = true;\n    }\n\n    vector<ProtoBlock> common_blocks;\n    vector<vector<vector<bool>>> visited_common = C_common;\n    for (int x=0; x<D; ++x) for (int y=0; y<D; ++y) for (int z=0; z<D; ++z) {\n        if (visited_common[x][y][z]) {\n            Shape pts; vector<Point3D> q; q.push_back({x,y,z});\n            visited_common[x][y][z] = false; size_t head=0;\n            while(head < q.size()) {\n                Point3D curr = q[head++]; pts.push_back(curr);\n                int dx[]={-1,1,0,0,0,0}, dy[]={0,0,-1,1,0,0}, dz[]={0,0,0,0,-1,1};\n                for (int i=0; i<6; ++i) {\n                    Point3D next = {curr.x+dx[i], curr.y+dy[i], curr.z+dz[i]};\n                    if (is_valid_coord(next.x, next.y, next.z) && visited_common[next.x][next.y][next.z]) {\n                        visited_common[next.x][next.y][next.z] = false; q.push_back(next);\n                    }\n                }\n            }\n            common_blocks.push_back({pts, 0});\n        }\n    }\n    \n    vector<bool> f_start_req_met(D*D, false), r_start_req_met(D*D, false);\n    for (const auto& block : common_blocks) for (const auto& p : block.points) {\n        f_start_req_met[p.z*D+p.x] = true; r_start_req_met[p.z*D+p.y] = true;\n    }\n    \n    vector<ProtoBlock> start_fillers;\n    vector<Point3D> start_rem_cells;\n    for (int x=0; x<D; ++x) for(int y=0; y<D; ++y) for (int z=0; z<D; ++z) {\n        if (C_start[x][y][z] && !C_common[x][y][z]) start_rem_cells.push_back({x,y,z});\n    }\n\n    vector<Point3D> filler_cells;\n    while(!start_rem_cells.empty()) {\n        int best_score = -1; vector<int> best_indices;\n        for(size_t i=0; i<start_rem_cells.size(); ++i){\n            const auto& p = start_rem_cells[i];\n            int score = (!f_start_req_met[p.z*D+p.x]) + (!r_start_req_met[p.z*D+p.y]);\n            if(score > best_score) { best_score = score; best_indices.clear(); best_indices.push_back((int)i); }\n            else if(score == best_score) { best_indices.push_back((int)i); }\n        }\n        if(best_score <= 0) break;\n        \n        size_t chosen_rem_idx = best_indices[0];\n        if (best_score > 0 && best_indices.size() > 1 && !filler_cells.empty()){\n            Point3D last_p = filler_cells.back();\n            int min_dist = 1e9;\n            for(int idx : best_indices){\n                const auto& p = start_rem_cells[idx];\n                int dist = abs(p.x - last_p.x) + abs(p.y - last_p.y) + abs(p.z - last_p.z);\n                if(dist < min_dist){\n                    min_dist = dist;\n                    chosen_rem_idx = idx;\n                }\n            }\n        }\n\n        Point3D p = start_rem_cells[chosen_rem_idx];\n        filler_cells.push_back(p);\n        f_start_req_met[p.z*D+p.x] = true; r_start_req_met[p.z*D+p.y] = true;\n        swap(start_rem_cells[chosen_rem_idx], start_rem_cells.back()); start_rem_cells.pop_back();\n    }\n    \n    vector<vector<vector<bool>>> filler_grid(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    for(const auto& p : filler_cells) filler_grid[p.x][p.y][p.z] = true;\n    for(const auto& p_start : filler_cells) {\n        if (filler_grid[p_start.x][p_start.y][p_start.z]) {\n            Shape pts; vector<Point3D> q; q.push_back(p_start);\n            filler_grid[p_start.x][p_start.y][p_start.z] = false; size_t head=0;\n            while(head<q.size()){\n                Point3D curr = q[head++]; pts.push_back(curr);\n                int dx[]={-1,1,0,0,0,0}, dy[]={0,0,-1,1,0,0}, dz[]={0,0,0,0,-1,1};\n                for(int i=0; i<6; ++i) {\n                    Point3D next = {curr.x+dx[i], curr.y+dy[i], curr.z+dz[i]};\n                    if(is_valid_coord(next.x, next.y, next.z) && filler_grid[next.x][next.y][next.z]) {\n                        filler_grid[next.x][next.y][next.z] = false; q.push_back(next);\n                    }\n                }\n            }\n            start_fillers.push_back({pts, 0});\n        }\n    }\n    \n    vector<PlacedBlock> placed_common_blocks;\n    vector<vector<vector<bool>>> target_occupied(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    vector<bool> f_target_req_met(D*D, false), r_target_req_met(D*D, false);\n    vector<bool> common_block_placed(common_blocks.size(), false);\n    \n    vector<pair<int, const ProtoBlock*>> sorted_common_blocks;\n    for(size_t i = 0; i < common_blocks.size(); ++i) sorted_common_blocks.push_back({(int)i, &common_blocks[i]});\n    sort(sorted_common_blocks.begin(), sorted_common_blocks.end(), [](const auto&a, const auto&b){\n        return a.second->points.size() > b.second->points.size();\n    });\n\n    for (const auto& [idx, block_ptr] : sorted_common_blocks) {\n        if (time_limit_exceeded(time_limit_ms - 200)) break;\n        Shape s_rel = normalize_shape(block_ptr->points);\n        int best_block_score = -1; Shape best_block_placed_shape;\n        for (const auto& R : ROTS) {\n            Shape s_rot; for(const auto& p : s_rel) s_rot.push_back(rotate(p, R));\n            Point3D min_p_rot = s_rot[0];\n            for(size_t j=1; j<s_rot.size(); ++j) { min_p_rot.x=min(min_p_rot.x,s_rot[j].x); min_p_rot.y=min(min_p_rot.y,s_rot[j].y); min_p_rot.z=min(min_p_rot.z,s_rot[j].z); }\n            for (int x=0; x<D; ++x) for(int y=0; y<D; ++y) for(int z=0; z<D; ++z) {\n                Point3D trans = {x - min_p_rot.x, y - min_p_rot.y, z - min_p_rot.z};\n                bool possible = true; Shape placed_shape;\n                set<pair<int,int>> f_covered, r_covered;\n                for (const auto& p_rot : s_rot) {\n                    Point3D p_final = p_rot + trans;\n                    if (!is_valid_coord(p_final.x, p_final.y, p_final.z) || !C_target[p_final.x][p_final.y][p_final.z] || target_occupied[p_final.x][p_final.y][p_final.z]) {\n                        possible = false; break;\n                    }\n                    placed_shape.push_back(p_final);\n                    if (!f_target_req_met[p_final.z*D+p_final.x]) f_covered.insert({p_final.z, p_final.x});\n                    if (!r_target_req_met[p_final.z*D+p_final.y]) r_covered.insert({p_final.z, p_final.y});\n                }\n                if (possible) {\n                    int current_score = f_covered.size() + r_covered.size();\n                    if (current_score > best_block_score) {\n                        best_block_score = current_score; best_block_placed_shape = placed_shape;\n                    }\n                }\n            }\n        }\n        if(best_block_score >= 0){\n            placed_common_blocks.push_back({best_block_placed_shape, idx, 0});\n            common_block_placed[idx] = true;\n            for (const auto& p : best_block_placed_shape) {\n                target_occupied[p.x][p.y][p.z] = true;\n                f_target_req_met[p.z*D+p.x] = true; r_target_req_met[p.z*D+p.y] = true;\n            }\n        }\n    }\n    \n    vector<ProtoBlock> target_fillers;\n    vector<Point3D> target_rem_cells;\n    for (int x=0; x<D; ++x) for (int y=0; y<D; ++y) for (int z=0; z<D; ++z) {\n        if (C_target[x][y][z] && !target_occupied[x][y][z]) target_rem_cells.push_back({x,y,z});\n    }\n    vector<Point3D> t_filler_cells;\n    while(!target_rem_cells.empty()) {\n        int best_score = -1; vector<int> best_indices;\n        for(size_t i=0; i<target_rem_cells.size(); ++i){\n            const auto& p = target_rem_cells[i];\n            int score = (!f_target_req_met[p.z*D+p.x]) + (!r_target_req_met[p.z*D+p.y]);\n            if(score > best_score) { best_score = score; best_indices.clear(); best_indices.push_back((int)i); }\n            else if(score == best_score) { best_indices.push_back((int)i); }\n        }\n        if(best_score <= 0) break;\n        \n        size_t chosen_rem_idx = best_indices[0];\n        if (best_score > 0 && best_indices.size() > 1 && !t_filler_cells.empty()){\n            Point3D last_p = t_filler_cells.back();\n            int min_dist = 1e9;\n            for(int idx : best_indices){\n                const auto& p = target_rem_cells[idx];\n                int dist = abs(p.x - last_p.x) + abs(p.y - last_p.y) + abs(p.z - last_p.z);\n                if(dist < min_dist){\n                    min_dist = dist;\n                    chosen_rem_idx = idx;\n                }\n            }\n        }\n\n        Point3D p = target_rem_cells[chosen_rem_idx];\n        t_filler_cells.push_back(p);\n        f_target_req_met[p.z*D+p.x] = true; r_target_req_met[p.z*D+p.y] = true;\n        swap(target_rem_cells[chosen_rem_idx], target_rem_cells.back()); target_rem_cells.pop_back();\n    }\n    \n    vector<vector<vector<bool>>> t_filler_grid(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    for(const auto& p : t_filler_cells) t_filler_grid[p.x][p.y][p.z] = true;\n    for(const auto& p_start : t_filler_cells) {\n        if (t_filler_grid[p_start.x][p_start.y][p_start.z]) {\n            Shape pts; vector<Point3D> q; q.push_back(p_start);\n            t_filler_grid[p_start.x][p_start.y][p_start.z] = false; size_t head=0;\n            while(head<q.size()){\n                Point3D curr = q[head++]; pts.push_back(curr);\n                int dx[]={-1,1,0,0,0,0}, dy[]={0,0,-1,1,0,0}, dz[]={0,0,0,0,-1,1};\n                for(int i=0; i<6; ++i) {\n                    Point3D next = {curr.x+dx[i], curr.y+dy[i], curr.z+dz[i]};\n                    if(is_valid_coord(next.x, next.y, next.z) && t_filler_grid[next.x][next.y][next.z]) {\n                        t_filler_grid[next.x][next.y][next.z] = false; q.push_back(next);\n                    }\n                }\n            }\n            target_fillers.push_back({pts, 0});\n        }\n    }\n\n    int next_id = 1;\n    for (size_t i=0; i<common_blocks.size(); ++i) {\n        if (common_block_placed[i]) {\n            common_blocks[i].id = next_id++;\n        }\n    }\n    for (auto& pb : placed_common_blocks) {\n        pb.id = common_blocks[pb.original_idx].id;\n    }\n    \n    vector<ProtoBlock*> unplaced_common_ptrs;\n    for(size_t i=0; i<common_blocks.size(); ++i) if(!common_block_placed[i]) unplaced_common_ptrs.push_back(&common_blocks[i]);\n    vector<ProtoBlock*> start_fillers_ptrs; for(auto&b: start_fillers) start_fillers_ptrs.push_back(&b);\n    vector<ProtoBlock*> target_fillers_ptrs; for(auto&b: target_fillers) target_fillers_ptrs.push_back(&b);\n\n    vector<ProtoBlock*> start_specific_ptrs = unplaced_common_ptrs;\n    start_specific_ptrs.insert(start_specific_ptrs.end(), start_fillers_ptrs.begin(), start_fillers_ptrs.end());\n    \n    map<Shape, vector<ProtoBlock*>> start_by_canon, target_by_canon;\n    set<Shape> all_rem_canons;\n    for(auto ptr : start_specific_ptrs) {\n        if (ptr->points.empty()) continue;\n        Shape canon = get_canonical_shape(normalize_shape(ptr->points));\n        start_by_canon[canon].push_back(ptr); all_rem_canons.insert(canon);\n    }\n    for(auto ptr : target_fillers_ptrs) {\n        if (ptr->points.empty()) continue;\n        Shape canon = get_canonical_shape(normalize_shape(ptr->points));\n        target_by_canon[canon].push_back(ptr); all_rem_canons.insert(canon);\n    }\n\n    long long r_start_vol = 0, r_target_vol = 0; double inv_v_sum = 0;\n    for (const auto& b : placed_common_blocks) inv_v_sum += 1.0 / b.points.size();\n\n    for (const auto& canon : all_rem_canons) {\n        auto it1 = start_by_canon.find(canon); auto it2 = target_by_canon.find(canon);\n        vector<ProtoBlock*> v1 = (it1 == start_by_canon.end()) ? vector<ProtoBlock*>() : it1->second;\n        vector<ProtoBlock*> v2 = (it2 == target_by_canon.end()) ? vector<ProtoBlock*>() : it2->second;\n        size_t matches = min(v1.size(), v2.size());\n        for (size_t i = 0; i < matches; ++i) {\n            int id = next_id++; v1[i]->id = id; v2[i]->id = id;\n            inv_v_sum += 1.0 / v1[i]->points.size();\n        }\n        for (size_t i = matches; i < v1.size(); ++i) {\n            v1[i]->id = next_id++; r_target_vol += v1[i]->points.size();\n        }\n        for (size_t i = matches; i < v2.size(); ++i) {\n            v2[i]->id = next_id++; r_start_vol += v2[i]->points.size();\n        }\n    }\n    \n    Solution res;\n    res.score = round(1e9 * (r_start_vol + r_target_vol + inv_v_sum));\n    res.n = next_id - 1;\n    res.b1.assign(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    res.b2.assign(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    \n    for (const auto& block : common_blocks) for (const auto& p : block.points) res.b1[p.x][p.y][p.z] = block.id;\n    for (const auto& block : start_fillers) for (const auto& p : block.points) res.b1[p.x][p.y][p.z] = block.id;\n    for (const auto& block : placed_common_blocks) for (const auto& p : block.points) res.b2[p.x][p.y][p.z] = block.id;\n    for (const auto& block : target_fillers) for (const auto& p : block.points) res.b2[p.x][p.y][p.z] = block.id;\n    return res;\n}\n\nint main() {\n    T_START = chrono::high_resolution_clock::now();\n    ios_base::sync_with_stdio(false); cin.tie(NULL);\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    Solution res1 = solve(f1, r1, f2, r2, 2900);\n    Solution res2_swapped;\n    if (!time_limit_exceeded(5800)) {\n       res2_swapped = solve(f2, r2, f1, r1, 5800);\n    }\n\n    Solution best_res = res1;\n    if (res2_swapped.is_valid()) {\n        Solution res2 = {res2_swapped.score, res2_swapped.n, res2_swapped.b2, res2_swapped.b1};\n        if (!best_res.is_valid() || res2.score < best_res.score) {\n            best_res = res2;\n        }\n    }\n\n    if (!best_res.is_valid() || best_res.n == 0) {\n         cout << 0 << endl;\n         for(int i=0; i<D*D*D; ++i) cout << \"0\" << (i==D*D*D-1 ? \"\" : \" \");\n         cout << endl;\n         for(int i=0; i<D*D*D; ++i) cout << \"0\" << (i==D*D*D-1 ? \"\" : \" \");\n         cout << endl;\n         return 0;\n    }\n\n    cout << best_res.n << endl;\n    for(int x=0; x<D; ++x) for(int y=0; y<D; ++y) for(int z=0; z<D; ++z) cout << best_res.b1[x][y][z] << (x==D-1&&y==D-1&&z==D-1?\"\":\" \");\n    cout << endl;\n    for(int x=0; x<D; ++x) for(int y=0; y<D; ++y) for(int z=0; z<D; ++z) cout << best_res.b2[x][y][z] << (x==D-1&&y==D-1&&z==D-1?\"\":\" \");\n    cout << endl;\n\n    return 0;\n}","ahc020":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <queue>\n\nusing namespace std;\n\nconst long long INF = 1e18;\n\nstruct Point {\n    long long x, y;\n};\n\nstruct Edge {\n    int u, v;\n    long long w;\n    int id;\n};\n\nstruct GraphEdge {\n    int to;\n    long long weight;\n    int id;\n};\n\nlong long distSq(const Point& p1, const Point& p2) {\n    return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y);\n}\n\n// Global timer\nchrono::steady_clock::time_point start_time;\n\nbool is_time_up(double time_limit) {\n    auto now = chrono::steady_clock::now();\n    double elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n    return elapsed > time_limit;\n}\n\n// --- Precomputed data ---\nint N, M, K;\nvector<Point> stations;\nvector<Point> residents;\nvector<Edge> edges;\nvector<vector<GraphEdge>> adj;\nvector<vector<long long>> dist_G;\nvector<vector<int>> parent_G;\nvector<vector<pair<long long, int>>> dists_to_resident;\n\n// --- Randomness ---\nmt19937 rng;\n\nlong long integer_ceil_sqrt(long long n) {\n    if (n < 0) return 0;\n    if (n == 0) return 0;\n    long long root = sqrtl((long double)n);\n    while (root * root > n) {\n        root--;\n    }\n    while ((root + 1) * (root + 1) <= n) {\n        root++;\n    }\n    if (root * root < n) {\n        return root + 1;\n    }\n    return root;\n}\n\nlong long calculate_connection_cost(const vector<int>& V_list) {\n    if (V_list.size() <= 1) return 0;\n\n    long long cost = 0;\n    vector<long long> min_cost(N + 1, INF);\n    vector<bool> in_mst(N + 1, false);\n\n    min_cost[V_list[0]] = 0;\n    \n    for (size_t i = 0; i < V_list.size(); ++i) {\n        int u = -1;\n        for (int station_id : V_list) {\n            if (!in_mst[station_id] && (u == -1 || min_cost[station_id] < min_cost[u])) {\n                u = station_id;\n            }\n        }\n\n        if (u == -1) break;\n        in_mst[u] = true;\n        cost += min_cost[u];\n\n        for (int v : V_list) {\n            if (!in_mst[v]) {\n                min_cost[v] = min(min_cost[v], dist_G[u - 1][v - 1]);\n            }\n        }\n    }\n    return cost;\n}\n\nbool check_coverage(const vector<bool>& active) {\n    for (int k = 0; k < K; ++k) {\n        bool covered = false;\n        for (const auto& p : dists_to_resident[k]) {\n            if (active[p.second]) {\n                covered = true;\n                break;\n            }\n        }\n        if (!covered) return false;\n    }\n    return true;\n}\n\nlong long calculate_total_cost(const vector<bool>& active, vector<long long>& required_power_sq_out, vector<int>& max_power_resident_out) {\n    vector<int> V_list;\n    for (int i = 1; i <= N; ++i) {\n        if (active[i]) V_list.push_back(i);\n    }\n    if (V_list.empty() || !active[1]) {\n        return INF;\n    }\n\n    long long connection_cost = calculate_connection_cost(V_list);\n\n    long long power_cost = 0;\n    required_power_sq_out.assign(N + 1, 0);\n    max_power_resident_out.assign(N + 1, -1);\n\n    for (int k = 0; k < K; ++k) {\n        for (const auto& p : dists_to_resident[k]) {\n            int station_id = p.second;\n            if (active[station_id]) {\n                if (p.first > required_power_sq_out[station_id]) {\n                    required_power_sq_out[station_id] = p.first;\n                    max_power_resident_out[station_id] = k;\n                }\n                break;\n            }\n        }\n    }\n\n    for (int i = 1; i <= N; ++i) {\n        if (required_power_sq_out[i] > 0) {\n            long long p = integer_ceil_sqrt(required_power_sq_out[i]);\n            if (p > 5000) return INF;\n            power_cost += p * p;\n        }\n    }\n    \n    return connection_cost + power_cost;\n}\n\nlong long calculate_total_cost(const vector<bool>& active) {\n    vector<long long> dummy_p;\n    vector<int> dummy_k;\n    return calculate_total_cost(active, dummy_p, dummy_k);\n}\n\nvoid solve() {\n    start_time = chrono::steady_clock::now();\n    \n    cin >> N >> M >> K;\n    stations.resize(N);\n    for (int i = 0; i < N; ++i) cin >> stations[i].x >> stations[i].y;\n    edges.resize(M);\n    adj.resize(N + 1);\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\n        edges[i].id = i + 1;\n        adj[edges[i].u].push_back({edges[i].v, edges[i].w, edges[i].id});\n        adj[edges[i].v].push_back({edges[i].u, edges[i].w, edges[i].id});\n    }\n    residents.resize(K);\n    for (int i = 0; i < K; ++i) cin >> residents[i].x >> residents[i].y;\n\n    // Precomputation\n    dist_G.assign(N, vector<long long>(N, INF));\n    parent_G.assign(N, vector<int>(N, -1));\n\n    for (int i = 0; i < N; ++i) {\n        dist_G[i][i] = 0;\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n        pq.push({0, i + 1});\n\n        vector<long long> d(N + 1, INF);\n        vector<int> p(N + 1, -1);\n        d[i + 1] = 0;\n\n        while (!pq.empty()) {\n            auto [cost, u] = pq.top();\n            pq.pop();\n\n            if (cost > d[u]) continue;\n\n            for (const auto& edge : adj[u]) {\n                int v = edge.to;\n                if (d[u] + edge.weight < d[v]) {\n                    d[v] = d[u] + edge.weight;\n                    p[v] = u;\n                    pq.push({d[v], v});\n                }\n            }\n        }\n        for (int j = 0; j < N; ++j) {\n            dist_G[i][j] = d[j + 1];\n            parent_G[i][j] = p[j + 1];\n        }\n    }\n    \n    dists_to_resident.resize(K);\n    for (int k = 0; k < K; ++k) {\n        for (int i = 0; i < N; ++i) {\n            dists_to_resident[k].push_back({distSq(residents[k], stations[i]), i + 1});\n        }\n        sort(dists_to_resident[k].begin(), dists_to_resident[k].end());\n    }\n\n    // --- Robust Initial Solution with Fixup Loop ---\n    vector<bool> current_V(N + 1, false);\n    current_V[1] = true;\n    for (int iter = 0; iter < N + 5; ++iter) {\n        while (true) {\n            int uncovered_k = -1;\n            for (int k = 0; k < K; ++k) {\n                bool covered = false;\n                for (const auto& p : dists_to_resident[k]) if (current_V[p.second]) { covered = true; break; }\n                if (!covered) { uncovered_k = k; break; }\n            }\n            if (uncovered_k == -1) break;\n            for (const auto& p : dists_to_resident[uncovered_k]) if (p.first <= 5000LL * 5000LL) { if (!current_V[p.second]) { current_V[p.second] = true; break; } }\n        }\n        vector<long long> req_p_sq; vector<int> max_p_res;\n        calculate_total_cost(current_V, req_p_sq, max_p_res);\n        int problematic_station = -1;\n        for (int i = 1; i <= N; ++i) if (req_p_sq[i] > 5000LL * 5000LL) { problematic_station = i; break; }\n        if (problematic_station == -1) break;\n        int problematic_resident = max_p_res[problematic_station];\n        for (const auto& p : dists_to_resident[problematic_resident]) if (p.first <= 5000LL * 5000LL) { if (!current_V[p.second]) { current_V[p.second] = true; break; } }\n    }\n    \n    // --- Greedy Refinement ---\n    bool changed = true;\n    while(changed) {\n        changed = false;\n        vector<int> active_nodes; for(int i=2; i<=N; ++i) if(current_V[i]) active_nodes.push_back(i);\n        shuffle(active_nodes.begin(), active_nodes.end(), rng);\n        long long base_cost = calculate_total_cost(current_V);\n        for(int v : active_nodes) {\n            current_V[v] = false;\n            if (check_coverage(current_V)) {\n                long long new_cost = calculate_total_cost(current_V);\n                if (new_cost != INF && new_cost < base_cost) { base_cost = new_cost; changed = true; } else { current_V[v] = true; }\n            } else { current_V[v] = true; }\n        }\n    }\n\n    vector<bool> best_V = current_V;\n    vector<long long> current_req_p_sq; vector<int> current_max_power_resident;\n    long long current_cost = calculate_total_cost(current_V, current_req_p_sq, current_max_power_resident);\n    long long best_cost = current_cost;\n\n    // --- Simulated Annealing ---\n    double time_limit = 1980;\n    double T_start = best_cost > 0 ? best_cost / 10.0 : 1000.0;\n    double T_end = 1.0;\n    \n    uniform_int_distribution<> dist_N(1, N);\n    uniform_real_distribution<> dist_real(0.0, 1.0);\n\n    while (!is_time_up(time_limit)) {\n        double elapsed = chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count();\n        double progress = elapsed / time_limit;\n        if (progress > 1.0) progress = 1.0;\n        double T = T_start * pow(T_end / T_start, progress);\n\n        vector<bool> next_V = current_V;\n        double move_type = dist_real(rng);\n\n        if (move_type < 0.4) { // ADD\n            bool guided_add = dist_real(rng) < 0.5; bool success = false;\n            if (guided_add) {\n                int s_max = -1; long long max_p_sq = -1;\n                for (int i=1; i<=N; ++i) if (current_V[i] && current_req_p_sq[i] > max_p_sq) { max_p_sq = current_req_p_sq[i]; s_max = i; }\n                if (s_max != -1) {\n                    int k_far = current_max_power_resident[s_max];\n                    if (k_far != -1) for(const auto& p : dists_to_resident[k_far]) if(!current_V[p.second]) { next_V[p.second] = true; success = true; break; }\n                }\n            }\n            if(!success) { int u; int attempts=0; do { u = dist_N(rng); attempts++; } while(next_V[u] && attempts < 2*N); if(!next_V[u]) next_V[u] = true; else continue; }\n        } else if (move_type < 0.8) { // REMOVE\n            bool guided_remove = dist_real(rng) < 0.5; bool success = false;\n            if (guided_remove) {\n                vector<pair<long long, int>> candidates;\n                for(int i = 2; i <= N; ++i) if (current_V[i]) candidates.push_back({current_req_p_sq[i], i});\n                if (!candidates.empty()) {\n                    sort(candidates.begin(), candidates.end());\n                    int num_to_pick = max(1, (int)candidates.size() / 5);\n                    uniform_int_distribution<> dist_cand(0, num_to_pick - 1);\n                    int v_to_remove = candidates[dist_cand(rng)].second;\n                    next_V[v_to_remove] = false; success = true;\n                }\n            }\n            if (!success) { vector<int> active_nodes; for(int i=2; i<=N; ++i) if(next_V[i]) active_nodes.push_back(i); if (active_nodes.empty()) continue; uniform_int_distribution<> dist_rem(0, active_nodes.size() - 1); next_V[active_nodes[dist_rem(rng)]] = false; }\n            if (!check_coverage(next_V)) continue;\n        } else { // SWAP\n            vector<int> active_nodes; for(int i=2; i<=N; ++i) if(next_V[i]) active_nodes.push_back(i); if (active_nodes.empty()) continue;\n            uniform_int_distribution<> dist_rem(0, active_nodes.size() - 1); int v = active_nodes[dist_rem(rng)];\n            int u; int attempts_u = 0; do { u = dist_N(rng); attempts_u++; } while(next_V[u] && attempts_u < 2*N); if(next_V[u]) continue;\n            next_V[v] = false; next_V[u] = true;\n            if (!check_coverage(next_V)) continue;\n        }\n        \n        vector<long long> next_req_p_sq; vector<int> next_max_power_resident;\n        long long next_cost = calculate_total_cost(next_V, next_req_p_sq, next_max_power_resident);\n        if(next_cost == INF) continue;\n\n        long long delta = next_cost - current_cost;\n        if (delta < 0 || (T > 0 && dist_real(rng) < exp(-(double)delta / T))) {\n            current_V = next_V;\n            current_cost = next_cost;\n            current_req_p_sq = next_req_p_sq;\n            current_max_power_resident = next_max_power_resident;\n            if (current_cost < best_cost) {\n                best_cost = current_cost;\n                best_V = current_V;\n            }\n        }\n    }\n\n    // --- Output ---\n    vector<long long> P(N + 1, 0);\n    vector<long long> required_power_sq(N + 1, 0); vector<int> dummy_k;\n    calculate_total_cost(best_V, required_power_sq, dummy_k);\n    for (int i = 1; i <= N; ++i) {\n        if (best_V[i] && required_power_sq[i] > 0) P[i] = integer_ceil_sqrt(required_power_sq[i]);\n    }\n\n    vector<bool> B(M + 1, false);\n    vector<int> V_list; for (int i = 1; i <= N; ++i) if (best_V[i]) V_list.push_back(i);\n    if (V_list.size() > 1) {\n        vector<long long> min_cost(N + 1, INF); vector<int> edge_from(N + 1, -1); vector<bool> in_mst(N + 1, false);\n        min_cost[V_list[0]] = 0;\n        for (size_t i = 0; i < V_list.size(); ++i) {\n            int u = -1;\n            for (int sid : V_list) if (!in_mst[sid] && (u == -1 || min_cost[sid] < min_cost[u])) u = sid;\n            if (u == -1) break;\n            in_mst[u] = true;\n            if (edge_from[u] != -1) {\n                int v = edge_from[u], start_node_idx = v-1, curr_node_idx = u-1;\n                while(curr_node_idx != start_node_idx) {\n                    int prev_node = parent_G[start_node_idx][curr_node_idx];\n                    if (prev_node == -1) break;\n                    for(const auto& edge : adj[curr_node_idx+1]) if (edge.to == prev_node) { B[edge.id] = true; break; }\n                    curr_node_idx = prev_node-1;\n                }\n            }\n            for (int v_idx : V_list) if (!in_mst[v_idx] && dist_G[u-1][v_idx-1] < min_cost[v_idx]) { min_cost[v_idx] = dist_G[u-1][v_idx-1]; edge_from[v_idx] = u; }\n        }\n    }\n\n    for (int i = 1; i <= N; ++i) cout << P[i] << (i == N ? \"\" : \" \"); cout << endl;\n    for (int i = 1; i <= M; ++i) cout << B[i] << (i == M ? \"\" : \" \"); cout << endl;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    unsigned int seed = chrono::high_resolution_clock::now().time_since_epoch().count();\n    rng.seed(seed);\n    solve();\n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <tuple>\n\nconst int N = 30;\nconst int TOTAL_BALLS = N * (N + 1) / 2;\nconst int MAX_OPS = 10000;\n\nstd::vector<std::vector<int>> b;\nstd::vector<std::pair<int, int>> pos;\nstd::vector<std::tuple<int, int, int, int>> ops;\n\nvoid do_swap(int r1, int c1, int r2, int c2) {\n    if (ops.size() >= MAX_OPS) return;\n\n    int val1 = b[r1][c1];\n    int val2 = b[r2][c2];\n\n    std::swap(b[r1][c1], b[r2][c2]);\n    std::swap(pos[val1], pos[val2]);\n    \n    ops.emplace_back(r1, c1, r2, c2);\n}\n\n// Moves small values up as far as they can go.\nvoid small_up_climb_pass() {\n    for (int v = 0; v < TOTAL_BALLS; ++v) {\n        while (ops.size() < MAX_OPS) {\n            auto [r, c] = pos[v];\n            if (r == 0) break;\n\n            bool has_p_left = (c > 0);\n            bool has_p_right = (c < r);\n\n            int p_left_val = -1, p_right_val = -1;\n            if (has_p_left) p_left_val = b[r - 1][c - 1];\n            if (has_p_right) p_right_val = b[r - 1][c];\n            \n            bool swap_left = has_p_left && v < p_left_val;\n            bool swap_right = has_p_right && v < p_right_val;\n\n            if (!swap_left && !swap_right) break;\n\n            if (swap_left && swap_right) {\n                if (p_left_val > p_right_val) {\n                    do_swap(r, c, r - 1, c - 1);\n                } else {\n                    do_swap(r, c, r - 1, c);\n                }\n            } else if (swap_left) {\n                do_swap(r, c, r - 1, c - 1);\n            } else { // swap_right\n                do_swap(r, c, r - 1, c);\n            }\n        }\n    }\n}\n\n// Moves large values down as far as they can go.\nvoid large_down_sink_pass() {\n    for (int v = TOTAL_BALLS - 1; v >= 0; --v) {\n        while (ops.size() < MAX_OPS) {\n            auto [r, c] = pos[v];\n            if (r == N - 1) break;\n            \n            int child_left_val = b[r + 1][c];\n            int child_right_val = b[r + 1][c + 1];\n\n            bool swap_left = v > child_left_val;\n            bool swap_right = v > child_right_val;\n\n            if (!swap_left && !swap_right) break;\n\n            if (swap_left && swap_right) {\n                if (child_left_val < child_right_val) {\n                    do_swap(r, c, r + 1, c);\n                } else {\n                    do_swap(r, c, r + 1, c + 1);\n                }\n            } else if (swap_left) {\n                do_swap(r, c, r + 1, c);\n            } else { // swap_right\n                do_swap(r, c, r + 1, c + 1);\n            }\n        }\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    b.resize(N);\n    pos.resize(TOTAL_BALLS);\n    for (int i = 0; i < N; ++i) {\n        b[i].resize(i + 1);\n        for (int j = 0; j <= i; ++j) {\n            std::cin >> b[i][j];\n            pos[b[i][j]] = {i, j};\n        }\n    }\n\n    int iter = 0;\n    while(ops.size() < MAX_OPS) {\n        size_t ops_before_iter = ops.size();\n        \n        if (iter % 2 == 0) {\n            small_up_climb_pass();\n            if (ops.size() >= MAX_OPS) break;\n            large_down_sink_pass();\n        } else {\n            large_down_sink_pass();\n            if (ops.size() >= MAX_OPS) break;\n            small_up_climb_pass();\n        }\n\n        if (ops.size() == ops_before_iter) break;\n        iter++;\n    }\n\n    std::cout << ops.size() << \"\\n\";\n    for (const auto& op : ops) {\n        std::cout << std::get<0>(op) << \" \" << std::get<1>(op) << \" \" << std::get<2>(op) << \" \" << std::get<3>(op) << \"\\n\";\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n#include <map>\n#include <tuple>\n#include <set>\n#include <cassert>\n\nusing namespace std;\n\n// Constants and global state\nconst int D_CONST = 9;\nconst int ENTRANCE_R = 0;\nconst int ENTRANCE_C = (D_CONST - 1) / 2;\nconst int DR[] = {-1, 1, 0, 0};\nconst int DC[] = {0, 0, -1, 1};\n\nint D_input, N;\nint C; // Total number of containers\nvector<vector<int>> grid; // Grid state: -3=Empty, -2=Entrance, -1=Obstacle, >=0=Container ID\nmap<int, pair<int, int>> container_locs; // Maps container ID to its location\n\n// Candidate struct for dynamic placement decision\nstruct Candidate {\n    int r, c;\n    int dist;\n    int dynamic_block_count;\n};\n\n// Utility to check if coordinates are within the grid\nbool is_valid(int r, int c) {\n    return r >= 0 && r < D_CONST && c >= 0 && c < D_CONST;\n}\n\n// Phase 1: Just read inputs and set up the initial grid\nvoid precompute() {\n    C = D_CONST * D_CONST - 1 - N;\n    grid.assign(D_CONST, vector<int>(D_CONST, -3));\n    grid[ENTRANCE_R][ENTRANCE_C] = -2;\n    \n    for (int i = 0; i < N; ++i) {\n        int r, c;\n        cin >> r >> c;\n        grid[r][c] = -1;\n    }\n}\n\n// Phase 2: Place containers using a proportional, dynamic strategy\nvoid solve_placement() {\n    for (int d = 0; d < C; ++d) {\n        int t_d;\n        cin >> t_d;\n\n        // 1. Find all currently reachable empty squares and their distances.\n        vector<pair<int, int>> reachable_empty_squares;\n        vector<vector<int>> dist_grid(D_CONST, vector<int>(D_CONST, -1));\n        queue<pair<int, int>> q;\n        \n        q.push({ENTRANCE_R, ENTRANCE_C});\n        dist_grid[ENTRANCE_R][ENTRANCE_C] = 0;\n\n        queue<pair<int, int>> q_bfs = q;\n        while(!q_bfs.empty()){\n            auto [r, c] = q_bfs.front();\n            q_bfs.pop();\n            if(grid[r][c] == -3) {\n                reachable_empty_squares.push_back({r, c});\n            }\n            for(int i = 0; i < 4; ++i){\n                int nr = r + DR[i];\n                int nc = c + DC[i];\n                if(is_valid(nr, nc) && dist_grid[nr][nc] == -1 && (grid[nr][nc] == -3 || grid[nr][nc] == -2)) {\n                    dist_grid[nr][nc] = dist_grid[r][c] + 1;\n                    q_bfs.push({nr, nc});\n                }\n            }\n        }\n        \n        assert(!reachable_empty_squares.empty());\n\n        // 2. Evaluate each reachable empty square as a candidate.\n        vector<Candidate> candidates;\n        for (const auto& square : reachable_empty_squares) {\n            int r = square.first, c = square.second;\n            grid[r][c] = -1; // Temporarily block\n            \n            int reachable_count_after = 0;\n            vector<vector<char>> visited_after(D_CONST, vector<char>(D_CONST, 0));\n            queue<pair<int, int>> q_check;\n            if(grid[ENTRANCE_R][ENTRANCE_C] != -1) {\n                q_check.push({ENTRANCE_R, ENTRANCE_C});\n                visited_after[ENTRANCE_R][ENTRANCE_C] = 1;\n            }\n            while(!q_check.empty()){\n                auto [curr_r, curr_c] = q_check.front(); q_check.pop();\n                for(int i = 0; i < 4; ++i){\n                    int nr = curr_r + DR[i]; int nc = curr_c + DC[i];\n                    if(is_valid(nr, nc) && !visited_after[nr][nc] && (grid[nr][nc] == -3 || grid[nr][nc] == -2)){\n                        visited_after[nr][nc] = 1; q_check.push({nr, nc});\n                    }\n                }\n            }\n            for(const auto& other_square : reachable_empty_squares) {\n                if (square != other_square && visited_after[other_square.first][other_square.second]) {\n                    reachable_count_after++;\n                }\n            }\n            int dynamic_block_count = (int)(reachable_empty_squares.size() - 1) - reachable_count_after;\n            \n            grid[r][c] = -3; // Restore\n            candidates.push_back({r, c, dist_grid[r][c], dynamic_block_count});\n        }\n        \n        // 3. Select the best candidate using the proportional placement strategy.\n        vector<Candidate> safe_candidates, bottleneck_candidates;\n        for(const auto& cand : candidates) {\n            if(cand.dynamic_block_count == 0) safe_candidates.push_back(cand);\n            else bottleneck_candidates.push_back(cand);\n        }\n        \n        Candidate best_cand;\n        if (!safe_candidates.empty()) {\n            // Sort safe spots from best (close, top-left) to worst (far, bottom-right)\n            sort(safe_candidates.begin(), safe_candidates.end(), [](const Candidate& a, const Candidate& b){\n                if (a.dist != b.dist) return a.dist < b.dist;\n                if (a.r != b.r) return a.r < b.r;\n                return a.c < b.c;\n            });\n            \n            // Map container's priority (t_d) to a spot's quality rank\n            double percentile = (C > 1) ? (double)t_d / (C - 1) : 0.0;\n            int target_idx = round(percentile * (safe_candidates.size() - 1));\n            \n            best_cand = safe_candidates[target_idx];\n\n        } else { // Fallback: use bottleneck with least damage.\n            assert(!bottleneck_candidates.empty());\n            sort(bottleneck_candidates.begin(), bottleneck_candidates.end(), [](const Candidate& a, const Candidate& b){\n                if (a.dynamic_block_count != b.dynamic_block_count) return a.dynamic_block_count < b.dynamic_block_count;\n                if (a.dist != b.dist) return a.dist > b.dist;\n                if (a.r != b.r) return a.r > b.r;\n                return a.c > b.c;\n            });\n            best_cand = bottleneck_candidates[0];\n        }\n\n        grid[best_cand.r][best_cand.c] = t_d;\n        container_locs[t_d] = {best_cand.r, best_cand.c};\n        cout << best_cand.r << \" \" << best_cand.c << endl;\n    }\n}\n\n// Phase 3: Retrieve all containers in a greedy fashion\nvoid solve_retrieval() {\n    for (int k = 0; k < C; ++k) {\n        set<int> accessible_containers;\n        queue<pair<int, int>> q;\n        vector<vector<char>> visited_empty(D_CONST, vector<char>(D_CONST, 0));\n\n        q.push({ENTRANCE_R, ENTRANCE_C});\n        visited_empty[ENTRANCE_R][ENTRANCE_C] = 1;\n\n        while(!q.empty()){\n            auto [r, c] = q.front(); q.pop();\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + DR[i]; int nc = c + DC[i];\n                if (!is_valid(nr, nc)) continue;\n                if (grid[nr][nc] >= 0) {\n                    accessible_containers.insert(grid[nr][nc]);\n                } else if ((grid[nr][nc] == -3 || grid[nr][nc] == -2) && !visited_empty[nr][nc]) {\n                    visited_empty[nr][nc] = 1; q.push({nr, nc});\n                }\n            }\n        }\n        \n        if (accessible_containers.empty()) break;\n        int min_t = *accessible_containers.begin();\n        auto [qr, qc] = container_locs[min_t];\n        cout << qr << \" \" << qc << endl;\n        grid[qr][qc] = -3;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    cin >> D_input >> N;\n    precompute();\n    solve_placement();\n    solve_retrieval();\n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <set>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <queue>\n#include <tuple>\n\n// Constants\nconstexpr int N = 50;\nconstexpr int M = 100;\n\n// Randomness\nstruct Xoroshiro128 {\n    uint64_t s[2];\n\n    Xoroshiro128() {\n        std::random_device rd;\n        s[0] = ((uint64_t)rd() << 32) | rd();\n        s[1] = ((uint64_t)rd() << 32) | rd();\n    }\n\n    static inline uint64_t rotl(const uint64_t x, int k) {\n        return (x << k) | (x >> (64 - k));\n    }\n\n    uint64_t next() {\n        const uint64_t s0 = s[0];\n        uint64_t s1 = s[1];\n        const uint64_t result = s0 + s1;\n\n        s1 ^= s0;\n        s[0] = rotl(s0, 24) ^ s1 ^ (s1 << 16);\n        s[1] = rotl(s1, 37);\n\n        return result;\n    }\n\n    double next_double() {\n        return (double)(next() >> 11) * (1.0 / (1LL << 53));\n    }\n};\n\nXoroshiro128 rng;\n\n// Timer\nclass Timer {\npublic:\n    Timer() : start_time(std::chrono::high_resolution_clock::now()) {}\n\n    double get_elapsed_sec() {\n        auto now = std::chrono::high_resolution_clock::now();\n        return std::chrono::duration_cast<std::chrono::duration<double>>(now - start_time).count();\n    }\nprivate:\n    std::chrono::time_point<std::chrono::high_resolution_clock> start_time;\n};\n\n// Data structures\nstruct Point {\n    int r, c;\n};\n\nstruct Vec2d {\n    double x, y;\n};\n\n// Globals for problem data\nstd::vector<std::vector<bool>> adj;\nstd::vector<std::vector<int>> initial_grid;\n\nvoid read_input() {\n    int n_dummy, m_dummy;\n    std::cin >> n_dummy >> m_dummy;\n    initial_grid.assign(N, std::vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            std::cin >> initial_grid[i][j];\n        }\n    }\n}\n\nvoid build_adj() {\n    adj.assign(M + 1, std::vector<bool>(M + 1, false));\n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            if (r == 0 || r == N - 1 || c == 0 || c == N - 1) {\n                adj[initial_grid[r][c]][0] = adj[0][initial_grid[r][c]] = true;\n            }\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + dr[i];\n                int nc = c + dc[i];\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                    int c1 = initial_grid[r][c];\n                    int c2 = initial_grid[nr][nc];\n                    if (c1 != c2) {\n                        adj[c1][c2] = adj[c2][c1] = true;\n                    }\n                }\n            }\n        }\n    }\n}\n\nstruct Solution {\n    std::vector<std::vector<int>> grid;\n    int score;\n\n    Solution() : grid(N, std::vector<int>(N, 0)), score(0) {}\n\n    void calculate_score() {\n        int empty_count = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (grid[i][j] == 0) {\n                    empty_count++;\n                }\n            }\n        }\n        score = empty_count + 1;\n    }\n\n    void print() {\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                std::cout << grid[i][j] << (j == N - 1 ? \"\" : \" \");\n            }\n            std::cout << std::endl;\n        }\n    }\n};\n\nclass Solver {\npublic:\n    Solver(const Timer& timer) : timer(timer) {}\n\n    Solution solve() {\n        Solution best_solution;\n        best_solution.score = -1;\n\n        while(timer.get_elapsed_sec() < 1.95) {\n            Solution current_solution = generate_solution();\n            if (current_solution.score > best_solution.score) {\n                best_solution = current_solution;\n            }\n        }\n        return best_solution;\n    }\n\nprivate:\n    const Timer& timer;\n    std::vector<std::vector<int>> grid;\n    std::vector<Point> seed_pos;\n\n    Solution generate_solution() {\n        std::vector<Vec2d> positions = force_directed_layout();\n        grid.assign(N, std::vector<int>(N, 0));\n        seed_pos.assign(M + 1, {-1, -1});\n        place_seeds(positions);\n        connect_regions();\n        \n        Solution sol;\n        sol.grid = grid;\n        sol.calculate_score();\n        return sol;\n    }\n\n    std::vector<Vec2d> force_directed_layout() {\n        std::vector<Vec2d> pos(M + 1);\n        for (int i = 1; i <= M; ++i) {\n            pos[i] = {rng.next_double() * N, rng.next_double() * N};\n        }\n\n        double temp = N / 4.0;\n        const int iterations = 150;\n        const double k_attr = 0.1, k_rep = 150.0;\n        const double border_rep = 200.0;\n\n        for (int iter = 0; iter < iterations; ++iter) {\n            if (timer.get_elapsed_sec() > 1.95) break;\n\n            std::vector<Vec2d> forces(M + 1, {0.0, 0.0});\n            for (int i = 1; i <= M; ++i) {\n                for (int j = i + 1; j <= M; ++j) {\n                    Vec2d diff = {pos[j].x - pos[i].x, pos[j].y - pos[i].y};\n                    double dist_sq = diff.x * diff.x + diff.y * diff.y + 1e-6;\n                    double dist = std::sqrt(dist_sq);\n                    \n                    if (adj[i][j]) {\n                        double f = k_attr * (dist - N/10.0);\n                        forces[i].x += f * diff.x / dist;\n                        forces[i].y += f * diff.y / dist;\n                        forces[j].x -= f * diff.x / dist;\n                        forces[j].y -= f * diff.y / dist;\n                    } else {\n                        double f = k_rep / dist_sq;\n                        forces[i].x -= f * diff.x / dist;\n                        forces[i].y -= f * diff.y / dist;\n                        forces[j].x += f * diff.x / dist;\n                        forces[j].y += f * diff.y / dist;\n                    }\n                }\n            }\n\n            for (int i = 1; i <= M; ++i) {\n                 if (!adj[i][0]) {\n                    forces[i].x += border_rep / (pos[i].x * pos[i].x + 1e-6);\n                    forces[i].y += border_rep / (pos[i].y * pos[i].y + 1e-6);\n                    forces[i].x -= border_rep / ((N-1 - pos[i].x) * (N-1 - pos[i].x) + 1e-6);\n                    forces[i].y -= border_rep / ((N-1 - pos[i].y) * (N-1 - pos[i].y) + 1e-6);\n                }\n            }\n\n            for (int i = 1; i <= M; ++i) {\n                double force_mag = std::sqrt(forces[i].x * forces[i].x + forces[i].y * forces[i].y) + 1e-6;\n                pos[i].x += temp * forces[i].x / force_mag;\n                pos[i].y += temp * forces[i].y / force_mag;\n                pos[i].x = std::max(1.0, std::min((double)N - 2, pos[i].x));\n                pos[i].y = std::max(1.0, std::min((double)N - 2, pos[i].y));\n            }\n            temp *= 0.98;\n        }\n        return pos;\n    }\n\n    void place_seeds(const std::vector<Vec2d>& pos) {\n        std::vector<int> p(M);\n        std::iota(p.begin(), p.end(), 1);\n        auto mt = std::mt19937(rng.next());\n        std::shuffle(p.begin(), p.end(), mt);\n\n        for (int color : p) {\n            int target_r = std::round(pos[color].y);\n            int target_c = std::round(pos[color].x);\n\n            int best_r = -1, best_c = -1;\n            for (int d = 0; d < N; ++d) {\n                for(int i = -d; i <= d; ++i) {\n                    int j = d - std::abs(i);\n                    int r_offsets[] = {i, i};\n                    int c_offsets[] = {j, -j};\n                    for (int k = 0; k < 2; ++k) {\n                        int r = target_r + r_offsets[k];\n                        int c = target_c + c_offsets[k];\n                        if (r < 0 || r >= N || c < 0 || c >= N) continue;\n                        if (is_valid_placement(color, r, c)) {\n                            best_r = r; best_c = c; goto found_pos;\n                        }\n                    }\n                }\n            }\n            found_pos:;\n            if (best_r != -1) {\n                grid[best_r][best_c] = color;\n                seed_pos[color] = {best_r, best_c};\n            }\n        }\n    }\n\n    bool is_valid_placement(int color, int r, int c) {\n        if (grid[r][c] != 0) return false;\n        if (!adj[color][0] && (r == 0 || r == N - 1 || c == 0 || c == N - 1)) return false;\n        \n        int dr[] = {-1, 1, 0, 0};\n        int dc[] = {0, 0, -1, 1};\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i], nc = c + dc[i];\n            if (nr >= 0 && nr < N && nc >= 0 && nc < N && grid[nr][nc] != 0) {\n                if (!adj[color][grid[nr][nc]]) return false;\n            }\n        }\n        return true;\n    }\n\n    void connect_regions() {\n        std::vector<std::pair<int, int>> reqs;\n        for (int i = 1; i <= M; ++i) for (int j = i + 1; j <= M; ++j) if (adj[i][j]) reqs.push_back({i, j});\n        auto mt = std::mt19937(rng.next());\n        std::shuffle(reqs.begin(), reqs.end(), mt);\n        \n        std::vector<std::vector<bool>> satisfied_adj(M + 1, std::vector<bool>(M + 1, false));\n\n        for (const auto& p : reqs) {\n            if (timer.get_elapsed_sec() > 1.95) break;\n            \n            bool is_adj = false;\n            int c1 = p.first, c2 = p.second;\n            if(seed_pos[c1].r == -1 || seed_pos[c2].r == -1) continue;\n            for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) {\n                if(grid[r][c]==c1) {\n                    int dr[]={-1,1,0,0}, dc[]={0,0,-1,1};\n                    for(int i=0;i<4;++i) {\n                        int nr=r+dr[i], nc=c+dc[i];\n                        if(nr>=0 && nr<N && nc>=0 && nc<N && grid[nr][nc]==c2) { is_adj=true; goto end_check; }\n                    }\n                }\n            }\n            end_check:;\n\n            if (!is_adj) connect_pair(p.first, p.second);\n        }\n        \n        for (int i = 1; i <= M; ++i) {\n            if (timer.get_elapsed_sec() > 1.95) break;\n            if (adj[i][0]) {\n                 bool is_adj_to_0 = false;\n                 for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) {\n                    if (grid[r][c] == i && (r==0 || r==N-1 || c==0 || c==N-1)) {\n                        is_adj_to_0 = true; break;\n                    }\n                 }\n                 if(!is_adj_to_0) connect_to_border(i);\n            }\n        }\n    }\n\n    void connect_pair(int c1, int c2) {\n        using State = std::tuple<int, int, int>;\n        std::priority_queue<State, std::vector<State>, std::greater<State>> pq;\n        std::vector<std::vector<int>> dist(N, std::vector<int>(N, 1e9));\n        std::vector<std::vector<Point>> parent(N, std::vector<Point>(N, {-1, -1}));\n\n        for (int r = 0; r < N; ++r) for (int c = 0; c < N; ++c) {\n            if (grid[r][c] == c1) { pq.emplace(0, r, c); dist[r][c] = 0; }\n        }\n\n        const int PENALTY = N*N;\n        int dr[] = {-1, 1, 0, 0}; int dc[] = {0, 0, -1, 1};\n        Point end_pos = {-1, -1};\n\n        while (!pq.empty()) {\n            auto [d, r, c] = pq.top(); pq.pop();\n            if (d > dist[r][c]) continue;\n\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + dr[i], nc = c + dc[i];\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N && grid[nr][nc] == c2) {\n                    end_pos = {r, c}; goto path_found;\n                }\n            }\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + dr[i], nc = c + dc[i];\n                if (nr < 0 || nr >= N || nc < 0 || nc >= N || (grid[nr][nc] != 0 && grid[nr][nc] != c1)) continue;\n                int cost = 1, penalty = 0;\n                for (int j = 0; j < 4; ++j) {\n                    int nnr = nr + dr[j], nnc = nc + dc[j];\n                    if (nnr < 0 || nnr >= N || nnc < 0 || nnc >= N) continue;\n                    int neighbor_color = grid[nnr][nnc];\n                    if (neighbor_color != 0 && neighbor_color != c1 && !adj[c1][neighbor_color]) penalty += PENALTY;\n                }\n                if (dist[nr][nc] > d + cost + penalty) {\n                    dist[nr][nc] = d + cost + penalty; parent[nr][nc] = {r, c}; pq.emplace(dist[nr][nc], nr, nc);\n                }\n            }\n        }\n    path_found:\n        if (end_pos.r != -1) {\n            Point curr = end_pos;\n            while (grid[curr.r][curr.c] == 0) {\n                grid[curr.r][curr.c] = c1; curr = parent[curr.r][curr.c];\n            }\n        }\n    }\n\n    void connect_to_border(int c1) {\n        if (seed_pos[c1].r == -1) return;\n        using State = std::tuple<int, int, int>;\n        std::priority_queue<State, std::vector<State>, std::greater<State>> pq;\n        std::vector<std::vector<int>> dist(N, std::vector<int>(N, 1e9));\n        std::vector<std::vector<Point>> parent(N, std::vector<Point>(N, {-1, -1}));\n\n        for (int r = 0; r < N; ++r) for (int c = 0; c < N; ++c) {\n            if (grid[r][c] == c1) { pq.emplace(0, r, c); dist[r][c] = 0; }\n        }\n        \n        const int PENALTY = N*N;\n        int dr[] = {-1, 1, 0, 0}; int dc[] = {0, 0, -1, 1};\n        Point end_pos = {-1, -1};\n\n        while (!pq.empty()) {\n            auto [d, r, c] = pq.top(); pq.pop();\n            if (d > dist[r][c]) continue;\n            if (r == 0 || r == N - 1 || c == 0 || c == N - 1) { end_pos = {r, c}; break; }\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + dr[i], nc = c + dc[i];\n                if (nr < 0 || nr >= N || nc < 0 || nc >= N || (grid[nr][nc] != 0 && grid[nr][nc] != c1)) continue;\n                int cost = 1, penalty = 0;\n                for (int j = 0; j < 4; ++j) {\n                    int nnr = nr + dr[j], nnc = nc + dc[j];\n                    if (nnr < 0 || nnr >= N || nnc < 0 || nnc >= N) continue;\n                    int neighbor_color = grid[nnr][nnc];\n                    if (neighbor_color != 0 && neighbor_color != c1 && !adj[c1][neighbor_color]) penalty += PENALTY;\n                }\n                if (!adj[c1][0] && (nr==0 || nr==N-1 || nc==0 || nc==N-1)) penalty += PENALTY;\n                if (dist[nr][nc] > d + cost + penalty) {\n                    dist[nr][nc] = d + cost + penalty; parent[nr][nc] = {r, c}; pq.emplace(dist[nr][nc], nr, nc);\n                }\n            }\n        }\n        if (end_pos.r != -1) {\n            Point curr = end_pos;\n            while (grid[curr.r][curr.c] == 0) {\n                grid[curr.r][curr.c] = c1; curr = parent[curr.r][curr.c];\n            }\n        }\n    }\n};\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    Timer timer;\n\n    read_input();\n    build_adj();\n\n    Solver solver(timer);\n    Solution best_solution = solver.solve();\n    \n    best_solution.print();\n\n    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n\n// --- Utilities ---\nstruct Timer {\n    std::chrono::high_resolution_clock::time_point start_time;\n    Timer() {\n        start_time = std::chrono::high_resolution_clock::now();\n    }\n    long long get_elapsed_ms() const {\n        auto now = std::chrono::high_resolution_clock::now();\n        return std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time).count();\n    }\n};\n\nstd::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// --- Problem specific globals ---\nint N, D, Q;\nconst int NUM_PARTICLES = 2500;\nstd::vector<std::vector<long long>> particles;\ndouble W_CAP;\n\n// --- Query interaction ---\nchar query(const std::vector<int>& L, const std::vector<int>& R) {\n    if (L.empty() || R.empty()) {\n        return '=';\n    }\n    std::cout << L.size() << \" \" << R.size();\n    for (int x : L) std::cout << \" \" << x;\n    for (int x : R) std::cout << \" \" << x;\n    std::cout << std::endl;\n    char res;\n    std::cin >> res;\n    return res;\n}\n\n// --- Particle management ---\nvoid generate_particles() {\n    particles.clear();\n    std::uniform_real_distribution<double> unif(0.0, 1.0);\n    const double lambda = 1e-5;\n\n    particles.reserve(NUM_PARTICLES);\n    for (int i = 0; i < NUM_PARTICLES; ++i) {\n        std::vector<long long> weights(N);\n        for (int j = 0; j < N; ++j) {\n            double w_prime;\n            do {\n                double u = std::max(1e-9, unif(rng)); // Avoid log(0)\n                w_prime = -log(u) / lambda;\n            } while (w_prime > W_CAP);\n            weights[j] = std::max(1LL, (long long)round(w_prime));\n        }\n        particles.push_back(weights);\n    }\n}\n\nvoid filter_particles(const std::vector<int>& L, const std::vector<int>& R, char result) {\n    std::vector<std::vector<long long>> next_particles;\n    next_particles.reserve(particles.size());\n    for (const auto& p : particles) {\n        long long sum_L = 0, sum_R = 0;\n        for (int i : L) sum_L += p[i];\n        for (int i : R) sum_R += p[i];\n        \n        bool consistent = false;\n        if (result == '<' && sum_L < sum_R) consistent = true;\n        else if (result == '>' && sum_L > sum_R) consistent = true;\n        else if (result == '=' && sum_L == sum_R) consistent = true;\n        \n        if (consistent) {\n            next_particles.push_back(p);\n        }\n    }\n    if (!next_particles.empty()) {\n        particles = std::move(next_particles);\n    }\n}\n\nstd::vector<double> get_estimated_weights() {\n    std::vector<double> avg_weights(N, 0.0);\n    if (particles.empty()) {\n        for(int i=0; i<N; ++i) avg_weights[i] = 1.0;\n        return avg_weights;\n    }\n    int p_count = particles.size();\n    for (int i = 0; i < N; ++i) {\n        double total = 0;\n        for (const auto& p : particles) {\n            total += p[i];\n        }\n        avg_weights[i] = total / p_count;\n    }\n    return avg_weights;\n}\n\n// --- Main logic ---\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    Timer timer;\n\n    std::cin >> N >> D >> Q;\n    W_CAP = 1e5 * N / D;\n\n    generate_particles();\n\n    int queries_made = 0;\n\n    // Phase 1: Sorting queries\n    int num_sort_queries = Q * 2 / 5;\n    \n    std::vector<std::pair<int, int>> pairs;\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            pairs.push_back({i, j});\n        }\n    }\n    std::shuffle(pairs.begin(), pairs.end(), rng);\n\n    for (int i = 0; i < num_sort_queries && i < (int)pairs.size() && queries_made < Q; ++i) {\n        auto [u, v] = pairs[i];\n        char res = query({u}, {v});\n        filter_particles({u}, {v}, res);\n        queries_made++;\n    }\n\n    // Phase 2: Hybrid magnitude queries\n    int magnitude_queries_count = 0;\n    int one_vs_many_cycle = 0;\n    while (queries_made < Q) {\n        auto estimated_weights = get_estimated_weights();\n        std::vector<int> p(N);\n        std::iota(p.begin(), p.end(), 0);\n        std::sort(p.begin(), p.end(), [&](int i, int j) {\n            return estimated_weights[i] < estimated_weights[j];\n        });\n\n        if (magnitude_queries_count % 4 == 0 && N > 1) {\n            // Query type: Balanced groups of all items\n            std::vector<int> L, R;\n            double sum_L = 0, sum_R = 0;\n            for (int i = N - 1; i >= 0; --i) {\n                int item_idx = p[i];\n                if (sum_L <= sum_R) {\n                    L.push_back(item_idx);\n                    sum_L += estimated_weights[item_idx];\n                } else {\n                    R.push_back(item_idx);\n                    sum_R += estimated_weights[item_idx];\n                }\n            }\n            char res = query(L, R);\n            filter_particles(L, R, res);\n        } else {\n            // Query type: Cycling \"One vs. Many\"\n            int k_idx = (N - 1) - (one_vs_many_cycle % (std::max(1, N - 1)));\n            int item_k = p[k_idx];\n\n            std::vector<double> prefix_sum_w(k_idx, 0.0);\n            if (k_idx > 0) {\n                prefix_sum_w[0] = estimated_weights[p[0]];\n                for (int i = 1; i < k_idx; ++i) {\n                    prefix_sum_w[i] = prefix_sum_w[i-1] + estimated_weights[p[i]];\n                }\n            }\n            \n            auto it = std::upper_bound(prefix_sum_w.begin(), prefix_sum_w.end(), estimated_weights[item_k]);\n            int j_idx = std::distance(prefix_sum_w.begin(), it);\n            if (j_idx > 0 && j_idx < k_idx) {\n                if (std::abs(prefix_sum_w[j_idx] - estimated_weights[item_k]) > std::abs(prefix_sum_w[j_idx-1] - estimated_weights[item_k])) {\n                    j_idx--;\n                }\n            }\n            j_idx = std::max(0, std::min(k_idx - 1, j_idx));\n            \n            std::vector<int> L = {item_k};\n            std::vector<int> R;\n            for (int i = 0; i <= j_idx; ++i) {\n                R.push_back(p[i]);\n            }\n            \n            if (!R.empty()) {\n                char res = query(L, R);\n                filter_particles(L, R, res);\n            } else if (N > 1) {\n                char res = query({item_k}, {p[k_idx == 0 ? 1 : 0]});\n                filter_particles({item_k}, {p[k_idx == 0 ? 1 : 0]}, res);\n            }\n            one_vs_many_cycle++;\n        }\n        queries_made++;\n        magnitude_queries_count++;\n    }\n\n    // Partitioning phase\n    auto final_weights = get_estimated_weights();\n    std::vector<long long> scaled_weights(N);\n    double scale_factor = 10000.0;\n    for(int i=0; i<N; ++i) {\n        scaled_weights[i] = std::max(1LL, (long long)round(final_weights[i] * scale_factor));\n    }\n\n    // Initial solution using LPT greedy algorithm\n    std::vector<int> p_part(N);\n    std::iota(p_part.begin(), p_part.end(), 0);\n    std::sort(p_part.begin(), p_part.end(), [&](int i, int j) {\n        return scaled_weights[i] > scaled_weights[j];\n    });\n\n    std::vector<int> assignment(N);\n    using int128 = __int128_t;\n    std::vector<int128> set_sums(D, 0);\n    \n    for (int item_idx : p_part) {\n        if (D > 0) {\n            auto min_it = std::min_element(set_sums.begin(), set_sums.end());\n            int best_set = std::distance(set_sums.begin(), min_it);\n            assignment[item_idx] = best_set;\n            set_sums[best_set] += scaled_weights[item_idx];\n        }\n    }\n    \n    // Simulated Annealing\n    std::vector<int128> current_set_sums = set_sums;\n    std::vector<int> current_assignment = assignment;\n    \n    int128 current_score = 0;\n    for(auto s : current_set_sums) current_score += s*s;\n\n    auto best_assignment = current_assignment;\n    int128 best_score = current_score;\n\n    long double start_temp = 1.0;\n    if (N > 0 && D > 1) {\n        long double total_worsening_delta = 0;\n        int worsening_moves = 0;\n        for (int i = 0; i < 100; ++i) {\n            int item_idx = rng() % N;\n            int d1 = current_assignment[item_idx];\n            int d2;\n            do { d2 = rng() % D; } while (d1 == d2);\n            \n            int128 w = scaled_weights[item_idx];\n            int128 s1 = current_set_sums[d1];\n            int128 s2 = current_set_sums[d2];\n            int128 delta = (s1-w)*(s1-w) + (s2+w)*(s2+w) - s1*s1 - s2*s2;\n            if (delta > 0) {\n                total_worsening_delta += (long double)delta;\n                worsening_moves++;\n            }\n        }\n        if (worsening_moves > 0) {\n            long double avg_worsening_delta = total_worsening_delta / worsening_moves;\n            long double initial_accept_prob = 0.5;\n            start_temp = -avg_worsening_delta / log(initial_accept_prob);\n        }\n    }\n\n    long long time_limit = 1950;\n    \n    while(D > 1) {\n        long long elapsed_ms = timer.get_elapsed_ms();\n        if (elapsed_ms >= time_limit) break;\n\n        long double elapsed_ratio = (long double)elapsed_ms / time_limit;\n        long double temp = start_temp * (1.0 - elapsed_ratio);\n        if (temp < 1e-9) temp = 1e-9;\n        \n        if (rng() % 4 != 0) { // Move (75% total)\n            int item_idx = -1;\n            int d1 = -1;\n\n            if (rng() % 2 == 0) { // Targeted Move (37.5%)\n                auto max_it = std::max_element(current_set_sums.begin(), current_set_sums.end());\n                d1 = std::distance(current_set_sums.begin(), max_it);\n                \n                std::vector<int> candidates;\n                candidates.reserve(N);\n                for(int i=0; i<N; ++i) { if(current_assignment[i] == d1) candidates.push_back(i); }\n                if(candidates.empty()) continue;\n                item_idx = candidates[rng() % candidates.size()];\n            } else { // Simple Move (37.5%)\n                item_idx = rng() % N;\n                d1 = current_assignment[item_idx];\n            }\n            \n            int d2;\n            do { d2 = rng() % D; } while (d1 == d2);\n\n            int128 w = scaled_weights[item_idx];\n            int128 s1 = current_set_sums[d1];\n            int128 s2 = current_set_sums[d2];\n            int128 new_score = current_score - s1*s1 - s2*s2 + (s1 - w)*(s1 - w) + (s2 + w)*(s2 + w);\n            \n            if (new_score < current_score || std::uniform_real_distribution<long double>(0,1)(rng) < expl((long double)(current_score - new_score) / temp)) {\n                current_assignment[item_idx] = d2;\n                current_set_sums[d1] -= w;\n                current_set_sums[d2] += w;\n                current_score = new_score;\n                if (current_score < best_score) {\n                    best_score = current_score;\n                    best_assignment = current_assignment;\n                }\n            }\n        } else { // Swap (25%)\n            if (N < 2) continue;\n            int item1_idx = rng() % N;\n            int item2_idx;\n            do { item2_idx = rng() % N; } while (item1_idx == item2_idx);\n\n            int d1 = current_assignment[item1_idx];\n            int d2 = current_assignment[item2_idx];\n            if (d1 == d2) continue;\n\n            int128 w1 = scaled_weights[item1_idx];\n            int128 w2 = scaled_weights[item2_idx];\n            int128 s1 = current_set_sums[d1];\n            int128 s2 = current_set_sums[d2];\n            int128 new_score = current_score - s1*s1 - s2*s2 + (s1 - w1 + w2)*(s1 - w1 + w2) + (s2 - w2 + w1)*(s2 - w2 + w1);\n\n            if (new_score < current_score || std::uniform_real_distribution<long double>(0,1)(rng) < expl((long double)(current_score - new_score) / temp)) {\n                std::swap(current_assignment[item1_idx], current_assignment[item2_idx]);\n                current_set_sums[d1] = s1 - w1 + w2;\n                current_set_sums[d2] = s2 - w2 + w1;\n                current_score = new_score;\n                if (current_score < best_score) {\n                    best_score = current_score;\n                    best_assignment = current_assignment;\n                }\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        std::cout << best_assignment[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    std::cout << std::endl;\n\n    return 0;\n}","ahc026":"#include <iostream>\n#include <vector>\n#include <array>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n\nusing namespace std;\n\n// Constants for the problem\nconst int N = 200;\nconst int M = 10;\nconst double TIME_LIMIT_MS = 1950.0;\n\n// Beam width parameters, pushed higher due to optimization.\nconst int INITIAL_BEAM_WIDTH = 400;\nconst int FINAL_BEAM_WIDTH = 30;\n\nstruct State {\n    array<vector<int>, M> stacks;\n    array<pair<int, int>, N + 1> box_pos; // {stack_idx, height_from_bottom}\n    long long cost = 0;\n    double eval_score = 0.0;\n    \n    // History tracing to avoid copying large vectors\n    int parent_idx = -1;\n    char num_ops = 0;\n    pair<int, int> op1{0,0}, op2{0,0};\n\n    State() {\n        for(int i=0; i<=N; ++i) box_pos[i] = {-1, -1};\n    }\n    \n    void evaluate(int v_start) {\n        double h1 = 0;\n        for (int v = v_start; v <= N; ++v) {\n            if (box_pos[v].first != -1) {\n                int stack_idx = box_pos[v].first;\n                int height = box_pos[v].second;\n                int boxes_on_top = stacks[stack_idx].size() - height - 1;\n                if (boxes_on_top > 0) {\n                    h1 += boxes_on_top + 1;\n                }\n            }\n        }\n        eval_score = cost + h1;\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    auto start_time = chrono::high_resolution_clock::now();\n\n    int n_in, m_in;\n    cin >> n_in >> m_in;\n\n    State initial_state;\n    for (int i = 0; i < M; ++i) {\n        initial_state.stacks[i].resize(N / M);\n        for (int j = 0; j < N / M; ++j) {\n            int b;\n            cin >> b;\n            initial_state.stacks[i][j] = b;\n            initial_state.box_pos[b] = {i, j};\n        }\n    }\n\n    vector<vector<State>> beam_history;\n    beam_history.reserve(N + 1);\n    beam_history.push_back({initial_state});\n\n    for (int v_to_carry = 1; v_to_carry <= N; ++v_to_carry) {\n        double elapsed_ms = chrono::duration<double, milli>(chrono::high_resolution_clock::now() - start_time).count();\n        \n        int current_beam_width;\n        if (elapsed_ms >= TIME_LIMIT_MS) {\n            current_beam_width = 1;\n        } else {\n            double time_ratio = elapsed_ms / TIME_LIMIT_MS;\n            current_beam_width = static_cast<int>(INITIAL_BEAM_WIDTH - (INITIAL_BEAM_WIDTH - FINAL_BEAM_WIDTH) * time_ratio);\n            current_beam_width = max(1, current_beam_width);\n        }\n        \n        vector<State> candidates;\n        candidates.reserve(beam_history.back().size() * 3);\n        \n        const auto& prev_beam = beam_history.back();\n        for (size_t p_idx = 0; p_idx < prev_beam.size(); ++p_idx) {\n            const auto& s = prev_beam[p_idx];\n            int stack_idx = s.box_pos[v_to_carry].first;\n            int height = s.box_pos[v_to_carry].second;\n            \n            if (s.stacks[stack_idx].size() - 1 == height) { // is on top\n                State next_s = s;\n                int box_v = next_s.stacks[stack_idx].back();\n                next_s.stacks[stack_idx].pop_back();\n                next_s.box_pos[box_v] = {-1, -1};\n                next_s.parent_idx = p_idx;\n                next_s.num_ops = 1;\n                next_s.op1 = {box_v, 0};\n                next_s.evaluate(v_to_carry + 1);\n                candidates.push_back(move(next_s));\n            } else { // not on top, must move\n                int move_v = s.stacks[stack_idx][height + 1];\n                vector<int> dest_options;\n                {\n                    int empty_idx = -1;\n                    for (int i = 0; i < M; ++i) if (s.stacks[i].empty()) { empty_idx = i; break; }\n                    if (empty_idx != -1) dest_options.push_back(empty_idx);\n                    int shortest_idx = -1, min_size = N + 2;\n                    for (int i = 0; i < M; ++i) {\n                        if (i == stack_idx || s.stacks[i].empty()) continue;\n                        if ((int)s.stacks[i].size() < min_size) { min_size = s.stacks[i].size(); shortest_idx = i; }\n                    }\n                    if (shortest_idx != -1) dest_options.push_back(shortest_idx);\n                    int largest_top_idx = -1, max_top = -1;\n                    for (int i = 0; i < M; ++i) {\n                        if (i == stack_idx || s.stacks[i].empty()) continue;\n                        if (s.stacks[i].back() > max_top) { max_top = s.stacks[i].back(); largest_top_idx = i; }\n                    }\n                    if (largest_top_idx != -1) dest_options.push_back(largest_top_idx);\n                    if (dest_options.empty()) for (int i = 0; i < M; ++i) if (i != stack_idx) { dest_options.push_back(i); break; }\n                    sort(dest_options.begin(), dest_options.end());\n                    dest_options.erase(unique(dest_options.begin(), dest_options.end()), dest_options.end());\n                }\n\n                for (int dest_idx : dest_options) {\n                    State next_s = s;\n                    auto& src_stack = next_s.stacks[stack_idx];\n                    vector<int> moved_boxes(src_stack.begin() + height + 1, src_stack.end());\n                    src_stack.resize(height + 1);\n                    next_s.cost += moved_boxes.size() + 1;\n                    auto& dest_stack = next_s.stacks[dest_idx];\n                    size_t old_dest_size = dest_stack.size();\n                    dest_stack.insert(dest_stack.end(), moved_boxes.begin(), moved_boxes.end());\n                    for (size_t i = 0; i < moved_boxes.size(); ++i) next_s.box_pos[moved_boxes[i]] = {dest_idx, (int)(old_dest_size + i)};\n                    int box_v = next_s.stacks[stack_idx].back();\n                    next_s.stacks[stack_idx].pop_back();\n                    next_s.box_pos[box_v] = {-1, -1};\n                    next_s.parent_idx = p_idx;\n                    next_s.num_ops = 2;\n                    next_s.op1 = {move_v, dest_idx + 1};\n                    next_s.op2 = {box_v, 0};\n                    next_s.evaluate(v_to_carry + 1);\n                    candidates.push_back(move(next_s));\n                }\n            }\n        }\n\n        sort(candidates.begin(), candidates.end(), [](const auto& a, const auto& b) {\n            return a.eval_score < b.eval_score;\n        });\n\n        vector<State> next_beam;\n        next_beam.reserve(current_beam_width);\n        for (size_t i = 0; i < min((size_t)candidates.size(), (size_t)current_beam_width); ++i) {\n            next_beam.push_back(move(candidates[i]));\n        }\n        if (next_beam.empty() && !candidates.empty()) {\n            next_beam.push_back(move(candidates[0]));\n        }\n        beam_history.push_back(move(next_beam));\n    }\n    \n    const auto& final_beam = beam_history.back();\n    int best_final_idx = 0;\n    for(size_t i = 1; i < final_beam.size(); ++i) {\n        if(final_beam[i].cost < final_beam[best_final_idx].cost) {\n            best_final_idx = i;\n        }\n    }\n\n    vector<pair<int, int>> final_ops;\n    int current_beam_level = beam_history.size() - 1;\n    while(current_beam_level > 0) {\n        const auto& s = beam_history[current_beam_level][best_final_idx];\n        if (s.num_ops >= 2) final_ops.push_back(s.op2);\n        if (s.num_ops >= 1) final_ops.push_back(s.op1);\n        best_final_idx = s.parent_idx;\n        current_beam_level--;\n    }\n    reverse(final_ops.begin(), final_ops.end());\n\n    for (const auto& op : final_ops) {\n        cout << op.first << \" \" << op.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc027":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <functional>\n#include <list>\n#include <set>\n#include <chrono>\n#include <map>\n#include <unordered_map>\n#include <memory>\n\n// Timer\nauto start_time = std::chrono::high_resolution_clock::now();\ndouble get_time() {\n    return std::chrono::duration_cast<std::chrono::duration<double>>(std::chrono::high_resolution_clock::now() - start_time).count();\n}\n\nstruct Pos {\n    short r, c;\n    bool operator<(const Pos& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n    bool operator==(const Pos& other) const {\n        return r == other.r && c == other.c;\n    }\n};\n\nint N;\nstd::vector<std::string> h_walls, v_walls;\nstd::vector<std::vector<int>> d;\nstd::vector<std::vector<std::vector<Pos>>> adj;\n\n// Randomness\nstd::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\nvoid build_adj() {\n    adj.assign(N, std::vector<std::vector<Pos>>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (i > 0 && h_walls[i - 1][j] == '0') adj[i][j].push_back({(short)(i - 1), (short)j});\n            if (i < N - 1 && h_walls[i][j] == '0') adj[i][j].push_back({(short)(i + 1), (short)j});\n            if (j > 0 && v_walls[i][j - 1] == '0') adj[i][j].push_back({(short)i, (short)(j - 1)});\n            if (j < N - 1 && v_walls[i][j] == '0') adj[i][j].push_back({(short)i, (short)(j + 1)});\n        }\n    }\n}\n\n// Initial path via randomized DFS\nstd::list<Pos> initial_tour;\nstd::vector<std::vector<bool>> visited;\nvoid generate_initial_path_dfs(Pos p) {\n    visited[p.r][p.c] = true;\n    initial_tour.push_back(p);\n    \n    std::vector<Pos> neighbors = adj[p.r][p.c];\n    std::shuffle(neighbors.begin(), neighbors.end(), rng);\n    \n    for (const auto& next_p : neighbors) {\n        if (!visited[next_p.r][next_p.c]) {\n            generate_initial_path_dfs(next_p);\n            initial_tour.push_back(p);\n        }\n    }\n}\n\nstd::string pos_to_moves(const std::list<Pos>& pos_path) {\n    std::string moves;\n    if (pos_path.size() <= 1) return \"\";\n    moves.reserve(pos_path.size() - 1);\n    auto it = pos_path.begin();\n    Pos current = *it;\n    ++it;\n    while (it != pos_path.end()) {\n        Pos next = *it;\n        if (next.r == current.r - 1) moves.push_back('U');\n        else if (next.r == current.r + 1) moves.push_back('D');\n        else if (next.c == current.c - 1) moves.push_back('L');\n        else moves.push_back('R');\n        current = next;\n        ++it;\n    }\n    return moves;\n}\n\n// State for SA\nstruct State {\n    using list_iterator = std::list<Pos>::iterator;\n    \n    struct IteratorHasher {\n        std::size_t operator()(const list_iterator& it) const {\n            return std::hash<const Pos*>()(&*it);\n        }\n    };\n\n    std::list<Pos> tour;\n    std::vector<std::vector<long long>> k;\n    double score_sum_d_div_k;\n\n    // For fast SA moves\n    std::vector<std::vector<std::vector<list_iterator>>> occurrences;\n    std::vector<std::vector<std::unordered_map<list_iterator, int, IteratorHasher>>> occurrences_indices;\n\n    std::vector<list_iterator> detour_centers;\n    std::unordered_map<list_iterator, int, IteratorHasher> detour_centers_indices;\n    \n    State() {\n        k.resize(N, std::vector<long long>(N, 0));\n        occurrences.resize(N, std::vector<std::vector<list_iterator>>(N));\n        occurrences_indices.resize(N, std::vector<std::unordered_map<list_iterator, int, IteratorHasher>>(N));\n    }\n\n    void add_occurrence(const Pos& p, list_iterator it) {\n        occurrences_indices[p.r][p.c][it] = occurrences[p.r][p.c].size();\n        occurrences[p.r][p.c].push_back(it);\n    }\n    void remove_occurrence(const Pos& p, list_iterator it) {\n        int idx_to_remove = occurrences_indices[p.r][p.c].at(it);\n        auto it_last = occurrences[p.r][p.c].back();\n        \n        occurrences[p.r][p.c][idx_to_remove] = it_last;\n        occurrences_indices[p.r][p.c][it_last] = idx_to_remove;\n        \n        occurrences[p.r][p.c].pop_back();\n        occurrences_indices[p.r][p.c].erase(it);\n    }\n\n    void add_detour_center(list_iterator it) {\n        detour_centers_indices[it] = detour_centers.size();\n        detour_centers.push_back(it);\n    }\n    void remove_detour_center(list_iterator it) {\n        auto map_it = detour_centers_indices.find(it);\n        if (map_it == detour_centers_indices.end()) return;\n        int idx_to_remove = map_it->second;\n\n        auto it_last = detour_centers.back();\n        \n        if (it != it_last) {\n            detour_centers[idx_to_remove] = it_last;\n            detour_centers_indices[it_last] = idx_to_remove;\n        }\n\n        detour_centers.pop_back();\n        detour_centers_indices.erase(map_it);\n    }\n    \n    void rebuild_detour_centers() {\n        detour_centers.clear();\n        detour_centers_indices.clear();\n        if (tour.size() < 3) return;\n        auto it1 = tour.begin();\n        auto it2 = std::next(it1);\n        auto it3 = std::next(it2);\n        while(it3 != tour.end()){\n            if (*it1 == *it3) {\n                add_detour_center(it2);\n            }\n            ++it1; ++it2; ++it3;\n        }\n    }\n\n    void init(const std::list<Pos>& initial_tour) {\n        tour = initial_tour;\n        score_sum_d_div_k = 0;\n        for (int i=0; i<N; ++i) for(int j=0; j<N; ++j) k[i][j] = 0;\n\n        for (auto it = tour.begin(); it != tour.end(); ++it) {\n            k[it->r][it->c]++;\n            add_occurrence(*it, it);\n        }\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (k[i][j] > 0) {\n                    score_sum_d_div_k += (double)d[i][j] / k[i][j];\n                }\n            }\n        }\n    }\n    \n    double get_energy() const {\n        if (tour.empty()) return 1e18;\n        return (double)(tour.size() - 1) * score_sum_d_div_k;\n    }\n};\n\ndouble calculate_g(long long count, int dirt) {\n    if (count == 0) return 1e18;\n    return (double)dirt / (count * (count + 1.0));\n}\nstruct PQ_Elem {\n    double score;\n    Pos p;\n    bool operator<(const PQ_Elem& other) const {\n        if (std::abs(score - other.score) > 1e-9) return score < other.score;\n        return p < other.p;\n    }\n};\n\nvoid solve() {\n    build_adj();\n\n    visited.assign(N, std::vector<bool>(N, false));\n    generate_initial_path_dfs({0,0});\n    \n    State state;\n    state.init(initial_tour);\n\n    const int MAX_L = 100000;\n    const double time_limit = 1.98;\n    const double greedy_time_limit = time_limit * 0.5;\n    {\n        std::vector<std::vector<double>> g(N, std::vector<double>(N));\n        std::vector<std::vector<Pos>> best_neighbor(N, std::vector<Pos>(N));\n        std::set<PQ_Elem> pq;\n\n        for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) g[i][j] = calculate_g(state.k[i][j], d[i][j]);\n\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                Pos p = {(short)i, (short)j};\n                double max_g = -1.0; Pos bn = {-1, -1};\n                for (const auto& neighbor : adj[i][j]) {\n                    if (g[neighbor.r][neighbor.c] > max_g) max_g = g[neighbor.r][neighbor.c], bn = neighbor;\n                }\n                best_neighbor[i][j] = bn;\n                if (bn.r != -1) pq.insert({g[i][j] + max_g, p});\n            }\n        }\n        \n        while (get_time() < greedy_time_limit && state.tour.size() + 2 <= MAX_L && !pq.empty()) {\n            PQ_Elem top = *pq.rbegin();\n            Pos u = top.p; Pos v = best_neighbor[u.r][u.c];\n            if (v.r == -1) { pq.erase(std::prev(pq.end())); continue; }\n            \n            int occ_idx = std::uniform_int_distribution<int>(0, state.occurrences[u.r][u.c].size() - 1)(rng);\n            auto it_u_old = state.occurrences[u.r][u.c][occ_idx];\n            auto it_after_u = std::next(it_u_old);\n            auto it_u_new = state.tour.insert(it_after_u, u);\n            auto it_v = state.tour.insert(it_u_new, v);\n            \n            state.score_sum_d_div_k -= ((double)d[u.r][u.c] / state.k[u.r][u.c]) + ((double)d[v.r][v.c] / state.k[v.r][v.c]);\n            state.k[u.r][u.c]++; state.k[v.r][v.c]++;\n            state.score_sum_d_div_k += ((double)d[u.r][u.c] / state.k[u.r][u.c]) + ((double)d[v.r][v.c] / state.k[v.r][v.c]);\n            state.add_occurrence(u, it_u_new); state.add_occurrence(v, it_v);\n\n            std::set<Pos> to_update_pq;\n            to_update_pq.insert(u); to_update_pq.insert(v);\n            for(const auto& n: adj[u.r][u.c]) to_update_pq.insert(n);\n            for(const auto& n: adj[v.r][v.c]) to_update_pq.insert(n);\n            \n            for (const auto& p : to_update_pq) {\n                Pos bn_old = best_neighbor[p.r][p.c];\n                if (bn_old.r != -1) pq.erase({g[p.r][p.c] + g[bn_old.r][bn_old.c], p});\n            }\n            g[u.r][u.c] = calculate_g(state.k[u.r][u.c], d[u.r][u.c]); g[v.r][v.c] = calculate_g(state.k[v.r][v.c], d[v.r][v.c]);\n            for (const auto& p : to_update_pq) {\n                double max_g = -1.0; Pos bn_new = {-1, -1};\n                if (!adj[p.r][p.c].empty()){\n                    for (const auto& n : adj[p.r][p.c]) {\n                        if (g[n.r][n.c] > max_g) max_g = g[n.r][n.c], bn_new = n;\n                    }\n                    best_neighbor[p.r][p.c] = bn_new;\n                    if (bn_new.r != -1) pq.insert({g[p.r][p.c] + max_g, p});\n                }\n            }\n        }\n    }\n\n    state.rebuild_detour_centers();\n\n    double start_temp = 1000, end_temp = 1;\n    double current_energy = state.get_energy();\n    std::uniform_real_distribution<> u_dist(0.0, 1.0);\n    int sa_iter = 0;\n    double temp = start_temp;\n\n    while (true) {\n        sa_iter++;\n        if ((sa_iter & 127) == 0) { // Batch processing\n            double time_now = get_time();\n            if (time_now > time_limit) break;\n            temp = start_temp + (end_temp - start_temp) * time_now / time_limit;\n        }\n        if ((sa_iter & 65535) == 0) {\n            state.rebuild_detour_centers();\n        }\n\n        int move_type = std::uniform_int_distribution<int>(0, 2)(rng);\n\n        if (move_type == 0 && state.tour.size() + 2 <= MAX_L) { // ADD\n            Pos p = {(short)std::uniform_int_distribution<int>(0,N-1)(rng), (short)std::uniform_int_distribution<int>(0,N-1)(rng)};\n            if (state.occurrences[p.r][p.c].empty() || adj[p.r][p.c].empty()) continue;\n            Pos v = adj[p.r][p.c][std::uniform_int_distribution<int>(0, adj[p.r][p.c].size() - 1)(rng)];\n            int occ_idx = std::uniform_int_distribution<int>(0, state.occurrences[p.r][p.c].size() - 1)(rng);\n            auto it_p_old = state.occurrences[p.r][p.c][occ_idx];\n\n            double new_sum_d_div_k = state.score_sum_d_div_k - (double)d[p.r][p.c]/state.k[p.r][p.c] + (double)d[p.r][p.c]/(state.k[p.r][p.c]+1) - (double)d[v.r][v.c]/state.k[v.r][v.c] + (double)d[v.r][v.c]/(state.k[v.r][v.c]+1);\n            double new_energy = (double)(state.tour.size() + 1) * new_sum_d_div_k;\n            double delta_e = new_energy - current_energy;\n\n            if (delta_e < 0 || u_dist(rng) < std::exp(-delta_e / temp)) {\n                auto it_after_p = std::next(it_p_old);\n                auto it_p_new = state.tour.insert(it_after_p, p);\n                auto it_v = state.tour.insert(it_p_new, v);\n                state.score_sum_d_div_k = new_sum_d_div_k;\n                state.k[p.r][p.c]++; state.k[v.r][v.c]++;\n                state.add_occurrence(p, it_p_new); state.add_occurrence(v, it_v); state.add_detour_center(it_v);\n                current_energy = new_energy;\n            }\n        } else if (move_type >= 1 && !state.detour_centers.empty()) { // REMOVE or CHANGE\n            int dc_idx = std::uniform_int_distribution<int>(0, state.detour_centers.size() - 1)(rng);\n            auto it_u = state.detour_centers[dc_idx];\n            if (it_u == state.tour.begin()) { state.remove_detour_center(it_u); continue; }\n            auto it_p1 = std::prev(it_u); auto it_p2 = std::next(it_u);\n\n            if (it_p2 == state.tour.end() || !(*it_p1 == *it_p2)) { state.remove_detour_center(it_u); continue; }\n            Pos u = *it_u, p = *it_p1;\n\n            if (move_type == 1 && state.tour.size() - 2 > (size_t)2 * (N*N-1)) { // REMOVE\n                double new_sum_d_div_k = state.score_sum_d_div_k - (double)d[p.r][p.c]/state.k[p.r][p.c] + (double)d[p.r][p.c]/(state.k[p.r][p.c]-1) - (double)d[u.r][u.c]/state.k[u.r][u.c] + (double)d[u.r][u.c]/(state.k[u.r][u.c]-1);\n                double new_energy = (double)(state.tour.size() - 3) * new_sum_d_div_k;\n                double delta_e = new_energy - current_energy;\n\n                if (delta_e < 0 || u_dist(rng) < std::exp(-delta_e / temp)) {\n                    state.remove_detour_center(it_u); state.remove_detour_center(it_p2);\n                    state.remove_occurrence(u, it_u); state.remove_occurrence(p, it_p2);\n                    state.tour.erase(it_u); state.tour.erase(it_p2);\n                    state.score_sum_d_div_k = new_sum_d_div_k;\n                    state.k[p.r][p.c]--; state.k[u.r][u.c]--;\n                    current_energy = new_energy;\n                }\n            } else if (move_type == 2) { // CHANGE\n                if (adj[p.r][p.c].size() <= 1) continue;\n                Pos v = adj[p.r][p.c][std::uniform_int_distribution<int>(0, adj[p.r][p.c].size() - 1)(rng)];\n                if (v == u) continue;\n\n                double new_sum_d_div_k = state.score_sum_d_div_k - (double)d[u.r][u.c]/state.k[u.r][u.c] + (double)d[u.r][u.c]/(state.k[u.r][u.c]-1) - (double)d[v.r][v.c]/state.k[v.r][v.c] + (double)d[v.r][v.c]/(state.k[v.r][v.c]+1);\n                double new_energy = (double)(state.tour.size() - 1) * new_sum_d_div_k;\n                double delta_e = new_energy - current_energy;\n\n                if (delta_e < 0 || u_dist(rng) < std::exp(-delta_e / temp)) {\n                    state.remove_occurrence(u, it_u); *it_u = v; state.add_occurrence(v, it_u);\n                    state.score_sum_d_div_k = new_sum_d_div_k;\n                    state.k[u.r][u.c]--; state.k[v.r][v.c]++;\n                    current_energy = new_energy;\n                }\n            }\n        }\n    }\n\n    std::string moves = pos_to_moves(state.tour);\n    std::cout << moves << std::endl;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    \n    std::cin >> N;\n    h_walls.resize(N - 1);\n    v_walls.resize(N);\n    d.assign(N, std::vector<int>(N));\n    for (int i = 0; i < N - 1; ++i) std::cin >> h_walls[i];\n    for (int i = 0; i < N; ++i) std::cin >> v_walls[i];\n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) std::cin >> d[i][j];\n    \n    solve();\n    \n    return 0;\n}","ahc028":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <random>\n\nusing namespace std;\n\n// Constants from problem statement\nconst int N_GRID = 15;\nconst int M_TARGETS = 200;\n\n// Global variables for problem input\nint start_r, start_c;\nvector<string> grid(N_GRID);\nvector<string> targets(M_TARGETS);\n\n// Precomputed data structures\nvector<pair<int, int>> char_positions[26];\nint overlaps[M_TARGETS][M_TARGETS];\ndouble avg_transition_cost[26][26];\ndouble weights[M_TARGETS][M_TARGETS];\n\n// Random number generator for SA\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// --- Utility Functions ---\n\ninline int manhattan_distance(const pair<int,int>& p1, const pair<int,int>& p2) {\n    return abs(p1.first - p2.first) + abs(p1.second - p2.second);\n}\n\n// --- Precomputation Functions ---\n\nvoid read_input() {\n    int n_in, m_in;\n    cin >> n_in >> m_in;\n    cin >> start_r >> start_c;\n    for (int i = 0; i < N_GRID; ++i) cin >> grid[i];\n    for (int i = 0; i < M_TARGETS; ++i) cin >> targets[i];\n}\n\nvoid precompute_char_positions() {\n    for (int i = 0; i < N_GRID; ++i) {\n        for (int j = 0; j < N_GRID; ++j) {\n            char_positions[grid[i][j] - 'A'].push_back({i, j});\n        }\n    }\n}\n\nvoid precompute_overlaps() {\n    for (int i = 0; i < M_TARGETS; ++i) {\n        for (int j = 0; j < M_TARGETS; ++j) {\n            if (i == j) continue;\n            for (int k = 4; k >= 1; --k) {\n                if (targets[i].substr(5 - k) == targets[j].substr(0, k)) {\n                    overlaps[i][j] = k;\n                    break;\n                }\n            }\n        }\n    }\n}\n\nvoid precompute_avg_transition_cost() {\n    for (int i = 0; i < 26; ++i) {\n        for (int j = 0; j < 26; ++j) {\n            if (char_positions[i].empty() || char_positions[j].empty()) continue;\n            double total_min_dist = 0;\n            for (const auto& p1 : char_positions[i]) {\n                int min_dist = 1e9;\n                for (const auto& p2 : char_positions[j]) {\n                    min_dist = min(min_dist, manhattan_distance(p1, p2));\n                }\n                total_min_dist += min_dist;\n            }\n            avg_transition_cost[i][j] = total_min_dist / char_positions[i].size() + 1.0;\n        }\n    }\n}\n\nvoid precompute_weights() {\n    for (int i = 0; i < M_TARGETS; ++i) {\n        for (int j = 0; j < M_TARGETS; ++j) {\n            if (i == j) continue;\n            int ov = overlaps[i][j];\n            const string& t_j = targets[j];\n            const string& t_i = targets[i];\n            \n            double cost_est = 0;\n            if (5 - ov > 0) {\n                cost_est += avg_transition_cost[t_i.back() - 'A'][t_j[ov] - 'A'];\n                for (int k = ov; k < 4; ++k) {\n                    cost_est += avg_transition_cost[t_j[k] - 'A'][t_j[k+1] - 'A'];\n                }\n            }\n            weights[i][j] = cost_est;\n        }\n    }\n}\n\n// --- Core Logic ---\n// DP-based cost calculation. Corrected, simple version.\nlong long calculate_path_cost_dp(const vector<int>& path) {\n    string S;\n    S.reserve(5 * M_TARGETS);\n    if (path.empty()) return 0;\n    S += targets[path[0]];\n    for (size_t i = 1; i < path.size(); ++i) {\n        S += targets[path[i]].substr(overlaps[path[i - 1]][path[i]]);\n    }\n    if (S.length() > 5000) return 1e18;\n    if (S.empty()) return 0;\n\n    vector<long long> prev_dp;\n    const auto& pos_0 = char_positions[S[0] - 'A'];\n    prev_dp.resize(pos_0.size());\n    for (size_t i = 0; i < pos_0.size(); ++i) {\n        prev_dp[i] = manhattan_distance({start_r, start_c}, pos_0[i]) + 1;\n    }\n\n    for (size_t k = 1; k < S.length(); ++k) {\n        const auto& pos_k_minus_1 = char_positions[S[k - 1] - 'A'];\n        const auto& pos_k = char_positions[S[k] - 'A'];\n        vector<long long> current_dp(pos_k.size());\n\n        for (size_t j = 0; j < pos_k.size(); ++j) {\n            long long min_prev_cost = 1e18;\n            for (size_t i = 0; i < pos_k_minus_1.size(); ++i) {\n                long long cost = prev_dp[i] + manhattan_distance(pos_k_minus_1[i], pos_k[j]);\n                min_prev_cost = min(min_prev_cost, cost);\n            }\n            current_dp[j] = min_prev_cost + 1;\n        }\n        prev_dp = move(current_dp);\n    }\n    if (prev_dp.empty()) return 1e18;\n    return *min_element(prev_dp.begin(), prev_dp.end());\n}\n\n// Full DP with backpointers to generate final move sequence.\nvoid generate_final_moves(const vector<int>& path, vector<pair<int, int>>& move_sequence) {\n    string S;\n    S.reserve(5 * M_TARGETS);\n    if (path.empty()) return;\n    S += targets[path[0]];\n    for (size_t i = 1; i < path.size(); ++i) {\n        S += targets[path[i]].substr(overlaps[path[i-1]][path[i]]);\n    }\n    if (S.empty() || S.length() > 5000) return;\n\n    move_sequence.clear();\n    vector<vector<long long>> dp(S.length());\n    vector<vector<int>> backpointers(S.length());\n\n    const auto& pos_0 = char_positions[S[0] - 'A'];\n    dp[0].resize(pos_0.size());\n    for (size_t i = 0; i < pos_0.size(); ++i) {\n        dp[0][i] = manhattan_distance({start_r, start_c}, pos_0[i]) + 1;\n    }\n\n    for (size_t k = 1; k < S.length(); ++k) {\n        const auto& pos_k_minus_1 = char_positions[S[k - 1] - 'A'];\n        const auto& pos_k = char_positions[S[k] - 'A'];\n        dp[k].resize(pos_k.size());\n        backpointers[k].resize(pos_k.size());\n\n        for (size_t j = 0; j < pos_k.size(); ++j) {\n            long long min_prev_cost = 1e18;\n            int best_prev_idx = -1;\n            for (size_t i = 0; i < pos_k_minus_1.size(); ++i) {\n                long long cost = dp[k-1][i] + manhattan_distance(pos_k_minus_1[i], pos_k[j]);\n                if (cost < min_prev_cost) {\n                    min_prev_cost = cost;\n                    best_prev_idx = i;\n                }\n            }\n            dp[k][j] = min_prev_cost + 1;\n            backpointers[k][j] = best_prev_idx;\n        }\n    }\n\n    long long final_cost = 1e18;\n    int last_idx = -1;\n    if (!dp.back().empty()) {\n        for (size_t i = 0; i < dp.back().size(); ++i) {\n            if (dp.back()[i] < final_cost) {\n                final_cost = dp.back()[i];\n                last_idx = i;\n            }\n        }\n    }\n\n    move_sequence.resize(S.length());\n    for (int k = S.length() - 1; k >= 0; --k) {\n        move_sequence[k] = char_positions[S[k] - 'A'][last_idx];\n        if (k > 0) last_idx = backpointers[k][last_idx];\n    }\n}\n\n\ndouble calculate_approx_cost(const vector<int>& path) {\n    double cost = 0;\n    for (size_t i = 0; i < path.size() - 1; ++i) {\n        cost += weights[path[i]][path[i+1]];\n    }\n    return cost;\n}\n\nvector<int> get_initial_solution() {\n    vector<int> best_path;\n    double min_weight_sum = 1e18;\n\n    vector<int> p(M_TARGETS);\n    iota(p.begin(), p.end(), 0);\n    shuffle(p.begin(), p.end(), rng);\n    \n    for(int i = 0; i < min(M_TARGETS, 20); ++i) {\n        int start_node = p[i];\n        vector<int> path; path.reserve(M_TARGETS);\n        path.push_back(start_node);\n        vector<bool> visited(M_TARGETS, false); visited[start_node] = true;\n        int current_node = start_node;\n        double current_weight_sum = 0;\n\n        for (int k = 0; k < M_TARGETS - 1; ++k) {\n            int next_node = -1; double min_weight = 1e18;\n            for (int j = 0; j < M_TARGETS; ++j) {\n                if (!visited[j] && weights[current_node][j] < min_weight) {\n                    min_weight = weights[current_node][j]; next_node = j;\n                }\n            }\n            visited[next_node] = true; path.push_back(next_node);\n            current_weight_sum += min_weight; current_node = next_node;\n        }\n        if (current_weight_sum < min_weight_sum) {\n            min_weight_sum = current_weight_sum; best_path = path;\n        }\n    }\n    return best_path;\n}\n\nvoid solve() {\n    auto time_start = chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_MS = 1950.0;\n    const double FAST_SA_TIME_MS = 1500.0;\n\n    vector<int> current_path = get_initial_solution();\n    vector<int> best_path_overall = current_path;\n    long long best_cost_overall = calculate_path_cost_dp(best_path_overall);\n\n    uniform_int_distribution<int> dist(0, M_TARGETS - 1);\n    uniform_int_distribution<int> move_dist(0, 9);\n    uniform_real_distribution<double> accept_dist(0.0, 1.0);\n\n    // Stage 1: Fast SA with approximate cost\n    {\n        double start_temp = 50.0, end_temp = 0.1;\n        vector<int> best_path_fast = current_path;\n        double current_approx = calculate_approx_cost(current_path);\n        double best_approx = current_approx;\n        int iter_count = 0;\n        \n        while (chrono::duration<double, milli>(chrono::high_resolution_clock::now() - time_start).count() < FAST_SA_TIME_MS) {\n            iter_count++;\n            vector<int> new_path = current_path;\n            int i = dist(rng), j = dist(rng);\n            if (i == j) continue;\n            \n            int move_type = move_dist(rng);\n            if (move_type < 5) { // Reverse (50%)\n                if (i > j) swap(i, j); reverse(new_path.begin() + i, new_path.begin() + j + 1);\n            } else if (move_type < 8) { // Move (30%)\n                int element = new_path[i]; new_path.erase(new_path.begin() + i); new_path.insert(new_path.begin() + j, element);\n            } else { // Swap (20%)\n                swap(new_path[i], new_path[j]);\n            }\n\n            double new_approx = calculate_approx_cost(new_path);\n            double elapsed_frac = chrono::duration<double, milli>(chrono::high_resolution_clock::now() - time_start).count() / FAST_SA_TIME_MS;\n            double temp = start_temp * pow(end_temp / start_temp, elapsed_frac);\n            \n            if (new_approx < current_approx || accept_dist(rng) < exp((current_approx - new_approx) / temp)) {\n                current_path = move(new_path); current_approx = new_approx;\n            }\n            if (current_approx < best_approx) { best_approx = current_approx; best_path_fast = current_path; }\n\n            if (iter_count % 5000 == 0) {\n                 long long fast_sa_best_full_cost = calculate_path_cost_dp(best_path_fast);\n                 if (fast_sa_best_full_cost < best_cost_overall) {\n                     best_cost_overall = fast_sa_best_full_cost; best_path_overall = best_path_fast;\n                 }\n            }\n        }\n        long long fast_sa_best_full_cost = calculate_path_cost_dp(best_path_fast);\n        if (fast_sa_best_full_cost < best_cost_overall) {\n            best_cost_overall = fast_sa_best_full_cost; best_path_overall = best_path_fast;\n        }\n    }\n\n    // Stage 2: Slow SA with exact DP cost\n    {\n        double start_temp = 200.0, end_temp = 1.0;\n        current_path = best_path_overall;\n        long long current_full_cost = best_cost_overall;\n        \n        while (chrono::duration<double, milli>(chrono::high_resolution_clock::now() - time_start).count() < TIME_LIMIT_MS) {\n            vector<int> new_path = current_path;\n            int i = dist(rng), j = dist(rng);\n            if (i == j) continue;\n            \n            int move_type = move_dist(rng);\n            if (move_type < 5) { if (i > j) swap(i, j); reverse(new_path.begin() + i, new_path.begin() + j + 1);\n            } else if (move_type < 8) { int element = new_path[i]; new_path.erase(new_path.begin() + i); new_path.insert(new_path.begin() + j, element);\n            } else { swap(new_path[i], new_path[j]); }\n\n            long long new_full_cost = calculate_path_cost_dp(new_path);\n            double time_now = chrono::duration<double, milli>(chrono::high_resolution_clock::now() - time_start).count();\n            if (time_now >= TIME_LIMIT_MS) break; \n            double elapsed_frac = (time_now - FAST_SA_TIME_MS) / (TIME_LIMIT_MS - FAST_SA_TIME_MS);\n            double temp = start_temp * pow(end_temp / start_temp, elapsed_frac);\n            \n            if (new_full_cost < current_full_cost || accept_dist(rng) < exp((double)(current_full_cost - new_full_cost) / temp)) {\n                current_path = move(new_path); current_full_cost = new_full_cost;\n            }\n            if (current_full_cost < best_cost_overall) { best_cost_overall = current_full_cost; best_path_overall = current_path; }\n        }\n    }\n\n    vector<pair<int, int>> final_moves;\n    generate_final_moves(best_path_overall, final_moves);\n    for (const auto& move : final_moves) {\n        cout << move.first << \" \" << move.second << \"\\n\";\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    read_input();\n    precompute_char_positions();\n    precompute_overlaps();\n    precompute_avg_transition_cost();\n    precompute_weights();\n    solve();\n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <map>\n#include <iomanip>\n\n// Constants and Typedefs\nusing namespace std;\nusing Point = pair<int, int>;\n\n// Utilities\nstruct Timer {\n    chrono::high_resolution_clock::time_point start_time;\n    Timer() {\n        start_time = chrono::high_resolution_clock::now();\n    }\n    long long get_elapsed_ms() {\n        auto end_time = chrono::high_resolution_clock::now();\n        return chrono::duration_cast<chrono::milliseconds>(end_time - start_time).count();\n    }\n};\n\n// Global random engine\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// Problem specific structures\nstruct Polyomino {\n    int id;\n    int d;\n    vector<Point> coords;\n    int max_i = 0, max_j = 0;\n};\n\nstruct Problem {\n    int N, M;\n    double epsilon;\n    vector<Polyomino> fields;\n    vector<vector<Point>> valid_placements;\n    map<vector<Point>, vector<int>> identical_shapes;\n};\n\nstruct Particle {\n    vector<Point> placements;\n    vector<vector<int>> v_grid;\n\n    Particle(int M, int N) : placements(M), v_grid(N, vector<int>(N, 0)) {}\n\n    void compute_v_grid(const Problem& prob) {\n        for (auto& row : v_grid) fill(row.begin(), row.end(), 0);\n        for (int m = 0; m < prob.M; ++m) {\n            const auto& p = placements[m];\n            if (p.first == -1) continue;\n            for (const auto& rel_coord : prob.fields[m].coords) {\n                v_grid[p.first + rel_coord.first][p.second + rel_coord.second]++;\n            }\n        }\n    }\n};\n\n// Main solver\nclass Solver {\nprivate:\n    Problem prob;\n    int num_particles;\n    vector<Particle> particles;\n    vector<double> log_weights;\n    vector<vector<int>> known_v;\n    Timer timer;\n    int query_count = 0;\n    \npublic:\n    Solver(int N, int M, double epsilon, const vector<Polyomino>& fields, int K)\n        : prob{N, M, epsilon, fields}, num_particles(K), known_v(N, vector<int>(N, -1)) {\n        prob.valid_placements.resize(M);\n        for (int m = 0; m < M; ++m) {\n            auto& field = prob.fields[m];\n            field.max_i = 0; field.max_j = 0;\n            for(const auto& p : field.coords) {\n                field.max_i = max(field.max_i, p.first);\n                field.max_j = max(field.max_j, p.second);\n            }\n            if (field.max_i >= N || field.max_j >= N) continue; \n            for (int i = 0; i <= N - 1 - field.max_i; ++i) {\n                for (int j = 0; j <= N - 1 - field.max_j; ++j) {\n                    prob.valid_placements[m].push_back({i, j});\n                }\n            }\n        }\n        \n        for (int m = 0; m < M; ++m) {\n            vector<Point> sorted_coords = fields[m].coords;\n            sort(sorted_coords.begin(), sorted_coords.end());\n            prob.identical_shapes[sorted_coords].push_back(m);\n        }\n    }\n\n    void solve() {\n        initialize_particles();\n        perform_initial_queries();\n\n        while (timer.get_elapsed_ms() < 2650 && query_count < 2 * prob.N * prob.N - prob.N) {\n            if (!run_main_loop_step()) break;\n        }\n\n        while (timer.get_elapsed_ms() < 2900 && query_count < 2 * prob.N * prob.N) {\n            auto p_grid = calculate_p_grid();\n            vector<pair<double, Point>> uncertain_cells_sorted;\n            for (int i=0; i<prob.N; ++i) for (int j=0; j<prob.N; ++j) if (known_v[i][j] == -1) {\n                if (p_grid[i][j] > 0.05 && p_grid[i][j] < 0.95) {\n                    uncertain_cells_sorted.push_back({abs(p_grid[i][j] - 0.5), {i, j}});\n                }\n            }\n            if (uncertain_cells_sorted.empty()) break;\n            sort(uncertain_cells_sorted.begin(), uncertain_cells_sorted.end());\n            query_drill(uncertain_cells_sorted[0].second.first, uncertain_cells_sorted[0].second.second);\n            if(timer.get_elapsed_ms() < 2900) resample_and_mutate();\n        }\n        \n        final_guess_loop();\n    }\n\nprivate:\n    void final_guess_loop() {\n        auto p_grid = calculate_p_grid();\n        vector<Point> guess;\n        for (int i = 0; i < prob.N; ++i) for (int j = 0; j < prob.N; ++j) {\n            if (known_v[i][j] != -1) { if (known_v[i][j] > 0) guess.push_back({i, j}); }\n            else { if (p_grid[i][j] > 0.5) guess.push_back({i, j}); }\n        }\n\n        while (query_count < 2 * prob.N * prob.N) {\n            cout << \"a \" << guess.size();\n            for(const auto& p : guess) cout << \" \" << p.first << \" \" << p.second;\n            cout << endl;\n\n            int result;\n            cin >> result;\n            if (result == 1) return;\n            query_count++; \n        }\n    }\n\n    bool run_main_loop_step() {\n        auto p_grid = calculate_p_grid();\n        Point most_uncertain_cell = {-1, -1};\n        double min_dist_to_half = 1.0;\n        int uncertain_count = 0;\n        for (int i=0; i<prob.N; ++i) for (int j=0; j<prob.N; ++j) if (known_v[i][j] == -1 && p_grid[i][j] > 0.05 && p_grid[i][j] < 0.95) {\n            uncertain_count++;\n            if (abs(p_grid[i][j] - 0.5) < min_dist_to_half) {\n                min_dist_to_half = abs(p_grid[i][j] - 0.5);\n                most_uncertain_cell = {i, j};\n            }\n        }\n        \n        if (most_uncertain_cell.first == -1) return false;\n\n        if (uncertain_count < prob.N + prob.M) {\n            query_drill(most_uncertain_cell.first, most_uncertain_cell.second);\n        } else {\n            vector<Point> query_set;\n            for (int di=-1; di<=1; ++di) for (int dj=-1; dj<=1; ++dj) {\n                int ni = most_uncertain_cell.first+di, nj=most_uncertain_cell.second+dj;\n                if (ni>=0 && ni<prob.N && nj>=0 && nj<prob.N && known_v[ni][nj]==-1) query_set.push_back({ni, nj});\n            }\n            if (query_set.size() >= 2) query_divine(query_set);\n            else query_drill(most_uncertain_cell.first, most_uncertain_cell.second);\n        }\n        resample_and_mutate();\n        return true;\n    }\n\n    void initialize_particles() {\n        particles.assign(num_particles, Particle(prob.M, prob.N));\n        for (int i = 0; i < num_particles; ++i) {\n            for (int m = 0; m < prob.M; ++m) {\n                if(prob.valid_placements[m].empty()){ particles[i].placements[m] = {-1, -1}; continue; }\n                uniform_int_distribution<> dist(0, prob.valid_placements[m].size() - 1);\n                particles[i].placements[m] = prob.valid_placements[m][dist(rng)];\n            }\n            particles[i].compute_v_grid(prob);\n        }\n        log_weights.assign(num_particles, 0.0);\n    }\n    \n    void perform_initial_queries() {\n        vector<Point> all, h_i, h_j, check;\n        for (int i=0; i<prob.N; ++i) for (int j=0; j<prob.N; ++j) {\n            all.push_back({i,j}); if (i<prob.N/2) h_i.push_back({i,j});\n            if (j<prob.N/2) h_j.push_back({i,j}); if ((i+j)%2==0) check.push_back({i,j});\n        }\n        for(const auto& q_set : {all, h_i, h_j, check}){\n            if (timer.get_elapsed_ms() > 2650 || q_set.size() < 2) continue;\n            query_divine(q_set); resample_and_mutate();\n        }\n    }\n\n    void query_drill(int r, int c) {\n        if (known_v[r][c] != -1 || query_count >= 2*prob.N*prob.N) return;\n        query_count++; cout << \"q 1 \" << r << \" \" << c << endl;\n        int v; cin >> v; known_v[r][c] = v;\n        for (int i=0; i<num_particles; ++i) if(particles[i].v_grid[r][c] != v) log_weights[i] = -HUGE_VAL;\n    }\n\n    void query_divine(const vector<Point>& S) {\n        if (S.empty() || query_count >= 2*prob.N*prob.N) return;\n        if (S.size() == 1) { query_drill(S[0].first, S[0].second); return; }\n        query_count++; cout << \"q \" << S.size(); for(const auto& p:S) cout<<\" \"<<p.first<<\" \"<<p.second; cout<<endl;\n        int O; cin >> O;\n        double var = S.size() * prob.epsilon * (1.0 - prob.epsilon), stddev = sqrt(var);\n        for (int i=0; i<num_particles; ++i) {\n            if (log_weights[i] <= -HUGE_VAL) continue;\n            int vS=0; for(const auto& p:S) vS+=particles[i].v_grid[p.first][p.second];\n            double mu = S.size()*prob.epsilon + vS*(1.0-2.0*prob.epsilon);\n            double log_p = (stddev>1e-9)? -log(stddev*sqrt(2*M_PI))-0.5*pow((O-mu)/stddev,2) : ((abs(O-mu)<0.5)?0.0:-HUGE_VAL);\n            log_weights[i] += log_p;\n        }\n    }\n\n    void resample_and_mutate() {\n        double max_log_w = -HUGE_VAL; for(double lw:log_weights) if(lw > max_log_w) max_log_w = lw;\n        if (!isfinite(max_log_w)) {\n            initialize_particles();\n            for (int r=0; r<prob.N; ++r) for(int c=0; c<prob.N; ++c) if (known_v[r][c]!=-1)\n                for(int i=0; i<num_particles; ++i) if (particles[i].v_grid[r][c] != known_v[r][c]) log_weights[i] = -HUGE_VAL;\n            return;\n        }\n        vector<double> current_weights(num_particles);\n        for(int i=0; i<num_particles; ++i) current_weights[i] = exp(log_weights[i] - max_log_w);\n        \n        vector<Particle> new_particles; new_particles.reserve(num_particles);\n        int num_elite=num_particles*0.05, num_random=num_particles*0.10;\n        \n        vector<pair<double,int>> sorted_w; for(int i=0; i<num_particles; ++i) sorted_w.push_back({-log_weights[i], i});\n        sort(sorted_w.begin(), sorted_w.end());\n        for(int i=0; i<num_elite; ++i) new_particles.push_back(particles[sorted_w[i].second]);\n        \n        discrete_distribution<int> dist(current_weights.begin(), current_weights.end());\n        for(int i=0; i<num_particles-num_elite-num_random; ++i) new_particles.push_back(particles[dist(rng)]);\n        for(int i=0; i<num_random; ++i){\n            new_particles.emplace_back(prob.M, prob.N);\n            for(int m=0; m<prob.M; ++m){\n                if(prob.valid_placements[m].empty()){ new_particles.back().placements[m]={-1,-1}; continue;}\n                uniform_int_distribution<> p_dist(0, prob.valid_placements[m].size()-1);\n                new_particles.back().placements[m] = prob.valid_placements[m][p_dist(rng)];\n            }\n            new_particles.back().compute_v_grid(prob);\n        }\n\n        uniform_real_distribution<> r_dist(0.0, 1.0); int dr[]={-1,1,0,0}, dc[]={0,0,-1,1};\n        for(size_t i = num_elite; i < new_particles.size(); ++i) {\n            auto& p = new_particles[i];\n            for(int m=0; m<prob.M; ++m) if(p.placements[m].first!=-1 && r_dist(rng)<0.1){\n                Point old_pos = p.placements[m], new_pos = old_pos;\n                if (r_dist(rng)<0.8) {\n                    vector<Point> neighbors; for(int k=0; k<4; ++k){\n                        Point n = {old_pos.first+dr[k], old_pos.second+dc[k]};\n                        if (n.first>=0 && n.first<=prob.N-1-prob.fields[m].max_i && n.second>=0 && n.second<=prob.N-1-prob.fields[m].max_j) neighbors.push_back(n);\n                    }\n                    if(!neighbors.empty()) new_pos = neighbors[uniform_int_distribution<>(0,neighbors.size()-1)(rng)];\n                } else {\n                    if (!prob.valid_placements[m].empty()) {\n                        new_pos = prob.valid_placements[m][uniform_int_distribution<>(0,prob.valid_placements[m].size()-1)(rng)];\n                    }\n                }\n                if (new_pos != old_pos) {\n                    p.placements[m] = new_pos;\n                    for(const auto& c:prob.fields[m].coords) {\n                        p.v_grid[old_pos.first+c.first][old_pos.second+c.second]--;\n                        p.v_grid[new_pos.first+c.first][new_pos.second+c.second]++;\n                    }\n                }\n            }\n            for(const auto& [sh, ids] : prob.identical_shapes) if (ids.size()>1 && r_dist(rng)<0.1) {\n                uniform_int_distribution<int> id_dist(0,ids.size()-1); int i1=id_dist(rng),i2=id_dist(rng);\n                if(i1!=i2) swap(p.placements[ids[i1]], p.placements[ids[i2]]);\n            }\n        }\n        particles=new_particles; log_weights.assign(num_particles,0.0);\n    }\n    \n    vector<vector<double>> calculate_p_grid() {\n        vector<vector<double>> p_grid(prob.N, vector<double>(prob.N, 0.0));\n        int valid_particles = 0;\n        for (const auto& p : particles) {\n             bool is_valid=true; for(const auto& pl:p.placements) if(pl.first==-1) {is_valid=false; break;}\n             if(!is_valid) continue; valid_particles++;\n             for(int i=0; i<prob.N; ++i) for(int j=0; j<prob.N; ++j) if(p.v_grid[i][j]>0) p_grid[i][j]+=1.0;\n        }\n        if(valid_particles>0) for(auto& r:p_grid) for(auto& c:r) c/=valid_particles;\n        return p_grid;\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false); cin.tie(NULL);\n    int N, M; double epsilon; cin >> N >> M >> epsilon;\n    vector<Polyomino> fields(M);\n    for (int i=0; i<M; ++i) {\n        fields[i].id = i; cin >> fields[i].d; fields[i].coords.resize(fields[i].d);\n        for(int j=0; j<fields[i].d; ++j) cin>>fields[i].coords[j].first>>fields[i].coords[j].second;\n    }\n    int K = 2200;\n    if (N <= 12) K = 1800;\n    if (M >= 15 || N >= 18) K = 3000;\n    Solver solver(N, M, epsilon, fields, K);\n    solver.solve();\n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n#include <functional>\n\nusing namespace std;\n\n// Constants\nconstexpr int W = 1000;\nint D, N;\n\n// Structures\nstruct Rect {\n    int r0, c0, r1, c1;\n    long long area() const {\n        return (long long)(r1 - r0) * (c1 - c0);\n    }\n};\n\nstruct Node {\n    bool is_leaf;\n    int k_min, k_max; // range of reservation indices\n    Node *left = nullptr, *right = nullptr;\n    Node *parent = nullptr;\n\n    // For internal nodes\n    bool is_vertical_split;\n    int split_idx;\n\n    // For leaf nodes\n    int k;\n};\n\n// Globals\nvector<vector<long long>> a;\nvector<Node> tree_nodes;\nint node_idx_counter;\nvector<Rect> current_rects;\nvector<int> split_coords;\nvector<Node*> split_idx_to_node;\n\nvector<vector<bool>> h_prev_exists, v_prev_exists;\nvector<vector<int>> h_curr_count, v_curr_count;\n\n// Randomness\nuint64_t xor_shift() {\n    static uint64_t x = 88172645463325252ULL;\n    x ^= x << 13;\n    x ^= x >> 7;\n    x ^= x << 17;\n    return x;\n}\n\nint rand_int(int min_val, int max_val) {\n    if (min_val > max_val) return min_val;\n    return min_val + xor_shift() % (max_val - min_val + 1);\n}\n\ndouble rand_double() {\n    return (double)xor_shift() / UINT64_MAX;\n}\n\n// Tree building\nNode* build_tree(int k_min, int k_max, const Rect& region) {\n    Node* node = &tree_nodes[node_idx_counter++];\n    node->k_min = k_min;\n    node->k_max = k_max;\n\n    if (k_max - k_min == 1) {\n        node->is_leaf = true;\n        node->k = k_min;\n        return node;\n    }\n\n    node->is_leaf = false;\n    int k_mid = k_min + (k_max - k_min) / 2;\n    \n    node->is_vertical_split = (region.c1 - region.c0 >= region.r1 - region.r0);\n    \n    Rect left_region, right_region;\n    if (node->is_vertical_split) {\n        int c_split = region.c0 + (region.c1 - region.c0) / 2;\n        left_region = {region.r0, region.c0, region.r1, c_split};\n        right_region = {region.r0, c_split, region.r1, region.c1};\n    } else {\n        int r_split = region.r0 + (region.r1 - region.r0) / 2;\n        left_region = {region.r0, region.c0, r_split, region.c1};\n        right_region = {r_split, region.c0, region.r1, region.c1};\n    }\n    \n    node->left = build_tree(k_min, k_mid, left_region);\n    node->left->parent = node;\n    node->right = build_tree(k_mid, k_max, right_region);\n    node->right->parent = node;\n    return node;\n}\n\nvoid assign_split_indices(Node* node, int& split_idx_counter) {\n    if (node->is_leaf) return;\n    node->split_idx = split_idx_counter++;\n    split_idx_to_node[node->split_idx] = node;\n    assign_split_indices(node->left, split_idx_counter);\n    assign_split_indices(node->right, split_idx_counter);\n}\n\n\n// Layout and cost calculations\nvoid get_rects_from_coords(Node* node, const Rect& region, const vector<int>& coords, vector<Rect>& rects_out) {\n    if (node->is_leaf) {\n        rects_out[node->k] = region;\n        return;\n    }\n\n    int coord = coords[node->split_idx];\n    Rect left_region, right_region;\n\n    if (node->is_vertical_split) {\n        left_region = {region.r0, region.c0, region.r1, coord};\n        right_region = {region.r0, coord, region.r1, region.c1};\n    } else {\n        left_region = {region.r0, region.c0, coord, region.c1};\n        right_region = {coord, region.c0, region.r1, region.c1};\n    }\n    get_rects_from_coords(node->left, left_region, coords, rects_out);\n    get_rects_from_coords(node->right, right_region, coords, rects_out);\n}\n\nvoid get_ideal_coords(Node* node, const Rect& region, int d, vector<int>& coords) {\n    if (node->is_leaf) return;\n    \n    long long total_area_left = 0;\n    for (int k = node->left->k_min; k < node->left->k_max; ++k) total_area_left += a[d][k];\n    \n    long long total_area_right = 0;\n    for (int k = node->right->k_min; k < node->right->k_max; ++k) total_area_right += a[d][k];\n\n    long long total_area_node = total_area_left + total_area_right;\n    if (total_area_node == 0) total_area_node = 1;\n\n    int coord;\n    Rect left_region, right_region;\n    if (node->is_vertical_split) {\n        coord = region.c0 + round((double)(region.c1 - region.c0) * total_area_left / total_area_node);\n        coord = clamp(coord, region.c0 + 1, region.c1 - 1);\n        left_region = {region.r0, region.c0, region.r1, coord};\n        right_region = {region.r0, coord, region.r1, region.c1};\n    } else {\n        coord = region.r0 + round((double)(region.r1 - region.r0) * total_area_left / total_area_node);\n        coord = clamp(coord, region.r0 + 1, region.r1 - 1);\n        left_region = {region.r0, region.c0, coord, region.c1};\n        right_region = {coord, region.c0, region.r1, region.c1};\n    }\n    coords[node->split_idx] = coord;\n    get_ideal_coords(node->left, left_region, d, coords);\n    get_ideal_coords(node->right, right_region, d, coords);\n}\n\nlong long calculate_area_cost(int d, const vector<Rect>& rects) {\n    long long cost = 0;\n    for (int k = 0; k < N; ++k) {\n        cost += 100 * max(0LL, a[d][k] - rects[k].area());\n    }\n    return cost;\n}\n\nvoid populate_partition_counts(const vector<Rect>& rects) {\n    for (int i=1; i<W; ++i) fill(h_curr_count[i].begin(), h_curr_count[i].end(), 0);\n    for (int i=0; i<W; ++i) fill(v_curr_count[i].begin(), v_curr_count[i].end(), 0);\n    \n    for (int k = 0; k < N; ++k) {\n        const auto& r = rects[k];\n        if (r.r0 > 0) for (int c = r.c0; c < r.c1; ++c) h_curr_count[r.r0][c]++;\n        if (r.r1 < W) for (int c = r.c0; c < r.c1; ++c) h_curr_count[r.r1][c]++;\n        if (r.c0 > 0) for (int i = r.r0; i < r.r1; ++i) v_curr_count[i][r.c0]++;\n        if (r.c1 < W) for (int i = r.r0; i < r.r1; ++i) v_curr_count[i][r.c1]++;\n    }\n}\n\nlong long calculate_partition_change_cost_full() {\n    long long cost = 0;\n    for (int i = 1; i < W; ++i) {\n        for (int j = 0; j < W; ++j) {\n            cost += (h_prev_exists[i][j] != (h_curr_count[i][j] > 0));\n        }\n    }\n    for (int i = 0; i < W; ++i) {\n        for (int j = 1; j < W; ++j) {\n            cost += (v_prev_exists[i][j] != (v_curr_count[i][j] > 0));\n        }\n    }\n    return cost;\n}\n\nvoid update_prev_partitions() {\n    for (int i = 1; i < W; ++i) {\n        for (int j = 0; j < W; ++j) {\n            h_prev_exists[i][j] = (h_curr_count[i][j] > 0);\n        }\n    }\n    for (int i = 0; i < W; ++i) {\n        for (int j = 1; j < W; ++j) {\n            v_prev_exists[i][j] = (v_curr_count[i][j] > 0);\n        }\n    }\n}\n\n// Main logic\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int W_in;\n    cin >> W_in >> D >> N; \n    a.resize(D, vector<long long>(N));\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            cin >> a[d][k];\n        }\n    }\n\n    tree_nodes.resize(2 * N);\n    node_idx_counter = 0;\n    split_idx_to_node.resize(N - 1);\n    Node* root = build_tree(0, N, {0, 0, W, W});\n    int split_idx_counter = 0;\n    assign_split_indices(root, split_idx_counter);\n\n    current_rects.resize(N);\n    split_coords.resize(N - 1);\n    \n    h_prev_exists.resize(W + 1, vector<bool>(W + 1, false));\n    v_prev_exists.resize(W + 1, vector<bool>(W + 1, false));\n    h_curr_count.resize(W + 1, vector<int>(W + 1, 0));\n    v_curr_count.resize(W + 1, vector<int>(W + 1, 0));\n\n    // Day 0\n    get_ideal_coords(root, {0, 0, W, W}, 0, split_coords);\n    get_rects_from_coords(root, {0, 0, W, W}, split_coords, current_rects);\n    populate_partition_counts(current_rects);\n    update_prev_partitions();\n\n    vector<vector<Rect>> solution(D, vector<Rect>(N));\n    solution[0] = current_rects;\n\n    auto global_start_time = chrono::high_resolution_clock::now();\n\n    // Day 1 to D-1\n    for (int d = 1; d < D; ++d) {\n        get_rects_from_coords(root, {0, 0, W, W}, split_coords, current_rects);\n        populate_partition_counts(current_rects);\n        \n        long long current_area_cost = calculate_area_cost(d, current_rects);\n        long long partition_change_cost = calculate_partition_change_cost_full();\n        long long current_total_cost = current_area_cost + partition_change_cost;\n        \n        vector<int> best_coords = split_coords;\n        long long best_total_cost = current_total_cost;\n        \n        auto day_start_time = chrono::high_resolution_clock::now();\n        double time_limit_per_day = (2950.0 - chrono::duration_cast<chrono::milliseconds>(day_start_time - global_start_time).count()) / (D - d);\n\n        double temp = 5000;\n        int iter = 0;\n        while (true) {\n            iter++;\n            if (iter % 128 == 0) {\n                 auto now = chrono::high_resolution_clock::now();\n                 double elapsed = chrono::duration_cast<chrono::milliseconds>(now - day_start_time).count();\n                 if (elapsed > time_limit_per_day) break;\n            }\n            temp *= 0.9999;\n\n            int split_to_change = rand_int(0, N - 2);\n            Node* target_node = split_idx_to_node[split_to_change];\n            \n            Rect split_region = {0, 0, W, W};\n            Node* temp_node = target_node;\n            while(temp_node->parent != nullptr) {\n                Node* p = temp_node->parent;\n                int p_coord = split_coords[p->split_idx];\n                if (p->is_vertical_split) {\n                    if (temp_node == p->left) split_region.c1 = min(split_region.c1, p_coord);\n                    else split_region.c0 = max(split_region.c0, p_coord);\n                } else {\n                    if (temp_node == p->left) split_region.r1 = min(split_region.r1, p_coord);\n                    else split_region.r0 = max(split_region.r0, p_coord);\n                }\n                temp_node = p;\n            }\n\n            int old_coord = split_coords[split_to_change];\n            int range_min, range_max;\n            if (target_node->is_vertical_split) {\n                range_min = split_region.c0 + 1; range_max = split_region.c1 - 1;\n            } else {\n                range_min = split_region.r0 + 1; range_max = split_region.r1 - 1;\n            }\n            if (range_min >= range_max) continue;\n\n            int move_range = max(1, (int)((range_max - range_min) * 0.1 * temp / 5000.0));\n            int new_coord = old_coord + rand_int(-move_range, move_range);\n            new_coord = clamp(new_coord, range_min, range_max);\n            \n            if (new_coord == old_coord) continue;\n\n            vector<Rect> new_subtree_rects(N);\n            vector<int> next_coords = split_coords;\n            next_coords[split_to_change] = new_coord;\n\n            std::function<void(Node*, Rect)> compute_subtree_rects = \n                [&](Node* node, Rect region) {\n                    if (node->is_leaf) {\n                        new_subtree_rects[node->k] = region;\n                        return;\n                    }\n                    int coord = next_coords[node->split_idx];\n                    Rect left_region, right_region;\n                    if (node->is_vertical_split) {\n                        left_region = {region.r0, region.c0, region.r1, coord};\n                        right_region = {region.r0, coord, region.r1, region.c1};\n                    } else {\n                        left_region = {region.r0, region.c0, coord, region.c1};\n                        right_region = {coord, region.c0, region.r1, region.c1};\n                    }\n                    compute_subtree_rects(node->left, left_region);\n                    compute_subtree_rects(node->right, right_region);\n            };\n            compute_subtree_rects(target_node, split_region);\n\n            long long area_cost_delta = 0;\n            for(int k=target_node->k_min; k<target_node->k_max; ++k) {\n                area_cost_delta -= 100 * max(0LL, a[d][k] - current_rects[k].area());\n                area_cost_delta += 100 * max(0LL, a[d][k] - new_subtree_rects[k].area());\n            }\n\n            long long partition_cost_delta = 0;\n            if (target_node->is_vertical_split) {\n                for (int i = split_region.r0; i < split_region.r1; ++i) {\n                    partition_cost_delta -= (v_prev_exists[i][old_coord] != (v_curr_count[i][old_coord] > 0));\n                    v_curr_count[i][old_coord]--;\n                    partition_cost_delta += (v_prev_exists[i][old_coord] != (v_curr_count[i][old_coord] > 0));\n                    partition_cost_delta -= (v_prev_exists[i][new_coord] != (v_curr_count[i][new_coord] > 0));\n                    v_curr_count[i][new_coord]++;\n                    partition_cost_delta += (v_prev_exists[i][new_coord] != (v_curr_count[i][new_coord] > 0));\n                }\n            } else {\n                for (int j = split_region.c0; j < split_region.c1; ++j) {\n                    partition_cost_delta -= (h_prev_exists[old_coord][j] != (h_curr_count[old_coord][j] > 0));\n                    h_curr_count[old_coord][j]--;\n                    partition_cost_delta += (h_prev_exists[old_coord][j] != (h_curr_count[old_coord][j] > 0));\n                    partition_cost_delta -= (h_prev_exists[new_coord][j] != (h_curr_count[new_coord][j] > 0));\n                    h_curr_count[new_coord][j]++;\n                    partition_cost_delta += (h_prev_exists[new_coord][j] != (h_curr_count[new_coord][j] > 0));\n                }\n            }\n\n            long long cost_delta = area_cost_delta + partition_cost_delta;\n\n            if (cost_delta < 0 || (temp > 1 && rand_double() < exp(-(double)cost_delta / temp))) {\n                current_total_cost += cost_delta;\n                split_coords[split_to_change] = new_coord;\n                for(int k=target_node->k_min; k<target_node->k_max; ++k) {\n                    current_rects[k] = new_subtree_rects[k];\n                }\n                \n                if (current_total_cost < best_total_cost) {\n                    best_total_cost = current_total_cost;\n                    best_coords = split_coords;\n                }\n            } else { // revert counts\n                if (target_node->is_vertical_split) {\n                    for (int i = split_region.r0; i < split_region.r1; ++i) {\n                        v_curr_count[i][old_coord]++; v_curr_count[i][new_coord]--;\n                    }\n                } else {\n                    for (int j = split_region.c0; j < split_region.c1; ++j) {\n                        h_curr_count[old_coord][j]++; h_curr_count[new_coord][j]--;\n                    }\n                }\n            }\n        }\n        \n        split_coords = best_coords;\n        get_rects_from_coords(root, {0, 0, W, W}, split_coords, current_rects);\n        solution[d] = current_rects;\n        populate_partition_counts(current_rects);\n        update_prev_partitions();\n    }\n\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            const auto& r = solution[d][k];\n            cout << r.r0 << \" \" << r.c0 << \" \" << r.r1 << \" \" << r.c1 << \"\\n\";\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <optional>\n#include <cmath>\n#include <array>\n#include <cstdint>\n\n// --- Constants ---\nconstexpr int N = 9;\nconstexpr int M = 20;\nconstexpr int K = 81;\nconstexpr long long P = 998244353;\nconstexpr int MAX_POS_COORD = N - 3;\n\n// --- Type Definitions ---\nusing Board = std::vector<std::vector<long long>>;\nusing Stamp = std::vector<std::vector<long long>>;\n\nstruct Operation {\n    int m, p, q;\n};\n\n// --- Global Variables ---\nstd::vector<Stamp> stamps(M, Stamp(3, std::vector<long long>(3)));\nBoard initial_board(N, std::vector<long long>(N));\n\n// --- Timer ---\nstd::chrono::steady_clock::time_point start_time;\n\n// --- Fast Random Number Generator (xoshiro256**) ---\nstruct Xoshiro256StarStar {\n    uint64_t s[4];\n    static inline uint64_t rotl(const uint64_t x, int k) { return (x << k) | (x >> (64 - k)); }\n    void seed(uint64_t seed) { for(int i = 0; i < 4; ++i) { uint64_t z = seed + 0x9e3779b97f4a7c15 * (i + 1); z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; z = (z ^ (z >> 27)) * 0x94d049bb133111eb; s[i] = z ^ (z >> 31); } }\n    uint64_t next() { const uint64_t result = rotl(s[1] * 5, 7) * 9; const uint64_t t = s[1] << 17; s[2] ^= s[0]; s[3] ^= s[1]; s[1] ^= s[2]; s[0] ^= s[3]; s[2] ^= t; s[3] = rotl(s[3], 45); return result; }\n    int next_int(int min, int max) { if (min > max) return min; return min + next() % (uint64_t)(max - min + 1); }\n    double next_double() { return (next() >> 11) * (1.0 / 9007199254740992.0); }\n};\nXoshiro256StarStar fast_rng;\n\n// --- Utility Functions ---\nlong long current_time_ms() { return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count(); }\nlong long positive_modulo(long long i, long long n) { return (i % n + n) % n; }\nBoard apply_operations(const std::vector<Operation>& ops) { Board b = initial_board; for (const auto& op : ops) for (int i = 0; i < 3; ++i) for (int j = 0; j < 3; ++j) b[op.p + i][op.q + j] += stamps[op.m][i][j]; return b; }\nlong long calculate_score(const Board& board) { long long s = 0; for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) s += positive_modulo(board[i][j], P); return s; }\n\n// --- Fast Greedy Algorithm ---\nstd::vector<Operation> fast_greedy_solution() {\n    std::vector<Operation> ops;\n    Board current_board = initial_board;\n    for (int k = 0; k < K; ++k) {\n        long long best_delta_score = 0;\n        std::optional<Operation> best_op;\n        for (int m = 0; m < M; ++m) {\n            for (int p = 0; p <= MAX_POS_COORD; ++p) {\n                for (int q = 0; q <= MAX_POS_COORD; ++q) {\n                    long long current_delta_score = 0;\n                    for (int i=0; i<3; ++i) for (int j=0; j<3; ++j) {\n                        long long old_v = current_board[p+i][q+j];\n                        long long new_v = old_v + stamps[m][i][j];\n                        current_delta_score += positive_modulo(new_v, P) - positive_modulo(old_v, P);\n                    }\n                    if (current_delta_score > best_delta_score) { best_delta_score = current_delta_score; best_op = {m,p,q}; }\n                }\n            }\n        }\n        if (best_op) { ops.push_back(*best_op); for (int i=0; i<3; ++i) for (int j=0; j<3; ++j) current_board[best_op->p+i][best_op->q+j] += stamps[best_op->m][i][j]; }\n        else break;\n    }\n    return ops;\n}\n\n// --- Simulated Annealing ---\nvoid simulated_annealing(std::vector<Operation>& solution) {\n    long long time_limit = 1980;\n    Board current_board = apply_operations(solution);\n    long long current_score = calculate_score(current_board);\n    \n    std::vector<Operation> best_solution = solution;\n    long long best_score = current_score;\n    Board best_board = current_board;\n\n    double start_temp = 1e10, end_temp = 1;\n    std::array<long long, N*N> deltas{};\n    std::vector<int> dirty_keys; dirty_keys.reserve(18);\n\n    long long iter_count = 0;\n    long long last_best_update = 0;\n    const long long PATIENCE = 75000;\n\n    while (true) {\n        long long elapsed_time = current_time_ms();\n        if (elapsed_time >= time_limit) break;\n        iter_count++;\n\n        if (iter_count - last_best_update > PATIENCE) {\n            solution = best_solution;\n            current_board = best_board;\n            current_score = best_score;\n            last_best_update = iter_count;\n        }\n\n        double progress = (double)elapsed_time / time_limit;\n        double temp = start_temp * std::pow(end_temp / start_temp, progress);\n        \n        int r = fast_rng.next_int(0, 99), move_type;\n        int op_count = solution.size();\n\n        if (op_count == K) { if (r < 85) move_type = 0; else move_type = 2; }\n        else if (op_count == 0) { move_type = 1; }\n        else { if (r < 80) move_type = 0; else if (r < 95) move_type = 1; else move_type = 2; }\n        \n        std::optional<Operation> old_op, new_op;\n        int op_idx = -1;\n\n        if (move_type == 0) {\n            op_idx = fast_rng.next_int(0, solution.size() - 1); old_op = solution[op_idx];\n            int change_r = fast_rng.next_int(0, 99);\n            if (change_r < 45) { // Jump position\n                Operation c=*old_op; do {c.p=fast_rng.next_int(0,MAX_POS_COORD);c.q=fast_rng.next_int(0,MAX_POS_COORD);} while(c.p==old_op->p&&c.q==old_op->q); new_op=c;\n            } else if (change_r < 90) { // Change stamp\n                Operation c=*old_op; do {c.m=fast_rng.next_int(0,M-1);} while(c.m==old_op->m); new_op=c;\n            } else { // Change both\n                Operation c; do {c.m=fast_rng.next_int(0,M-1);c.p=fast_rng.next_int(0,MAX_POS_COORD);c.q=fast_rng.next_int(0,MAX_POS_COORD);} while(c.m==old_op->m&&c.p==old_op->p&&c.q==old_op->q); new_op=c;\n            }\n        } else if (move_type == 1) { new_op = {fast_rng.next_int(0,M-1),fast_rng.next_int(0,MAX_POS_COORD),fast_rng.next_int(0,MAX_POS_COORD)}; }\n        else { op_idx = fast_rng.next_int(0, solution.size()-1); old_op = solution[op_idx]; }\n        \n        if(!new_op && !old_op) continue;\n        if(old_op){for(int i=0;i<3;++i)for(int j=0;j<3;++j){int k=(old_op->p+i)*N+old_op->q+j;if(deltas[k]==0)dirty_keys.push_back(k);deltas[k]-=stamps[old_op->m][i][j];}}\n        if(new_op){for(int i=0;i<3;++i)for(int j=0;j<3;++j){int k=(new_op->p+i)*N+new_op->q+j;if(deltas[k]==0)dirty_keys.push_back(k);deltas[k]+=stamps[new_op->m][i][j];}}\n        \n        long long delta_score=0; for(int k:dirty_keys){long long ov=current_board[k/N][k%N],nv=ov+deltas[k];delta_score+=positive_modulo(nv,P)-positive_modulo(ov,P);}\n        \n        if(delta_score > 0 || fast_rng.next_double() < std::exp((double)delta_score/temp)){\n            current_score+=delta_score; for(int k:dirty_keys)current_board[k/N][k%N]+=deltas[k];\n            if(move_type==0)solution[op_idx]=*new_op; else if(move_type==1)solution.push_back(*new_op); else solution.erase(solution.begin()+op_idx);\n            if(current_score > best_score){best_score=current_score; best_solution=solution; best_board=current_board; last_best_update=iter_count;}\n        }\n        for(int k:dirty_keys)deltas[k]=0; dirty_keys.clear();\n    }\n    solution = best_solution;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false); std::cin.tie(NULL);\n    start_time = std::chrono::steady_clock::now();\n    fast_rng.seed(std::chrono::duration_cast<std::chrono::nanoseconds>(start_time.time_since_epoch()).count());\n    \n    int n,m,k; std::cin>>n>>m>>k;\n    for(int i=0;i<N;++i)for(int j=0;j<N;++j)std::cin>>initial_board[i][j];\n    for(int i=0;i<M;++i)for(int r=0;r<3;++r)for(int c=0;c<3;++c)std::cin>>stamps[i][r][c];\n    \n    auto solution = fast_greedy_solution();\n    simulated_annealing(solution);\n\n    std::cout << solution.size() << '\\n';\n    for (const auto& op : solution) {\n        std::cout << op.m << \" \" << op.p << \" \" << op.q << '\\n';\n    }\n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <map>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nconst int N = 5;\nconst int MAX_TURNS = 10000;\n\nstruct Pos {\n    int r, c;\n    bool operator==(const Pos& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Pos& other) const {\n        return !(*this == other);\n    }\n    bool operator<(const Pos& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n};\n\nenum TaskType {\n    NONE,\n    MOVE_TO_PARK,\n    UNLOAD, // col 0 -> 1\n    SORT,   // col 1 -> 3\n    DISPATCH // col 3 -> 4\n};\n\nstruct Task {\n    TaskType type = NONE;\n    int container_id = -1;\n    Pos from;\n    Pos to;\n};\n\nstruct Crane {\n    int id;\n    Pos pos;\n    int payload = -1;\n    Task task;\n    bool bombed = false;\n};\n\n// Global state\nint grid[N][N];\nPos container_pos[N * N];\nCrane cranes[N];\nint arrival_idx[N];\nint dispatch_next[N];\nvector<string> history(N);\n\nvoid init_state() {\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            grid[i][j] = -1;\n        }\n    }\n    for (int i = 0; i < N * N; ++i) {\n        container_pos[i] = {-1, -1};\n    }\n    for (int i = 0; i < N; ++i) {\n        cranes[i].id = i;\n        cranes[i].pos = {i, 0};\n        arrival_idx[i] = 0;\n        dispatch_next[i] = N * i;\n    }\n}\n\nvoid apply_actions_to_state(const string& actions) {\n    // Phase 1: Pick up, Put down, Bomb\n    for (int i = 0; i < N; ++i) {\n        if (cranes[i].bombed) continue;\n        char act = actions[i];\n        if (act == 'P') {\n            cranes[i].payload = grid[cranes[i].pos.r][cranes[i].pos.c];\n            container_pos[grid[cranes[i].pos.r][cranes[i].pos.c]] = {-2,-2}; // on crane\n            grid[cranes[i].pos.r][cranes[i].pos.c] = -1;\n        } else if (act == 'Q') {\n            grid[cranes[i].pos.r][cranes[i].pos.c] = cranes[i].payload;\n            container_pos[cranes[i].payload] = cranes[i].pos;\n            cranes[i].payload = -1;\n        } else if (act == 'B') {\n            cranes[i].bombed = true;\n        }\n    }\n\n    // Phase 2: Move\n    for (int i = 0; i < N; ++i) {\n        if (cranes[i].bombed) continue;\n        char act = actions[i];\n        if (act == 'U') cranes[i].pos.r--;\n        else if (act == 'D') cranes[i].pos.r++;\n        else if (act == 'L') cranes[i].pos.c--;\n        else if (act == 'R') cranes[i].pos.c++;\n    }\n}\n\nPos get_next_pos(Pos current, char action) {\n    if (action == 'U') return {current.r - 1, current.c};\n    if (action == 'D') return {current.r + 1, current.c};\n    if (action == 'L') return {current.r, current.c - 1};\n    if (action == 'R') return {current.r, current.c + 1};\n    return current;\n}\n\nchar get_move_action(Pos from, Pos to) {\n    if (from.r < to.r) return 'D';\n    if (from.r > to.r) return 'U';\n    if (from.c < to.c) return 'R';\n    if (from.c > to.c) return 'L';\n    return '.';\n}\n\nchar find_path_and_get_first_move(Pos start, Pos end, const vector<vector<bool>>& obstacles) {\n    if (start == end) return '.';\n    \n    queue<Pos> q;\n    q.push(start);\n    map<Pos, Pos> parent;\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    visited[start.r][start.c] = true;\n\n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n    \n    bool found = false;\n    while (!q.empty()) {\n        Pos curr = q.front();\n        q.pop();\n\n        if (curr == end) {\n            found = true;\n            break;\n        }\n\n        for (int i = 0; i < 4; ++i) {\n            Pos next = {curr.r + dr[i], curr.c + dc[i]};\n            if (next.r >= 0 && next.r < N && next.c >= 0 && next.c < N && !visited[next.r][next.c] && !obstacles[next.r][next.c]) {\n                visited[next.r][next.c] = true;\n                parent[next] = curr;\n                q.push(next);\n            }\n        }\n    }\n\n    if (!found) return '.';\n\n    Pos curr = end;\n    while (parent.count(curr) && parent[curr] != start) {\n        curr = parent[curr];\n    }\n    return get_move_action(start, curr);\n}\n\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n_dummy;\n    cin >> n_dummy;\n    vector<vector<int>> A(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> A[i][j];\n        }\n    }\n\n    init_state();\n    int dispatched_count = 0;\n\n    for (int t = 0; t < MAX_TURNS; ++t) {\n        if (dispatched_count == N * N) break;\n\n        // 1. Containers arrive\n        for (int i = 0; i < N; ++i) {\n            bool gate_blocked_by_crane = false;\n            for(int k=0; k<N; ++k) {\n                if(!cranes[k].bombed && cranes[k].pos == Pos{i,0} && cranes[k].payload != -1) {\n                    gate_blocked_by_crane = true;\n                    break;\n                }\n            }\n            if (arrival_idx[i] < N && grid[i][0] == -1 && !gate_blocked_by_crane) {\n                int new_container = A[i][arrival_idx[i]];\n                grid[i][0] = new_container;\n                container_pos[new_container] = {i, 0};\n                arrival_idx[i]++;\n            }\n        }\n\n        // 2. Crane actions\n        string actions(N, '.');\n\n        if (t == 0) actions = \"RRRRR\";\n        else if (t == 1) actions = \".RRRR\";\n        else {\n            // Task assignment and invalidation\n            for (int i = 0; i < N; ++i) {\n                if (cranes[i].bombed) continue;\n                // Invalidate stale tasks\n                if (cranes[i].task.type != NONE) {\n                    if (cranes[i].payload == -1 && cranes[i].pos == cranes[i].task.from && grid[cranes[i].task.from.r][cranes[i].task.from.c] != cranes[i].task.container_id) cranes[i].task.type = NONE;\n                    if (cranes[i].task.type == MOVE_TO_PARK && cranes[i].pos == cranes[i].task.to) cranes[i].task.type = NONE;\n                    // THE BUG FIX: Only invalidate if container is DISPATCHED (r=-1), not just picked up (r=-2).\n                    if (cranes[i].task.container_id != -1 && container_pos[cranes[i].task.container_id].r == -1) cranes[i].task.type = NONE;\n                }\n                // Assign new tasks if idle\n                if (cranes[i].task.type == NONE) {\n                     if (i == 0) { // Large crane\n                        int c_to_dispatch = dispatch_next[0];\n                        if (c_to_dispatch < N && grid[0][N-1] == -1 && container_pos[c_to_dispatch] == Pos{0, 3}) { cranes[i].task = {DISPATCH, c_to_dispatch, {0, 3}, {0, N-1}};}\n                        if (cranes[i].task.type == NONE) { for (int r=0; r<N; ++r) if (grid[r][0] != -1 && grid[r][1] == -1) { cranes[i].task = {UNLOAD, grid[r][0], {r,0}, {r,1}}; break; }}\n                        if (cranes[i].task.type == NONE) { for (int r=0; r<N; ++r) if (grid[r][1] != -1) { int c = grid[r][1]; int dest_r = c / N; if (grid[dest_r][3] == -1) { cranes[i].task = {SORT, c, {r,1}, {dest_r,3}}; break; }}}\n                    } else { // Small cranes\n                        int c_to_dispatch = dispatch_next[i];\n                        if (c_to_dispatch < N*(i+1) && grid[i][N-1] == -1 && container_pos[c_to_dispatch] == Pos{i, 3}) { cranes[i].task = {DISPATCH, c_to_dispatch, {i, 3}, {i, N-1}}; }\n                        if (cranes[i].task.type == NONE && cranes[i].pos != Pos{i, 2}) { cranes[i].task = {MOVE_TO_PARK, -1, {}, {i,2}}; }\n                    }\n                }\n            }\n            \n            // Action Planning with BFS and collision avoidance\n            vector<Pos> future_pos(N); for(int i=0; i<N; ++i) future_pos[i] = cranes[i].pos;\n\n            for(int k=0; k<N; ++k) {\n                if (cranes[k].bombed) continue;\n                \n                Pos target_pos = {-1, -1};\n                char terminal_action = '.';\n                const auto& task = cranes[k].task;\n\n                if (task.type != NONE) {\n                    if (cranes[k].payload != -1) { target_pos = task.to; terminal_action = 'Q';} \n                    else {\n                        target_pos = task.from; terminal_action = 'P';\n                        if (task.type == MOVE_TO_PARK) { target_pos = task.to; terminal_action = '.'; }\n                    }\n                }\n\n                char planned_action;\n                if (target_pos.r == -1) planned_action = '.';\n                else if (cranes[k].pos == target_pos) {\n                    if (terminal_action == 'P' && grid[target_pos.r][target_pos.c] != task.container_id) planned_action = '.';\n                    else planned_action = terminal_action;\n                } else {\n                    vector<vector<bool>> obstacles(N, vector<bool>(N, false));\n                    for(int j=0; j<k; ++j) if (!cranes[j].bombed) obstacles[future_pos[j].r][future_pos[j].c] = true;\n                    for(int j=k+1; j<N; ++j) if (!cranes[j].bombed) obstacles[cranes[j].pos.r][cranes[j].pos.c] = true;\n                    if (cranes[k].payload != -1 && k > 0) {\n                        for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) if(grid[r][c]!=-1) obstacles[r][c] = true;\n                    }\n                    planned_action = find_path_and_get_first_move(cranes[k].pos, target_pos, obstacles);\n                }\n                \n                Pos planned_next_pos = get_next_pos(cranes[k].pos, planned_action);\n                bool is_swap = false;\n                for (int j = 0; j < k; ++j) {\n                    if (!cranes[j].bombed && planned_next_pos == cranes[j].pos && future_pos[j] == cranes[k].pos) {\n                        is_swap = true;\n                        break;\n                    }\n                }\n                \n                actions[k] = is_swap ? '.' : planned_action;\n                if (actions[k] == 'Q') cranes[k].task.type = NONE;\n                future_pos[k] = get_next_pos(cranes[k].pos, actions[k]);\n            }\n\n            for(int i=1; i<N; ++i){\n                if(!cranes[i].bombed && dispatch_next[i] >= N*(i+1) && cranes[i].payload == -1) {\n                    bool safe_to_bomb = true;\n                    for(int j=0; j<N; ++j) if (i!=j && !cranes[j].bombed && future_pos[j] == cranes[i].pos) { safe_to_bomb = false; break; }\n                    if (safe_to_bomb) actions[i] = 'B';\n                }\n            }\n        }\n        \n        for (int i = 0; i < N; ++i) history[i] += actions[i];\n        apply_actions_to_state(actions);\n        \n        // 3. Dispatch\n        for (int i = 0; i < N; ++i) {\n            if (grid[i][N - 1] != -1) {\n                int dispatched_container = grid[i][N - 1];\n                if (dispatched_container / N == i && dispatch_next[i] == dispatched_container) dispatch_next[i]++;\n                grid[i][N - 1] = -1;\n                container_pos[dispatched_container] = {-1, -1};\n                dispatched_count++;\n            }\n        }\n    }\n\n    size_t max_len = 0;\n    for(const auto& s : history) max_len = max(max_len, s.length());\n    if (max_len == 0) max_len = 1;\n    for (int i = 0; i < N; ++i) {\n        history[i].resize(max_len, '.');\n        cout << history[i] << endl;\n    }\n\n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <cmath>\n#include <map>\n#include <algorithm>\n#include <chrono>\n#include <random>\n\n#include <atcoder/mincostflow>\n\nusing namespace std;\n\n// --- Utilities ---\nstruct XorShift {\n    unsigned int x, y, z, w;\n    XorShift() : x(123456789), y(362436069), z(521288629), w(88675123) {}\n    unsigned int next() {\n        unsigned int t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));\n    }\n    int next_int(int upper) { return next() % upper; }\n    int next_int(int lower, int upper) { return lower + next() % (upper - lower + 1); }\n    double next_double() { return next() / 4294967295.0; }\n};\nXorShift rnd;\n\nauto start_time = chrono::steady_clock::now();\ndouble time_limit = 1.95;\n\nbool is_time_up() {\n    auto now = chrono::steady_clock::now();\n    double elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count() / 1000.0;\n    return elapsed > time_limit;\n}\n\n// --- Problem specific structures ---\nconst int N = 20;\nconst int SPLIT_THRESHOLD = 7;\n\nstruct Pos {\n    int r, c;\n};\n\nint manhattan_dist(const Pos& p1, const Pos& p2) {\n    return abs(p1.r - p2.r) + abs(p1.c - p2.c);\n}\n\nvector<Pos> sources, sinks;\nvector<int> source_supply, sink_demand;\n\nusing Plan = vector<vector<int>>;\nusing Stops = vector<pair<int, int>>;\n\nstruct TripResult {\n    long long cost = 0;\n    Pos end_pos;\n    vector<string> ops;\n};\n\n// --- Core Logic ---\n\nvoid optimize_tour(const Pos& start_pos, Stops& tour) {\n    if (tour.size() <= 2) return;\n\n    auto get_tour_dist = [&](const Stops& current_tour) {\n        long long d = 0;\n        Pos current_pos = start_pos;\n        for (const auto& stop : current_tour) {\n            d += manhattan_dist(current_pos, sinks[stop.first]);\n            current_pos = sinks[stop.first];\n        }\n        return d;\n    };\n    \n    int max_iter = min(400, (int)tour.size() * (int)tour.size() * 2);\n\n    for (int iter = 0; iter < max_iter; ++iter) {\n        int i = rnd.next_int(tour.size());\n        int j = rnd.next_int(tour.size());\n        if (i == j) continue;\n        if (i > j) swap(i, j);\n\n        Stops next_tour = tour;\n        reverse(next_tour.begin() + i, next_tour.begin() + j + 1);\n\n        if (get_tour_dist(next_tour) < get_tour_dist(tour)) {\n            tour = next_tour;\n        }\n    }\n}\n\nTripResult calculate_trip(Pos truck_pos, int s_idx, const Stops& stops, bool generate_ops) {\n    TripResult res;\n    res.end_pos = truck_pos;\n    if (stops.empty()) return res;\n\n    Pos s_pos = sources[s_idx];\n    res.cost += (long long)manhattan_dist(truck_pos, s_pos) * 100;\n    if (generate_ops) {\n        int dr = s_pos.r - truck_pos.r;\n        int dc = s_pos.c - truck_pos.c;\n        if (dr > 0) for(int i=0; i<dr; ++i) res.ops.push_back(\"D\");\n        if (dr < 0) for(int i=0; i<-dr; ++i) res.ops.push_back(\"U\");\n        if (dc > 0) for(int i=0; i<dc; ++i) res.ops.push_back(\"R\");\n        if (dc < 0) for(int i=0; i<-dc; ++i) res.ops.push_back(\"L\");\n    }\n    truck_pos = s_pos;\n\n    int total_load = 0;\n    for (const auto& stop : stops) total_load += stop.second;\n    res.cost += total_load;\n    if (generate_ops && total_load > 0) {\n        res.ops.push_back(\"+\" + to_string(total_load));\n    }\n    \n    Stops tour;\n    Stops remaining_stops = stops;\n    Pos nn_builder_pos = truck_pos;\n    while (!remaining_stops.empty()) {\n        auto best_it = remaining_stops.end();\n        int min_dist_t = 1e9;\n        for (auto it = remaining_stops.begin(); it != remaining_stops.end(); ++it) {\n            int d = manhattan_dist(nn_builder_pos, sinks[it->first]);\n            if (d < min_dist_t) {\n                min_dist_t = d;\n                best_it = it;\n            }\n        }\n        tour.push_back(*best_it);\n        nn_builder_pos = sinks[best_it->first];\n        remaining_stops.erase(best_it);\n    }\n    \n    optimize_tour(truck_pos, tour);\n\n    int truck_load = total_load;\n    for (const auto& stop : tour) {\n        Pos t_pos = sinks[stop.first];\n        res.cost += (long long)manhattan_dist(truck_pos, t_pos) * (100 + truck_load);\n        if (generate_ops) {\n            int dr = t_pos.r - truck_pos.r;\n            int dc = t_pos.c - truck_pos.c;\n            if (dr > 0) for(int i=0; i<dr; ++i) res.ops.push_back(\"D\");\n            if (dr < 0) for(int i=0; i<-dr; ++i) res.ops.push_back(\"U\");\n            if (dc > 0) for(int i=0; i<dc; ++i) res.ops.push_back(\"R\");\n            if (dc < 0) for(int i=0; i<-dc; ++i) res.ops.push_back(\"L\");\n            res.ops.push_back(\"-\" + to_string(stop.second));\n        }\n        res.cost += stop.second;\n        truck_load -= stop.second;\n        truck_pos = t_pos;\n    }\n    res.end_pos = truck_pos;\n    return res;\n}\n\nvector<Stops> split_stops(const Stops& stops) {\n    if (stops.size() < 2) return {stops};\n    \n    int s1 = -1, s2 = -1;\n    int max_d = -1;\n    for(size_t i=0; i<stops.size(); ++i) {\n        for(size_t j=i+1; j<stops.size(); ++j) {\n            int d = manhattan_dist(sinks[stops[i].first], sinks[stops[j].first]);\n            if (d > max_d) {\n                max_d = d;\n                s1 = stops[i].first;\n                s2 = stops[j].first;\n            }\n        }\n    }\n    \n    Stops c1, c2;\n    for(const auto& stop : stops) {\n        if (manhattan_dist(sinks[stop.first], sinks[s1]) < manhattan_dist(sinks[stop.first], sinks[s2])) {\n            c1.push_back(stop);\n        } else {\n            c2.push_back(stop);\n        }\n    }\n    if (c1.empty() || c2.empty()) return {stops};\n    return {c1, c2};\n}\n\nlong long evaluate(const Plan& plan, vector<string>* ops = nullptr) {\n    bool generate_ops = (ops != nullptr);\n    if (generate_ops) ops->clear();\n    \n    long long total_cost = 0;\n    Pos current_pos = {0, 0};\n\n    map<int, Stops> deliveries_by_source;\n    vector<int> active_sources_indices;\n    for (size_t s_idx = 0; s_idx < sources.size(); ++s_idx) {\n        bool has_delivery = false;\n        for (size_t t_idx = 0; t_idx < sinks.size(); ++t_idx) {\n            if (plan[s_idx][t_idx] > 0) {\n                deliveries_by_source[s_idx].push_back({(int)t_idx, plan[s_idx][t_idx]});\n                has_delivery = true;\n            }\n        }\n        if (has_delivery) {\n            active_sources_indices.push_back(s_idx);\n        }\n    }\n    \n    while (!active_sources_indices.empty()) {\n        int best_s_idx = -1;\n        int min_dist = 1e9;\n        size_t best_vec_idx = -1;\n        for (size_t i = 0; i < active_sources_indices.size(); ++i) {\n            int s_idx = active_sources_indices[i];\n            int d = manhattan_dist(current_pos, sources[s_idx]);\n            if (d < min_dist) {\n                min_dist = d;\n                best_s_idx = s_idx;\n                best_vec_idx = i;\n            }\n        }\n        \n        const auto& all_stops = deliveries_by_source.at(best_s_idx);\n        \n        bool do_split = false;\n        if (all_stops.size() >= SPLIT_THRESHOLD) {\n            auto clusters = split_stops(all_stops);\n            if (clusters.size() == 2) {\n                long long cost_single = calculate_trip(current_pos, best_s_idx, all_stops, false).cost;\n                TripResult trip1_res = calculate_trip(current_pos, best_s_idx, clusters[0], false);\n                TripResult trip2_res = calculate_trip(trip1_res.end_pos, best_s_idx, clusters[1], false);\n                if (trip1_res.cost + trip2_res.cost < cost_single) {\n                    do_split = true;\n                }\n            }\n        }\n\n        if (do_split) {\n            auto clusters = split_stops(all_stops);\n            TripResult trip1_res = calculate_trip(current_pos, best_s_idx, clusters[0], generate_ops);\n            total_cost += trip1_res.cost;\n            if (generate_ops) ops->insert(ops->end(), trip1_res.ops.begin(), trip1_res.ops.end());\n            current_pos = trip1_res.end_pos;\n\n            TripResult trip2_res = calculate_trip(current_pos, best_s_idx, clusters[1], generate_ops);\n            total_cost += trip2_res.cost;\n            if (generate_ops) ops->insert(ops->end(), trip2_res.ops.begin(), trip2_res.ops.end());\n            current_pos = trip2_res.end_pos;\n        } else {\n            TripResult trip_res = calculate_trip(current_pos, best_s_idx, all_stops, generate_ops);\n            total_cost += trip_res.cost;\n            if (generate_ops) ops->insert(ops->end(), trip_res.ops.begin(), trip_res.ops.end());\n            current_pos = trip_res.end_pos;\n        }\n\n        active_sources_indices.erase(active_sources_indices.begin() + best_vec_idx);\n    }\n    return total_cost;\n}\n\nvoid solve() {\n    vector<vector<int>> h(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> h[i][j];\n            if (h[i][j] > 0) {\n                sources.push_back({i, j});\n                source_supply.push_back(h[i][j]);\n            } else if (h[i][j] < 0) {\n                sinks.push_back({i, j});\n                sink_demand.push_back(-h[i][j]);\n            }\n        }\n    }\n    \n    if (sources.empty()) return;\n\n    int num_s = sources.size();\n    int num_t = sinks.size();\n    atcoder::mcf_graph<int, int> g(num_s + num_t + 2);\n    int S_node = num_s + num_t;\n    int T_node = S_node + 1;\n\n    long long total_supply_val = 0;\n    for (int i = 0; i < num_s; ++i) {\n        g.add_edge(S_node, i, source_supply[i], 0);\n        total_supply_val += source_supply[i];\n    }\n    for (int i = 0; i < num_t; ++i) {\n        g.add_edge(num_s + i, T_node, sink_demand[i], 0);\n    }\n    for (int i = 0; i < num_s; ++i) {\n        for (int j = 0; j < num_t; ++j) {\n            g.add_edge(i, num_s + j, 1e9, manhattan_dist(sources[i], sinks[j]));\n        }\n    }\n    \n    g.flow(S_node, T_node, total_supply_val);\n    \n    Plan current_plan(num_s, vector<int>(num_t, 0));\n    for (const auto& e : g.edges()) {\n        if (e.from >= 0 && e.from < num_s && e.to >= num_s && e.to < num_s + num_t) {\n            if (e.flow > 0) {\n                current_plan[e.from][e.to-num_s] = e.flow;\n            }\n        }\n    }\n\n    Plan best_plan = current_plan;\n    long long best_cost = evaluate(best_plan);\n    long long current_cost = best_cost;\n    \n    double start_temp = 5000, end_temp = 10;\n    \n    while (!is_time_up()) {\n        double elapsed_ratio = chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count() / 1000.0 / time_limit;\n        double temp = start_temp * pow(end_temp / start_temp, elapsed_ratio);\n\n        int s1 = rnd.next_int(num_s);\n        int s2 = rnd.next_int(num_s);\n        int t1 = rnd.next_int(num_t);\n        int t2 = rnd.next_int(num_t);\n\n        if (s1 == s2 || t1 == t2) continue;\n        \n        int amount1 = current_plan[s1][t1];\n        int amount2 = current_plan[s2][t2];\n        if (amount1 == 0 || amount2 == 0) continue;\n        \n        int d = rnd.next_int(1, min(amount1, amount2));\n        \n        Plan new_plan = current_plan;\n        new_plan[s1][t1] -= d;\n        new_plan[s2][t2] -= d;\n        new_plan[s1][t2] += d;\n        new_plan[s2][t1] += d;\n\n        long long new_cost = evaluate(new_plan);\n        \n        if (new_cost < current_cost || rnd.next_double() < exp((double)(current_cost - new_cost) / temp)) {\n            current_plan = new_plan;\n            current_cost = new_cost;\n            if (current_cost < best_cost) {\n                best_cost = current_cost;\n                best_plan = current_plan;\n            }\n        }\n    }\n    \n    vector<string> ops;\n    evaluate(best_plan, &ops);\n    for (const auto& op : ops) {\n        cout << op << '\\n';\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    int N_dummy;\n    cin >> N_dummy;\n    solve();\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n#include <random>\n#include <unordered_set>\n\n// --- Constants ---\nconstexpr int N = 6;\nconstexpr int M = 15;\nconstexpr int T = 10;\nconstexpr int SEED_COUNT = 2 * N * (N - 1); // 60\nconstexpr int GRID_SIZE = N * N;             // 36\nconstexpr long long TIME_LIMIT_MS = 190;\nconstexpr int TOP_K_SELECTION = 3; // Consider top K seeds for each criterion\n\n// --- Type Definitions ---\nstruct Seed {\n    int id;\n    std::vector<int> x;\n    int total_value;\n};\n\n// --- Global State ---\nstd::vector<Seed> current_seeds;\nstd::mt19937 rng;\nauto turn_start_time = std::chrono::high_resolution_clock::now();\n\n// --- Helper Functions ---\nvoid read_seeds() {\n    current_seeds.assign(SEED_COUNT, Seed());\n    for (int i = 0; i < SEED_COUNT; ++i) {\n        current_seeds[i].id = i;\n        current_seeds[i].x.resize(M);\n        current_seeds[i].total_value = 0;\n        for (int j = 0; j < M; ++j) {\n            std::cin >> current_seeds[i].x[j];\n            current_seeds[i].total_value += current_seeds[i].x[j];\n        }\n    }\n}\n\n// --- Core Logic for a Single Turn ---\nvoid solve_turn() {\n    // 1. REFINED SEED SELECTION: \"Top-K\" strategy\n    // This strategy selects seeds based on how many times they appear in the\n    // top K for any criterion. This prioritizes seeds that are champions or\n    // strong contenders in one or more areas, increasing the chance of\n    // combining multiple high-value traits.\n    \n    std::vector<int> top_K_counts(SEED_COUNT, 0);\n    std::vector<std::pair<int, int>> ranked_seeds(SEED_COUNT);\n\n    for (int j = 0; j < M; ++j) {\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            ranked_seeds[i] = {current_seeds[i].x[j], i};\n        }\n        std::sort(ranked_seeds.rbegin(), ranked_seeds.rend());\n        \n        for (int k = 0; k < TOP_K_SELECTION; ++k) {\n            top_K_counts[ranked_seeds[k].second]++;\n        }\n    }\n\n    std::vector<int> all_indices(SEED_COUNT);\n    std::iota(all_indices.begin(), all_indices.end(), 0);\n\n    // Sort all seeds by their top-K appearance count, then by total value as a tie-breaker.\n    std::sort(all_indices.begin(), all_indices.end(), [&](int a, int b) {\n        if (top_K_counts[a] != top_K_counts[b]) {\n            return top_K_counts[a] > top_K_counts[b];\n        }\n        return current_seeds[a].total_value > current_seeds[b].total_value;\n    });\n\n    std::vector<int> seeds_to_plant_indices;\n    seeds_to_plant_indices.reserve(GRID_SIZE);\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        seeds_to_plant_indices.push_back(all_indices[i]);\n    }\n\n    // 2. PLACEMENT using SIMULATED ANNEALING\n    \n    // Pre-calculate desirability for all pairs of selected seeds.\n    std::vector<std::vector<double>> desirability_cache(GRID_SIZE, std::vector<double>(GRID_SIZE));\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = i; j < GRID_SIZE; ++j) {\n            int seed_idx1 = seeds_to_plant_indices[i];\n            int seed_idx2 = seeds_to_plant_indices[j];\n            double d = 0;\n            for (int k = 0; k < M; ++k) {\n                d += std::max(current_seeds[seed_idx1].x[k], current_seeds[seed_idx2].x[k]);\n            }\n            desirability_cache[i][j] = desirability_cache[j][i] = d;\n        }\n    }\n\n    // Initialize with a random placement.\n    std::vector<int> p_indices(GRID_SIZE);\n    std::iota(p_indices.begin(), p_indices.end(), 0);\n    std::shuffle(p_indices.begin(), p_indices.end(), rng);\n\n    std::vector<std::vector<int>> current_placement(N, std::vector<int>(N));\n    for(int i = 0; i < GRID_SIZE; ++i) {\n        current_placement[i/N][i%N] = p_indices[i];\n    }\n    \n    auto calculate_total_desirability = [&](const auto& placement) {\n        double total_d = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (i + 1 < N) total_d += desirability_cache[placement[i][j]][placement[i + 1][j]];\n                if (j + 1 < N) total_d += desirability_cache[placement[i][j]][placement[i][j + 1]];\n            }\n        }\n        return total_d;\n    };\n    \n    double current_desirability = calculate_total_desirability(current_placement);\n    auto best_placement = current_placement;\n    double best_desirability = current_desirability;\n    \n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n\n    // Fast delta calculation for a swap move.\n    auto calculate_delta = [&](int r1, int c1, int r2, int c2) {\n        double delta = 0;\n        int s1_idx = current_placement[r1][c1];\n        int s2_idx = current_placement[r2][c2];\n\n        for (int k=0; k<4; ++k) {\n            int nr = r1 + dr[k], nc = c1 + dc[k];\n            if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n            if (nr == r2 && nc == c2) continue;\n            int neighbor_idx = current_placement[nr][nc];\n            delta += desirability_cache[s2_idx][neighbor_idx] - desirability_cache[s1_idx][neighbor_idx];\n        }\n        for (int k=0; k<4; ++k) {\n            int nr = r2 + dr[k], nc = c2 + dc[k];\n            if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n            if (nr == r1 && nc == c1) continue;\n            int neighbor_idx = current_placement[nr][nc];\n            delta += desirability_cache[s1_idx][neighbor_idx] - desirability_cache[s2_idx][neighbor_idx];\n        }\n        return delta;\n    };\n\n    // Auto-tune starting temperature.\n    double T_start = 2000.0, T_end = 0.1;\n    double avg_bad_delta = 0;\n    int bad_move_count = 0;\n    std::uniform_int_distribution<> dis_pos(0, GRID_SIZE - 1);\n    for (int i = 0; i < 500; ++i) { // Increased samples for better tuning\n        int p1_idx = dis_pos(rng), p2_idx = dis_pos(rng);\n        if (p1_idx == p2_idx) continue;\n        double delta = calculate_delta(p1_idx / N, p1_idx % N, p2_idx / N, p2_idx % N);\n        if (delta < 0) {\n            avg_bad_delta += -delta;\n            bad_move_count++;\n        }\n    }\n    if (bad_move_count > 0) {\n        avg_bad_delta /= bad_move_count;\n        T_start = avg_bad_delta / log(2.0);\n    }\n\n    std::uniform_real_distribution<double> accept_dis(0.0, 1.0);\n    int iter_count = 0;\n    while (true) {\n        iter_count++;\n        if (iter_count % 1024 == 0) {\n            if (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - turn_start_time).count() > TIME_LIMIT_MS) break;\n        }\n\n        double progress = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - turn_start_time).count() / (double)TIME_LIMIT_MS;\n        if (progress >= 1.0) break;\n        double temp = T_start * std::pow(T_end / T_start, progress);\n\n        int p1_idx = dis_pos(rng), p2_idx = dis_pos(rng);\n        if (p1_idx == p2_idx) continue;\n\n        int r1 = p1_idx / N, c1 = p1_idx % N;\n        int r2 = p2_idx / N, c2 = p2_idx % N;\n        \n        double delta_desirability = calculate_delta(r1, c1, r2, c2);\n        \n        if (delta_desirability > 0 || (temp > 1e-9 && accept_dis(rng) < std::exp(delta_desirability / temp))) {\n            std::swap(current_placement[r1][c1], current_placement[r2][c2]);\n            current_desirability += delta_desirability;\n            if (current_desirability > best_desirability) {\n                best_desirability = current_desirability;\n                best_placement = current_placement;\n            }\n        }\n    }\n\n    // 3. OUTPUT the best placement found.\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int placement_idx = best_placement[i][j];\n            int seed_id_to_print = seeds_to_plant_indices[placement_idx];\n            std::cout << seed_id_to_print << (j == N - 1 ? \"\" : \" \");\n        }\n        std::cout << std::endl;\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    rng.seed(std::chrono::steady_clock::now().time_since_epoch().count());\n    \n    int n_in, m_in, t_in;\n    std::cin >> n_in >> m_in >> t_in;\n\n    read_seeds();\n\n    for (int t = 0; t < T; ++t) {\n        turn_start_time = std::chrono::high_resolution_clock::now();\n        solve_turn();\n        if (t < T - 1) {\n            read_seeds();\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <set>\n#include <map>\n#include <tuple>\n#include <chrono>\n\n#include <atcoder/mincostflow>\n\nusing namespace std;\n\n// --- Utilities ---\nstruct Timer {\n    chrono::steady_clock::time_point start_time;\n    Timer() {\n        start_time = chrono::steady_clock::now();\n    }\n    double get_elapsed_time() const {\n        auto end_time = chrono::steady_clock::now();\n        return chrono::duration_cast<chrono::duration<double>>(end_time - start_time).count();\n    }\n};\n\nstruct Point {\n    int r, c;\n    bool operator<(const Point& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n    bool operator==(const Point& other) const {\n        return r == other.r && c == other.c;\n    }\n};\n\nPoint operator+(const Point& a, const Point& b) { return {a.r + b.r, a.c + b.c}; }\nPoint operator-(const Point& a, const Point& b) { return {a.r - b.r, a.c - b.c}; }\nPoint operator*(const Point& p, int scalar) { return {p.r * scalar, p.c * scalar}; }\nint manhattan(const Point& a, const Point& b) { return abs(a.r - b.r) + abs(a.c - b.c); }\n\n// Global constants for directions\nconst Point DIRS[] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; // 0:U, 1:R, 2:D, 3:L\nconst char MOVE_CHARS[] = {'U', 'R', 'D', 'L'};\nconst Point REL_DIRS[] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; // 0:R, 1:D, 2:L, 3:U\n\nint N, M, V;\n\n// --- Arm Structure ---\nstruct Arm {\n    int v_count;\n    Point root_pos;\n    vector<int> parent;\n    vector<int> length;\n    vector<vector<int>> children;\n    vector<int> is_leaf;\n\n    vector<int> edge_dir;\n    vector<Point> abs_pos;\n    \n    vector<int> finger_indices;\n\n    Arm(int v, Point root, const vector<pair<int, int>>& edges) : v_count(v), root_pos(root) {\n        parent.assign(v, -1);\n        length.assign(v, 0);\n        children.assign(v, vector<int>());\n        edge_dir.assign(v, 0); // All edges point right initially\n        abs_pos.resize(v);\n        is_leaf.assign(v, 0);\n\n        for(int i = 1; i < v; ++i) {\n            parent[i] = edges[i-1].first;\n            length[i] = edges[i-1].second;\n            children[parent[i]].push_back(i);\n        }\n\n        for (int i = 0; i < v; ++i) {\n            if (children[i].empty()) {\n                is_leaf[i] = 1;\n                finger_indices.push_back(i);\n            }\n        }\n        update_abs_pos();\n    }\n\n    void update_abs_pos() {\n        abs_pos.resize(v_count);\n        abs_pos[0] = root_pos;\n        vector<int> q;\n        q.push_back(0);\n        int q_ptr = 0;\n        while(q_ptr < (int)q.size()){\n            int u = q[q_ptr++];\n            for(int v : children[u]){\n                Point rel = REL_DIRS[edge_dir[v]] * length[v];\n                abs_pos[v] = abs_pos[u] + rel;\n                q.push_back(v);\n            }\n        }\n    }\n    \n    void apply_command(const string& cmd) {\n        if (cmd[0] == 'U') root_pos.r--;\n        else if (cmd[0] == 'D') root_pos.r++;\n        else if (cmd[0] == 'L') root_pos.c--;\n        else if (cmd[0] == 'R') root_pos.c++;\n\n        for (int i = 1; i < v_count; ++i) {\n            if (cmd[i] == 'L') edge_dir[i] = (edge_dir[i] + 3) % 4;\n            else if (cmd[i] == 'R') edge_dir[i] = (edge_dir[i] + 1) % 4;\n        }\n        update_abs_pos();\n    }\n};\n\n// --- Game State ---\nstruct GameState {\n    Arm arm;\n    set<Point> sources_left;\n    set<Point> targets_to_fill;\n    map<int, Point> held_by_finger; // finger_idx -> original_source_pos\n    map<Point, Point> s_to_t_map;\n\n    GameState(Arm a, set<Point> s, set<Point> t, map<Point, Point> st_map)\n        : arm(a), sources_left(s), targets_to_fill(t), s_to_t_map(st_map) {}\n};\n\nstruct TargetConfig {\n    bool is_pickup;\n    Point root_pos;\n    vector<int> edge_dirs;\n    map<int, Point> finger_assignments;\n    double value = -1e18;\n};\n\n// --- Planning Functions ---\nTargetConfig find_best_config(const GameState& state, bool is_pickup, const Timer& timer, double time_limit) {\n    TargetConfig best_config;\n    best_config.is_pickup = is_pickup;\n\n    vector<int> available_fingers;\n    if (is_pickup) {\n        for (int f_idx : state.arm.finger_indices) {\n            if (state.held_by_finger.find(f_idx) == state.held_by_finger.end()) {\n                available_fingers.push_back(f_idx);\n            }\n        }\n        if (available_fingers.empty() || state.sources_left.empty()) return best_config;\n\n        const int K_ANCHORS = 30;\n        vector<Point> anchor_candidates;\n        if (state.sources_left.size() <= K_ANCHORS) {\n            anchor_candidates.assign(state.sources_left.begin(), state.sources_left.end());\n        } else {\n            vector<pair<int, Point>> sorted_sources;\n            sorted_sources.reserve(state.sources_left.size());\n            for (const auto& s : state.sources_left) {\n                sorted_sources.push_back({manhattan(state.arm.root_pos, s), s});\n            }\n            std::partial_sort(sorted_sources.begin(), sorted_sources.begin() + K_ANCHORS, sorted_sources.end());\n            anchor_candidates.reserve(K_ANCHORS);\n            for (int i = 0; i < K_ANCHORS; ++i) {\n                anchor_candidates.push_back(sorted_sources[i].second);\n            }\n        }\n\n        for (const Point& p_anchor : anchor_candidates) {\n            if (timer.get_elapsed_time() > time_limit) break;\n            for (int f_anchor_idx : available_fingers) {\n                if (state.arm.parent[f_anchor_idx] != 0) continue;\n                for (int dir = 0; dir < 4; ++dir) {\n                    Point root_rel = REL_DIRS[dir] * state.arm.length[f_anchor_idx];\n                    Point cand_root_pos = p_anchor - root_rel;\n\n                    map<int, Point> assignments;\n                    vector<int> cand_dirs(state.arm.v_count, 0);\n                    \n                    set<Point> remaining_sources = state.sources_left;\n                    \n                    int current_score = 0;\n\n                    for(int f_idx : available_fingers) {\n                        for(int f_dir = 0; f_dir < 4; ++f_dir) {\n                            Point f_rel = REL_DIRS[f_dir] * state.arm.length[f_idx];\n                            Point f_pos = cand_root_pos + f_rel;\n                            if (remaining_sources.count(f_pos)) {\n                                assignments[f_idx] = f_pos;\n                                cand_dirs[f_idx] = f_dir;\n                                remaining_sources.erase(f_pos);\n                                current_score++;\n                                break;\n                            }\n                        }\n                    }\n\n                    int dist_cost = manhattan(state.arm.root_pos, cand_root_pos);\n                    double value = current_score * 400.0 - dist_cost;\n\n                    if (value > best_config.value) {\n                        best_config.value = value;\n                        best_config.root_pos = cand_root_pos;\n                        best_config.edge_dirs = cand_dirs;\n                        best_config.finger_assignments = assignments;\n                    }\n                }\n            }\n        }\n    } else { // dropoff\n        map<int, Point> finger_to_dest;\n        for (const auto& [f_idx, s_pos] : state.held_by_finger) {\n            available_fingers.push_back(f_idx);\n            finger_to_dest[f_idx] = state.s_to_t_map.at(s_pos);\n        }\n        if (available_fingers.empty()) return best_config;\n        \n        for (int f_anchor_idx : available_fingers) {\n            if (timer.get_elapsed_time() > time_limit) break;\n            const Point& p_anchor = finger_to_dest.at(f_anchor_idx);\n            if (state.arm.parent[f_anchor_idx] != 0) continue;\n\n            for (int dir = 0; dir < 4; ++dir) {\n                Point root_rel = REL_DIRS[dir] * state.arm.length[f_anchor_idx];\n                Point cand_root_pos = p_anchor - root_rel;\n\n                vector<int> cand_dirs(state.arm.v_count, 0);\n                map<int, Point> assignments;\n                \n                int current_score = 0;\n                for(auto const& [f_idx, dest_pos] : finger_to_dest) {\n                    for (int f_dir = 0; f_dir < 4; ++f_dir) {\n                        Point f_rel = REL_DIRS[f_dir] * state.arm.length[f_idx];\n                        if (cand_root_pos + f_rel == dest_pos) {\n                            cand_dirs[f_idx] = f_dir;\n                            assignments[f_idx] = dest_pos;\n                            current_score++;\n                            break;\n                        }\n                    }\n                }\n\n                int dist_cost = manhattan(state.arm.root_pos, cand_root_pos);\n                double value = current_score * 400.0 - dist_cost;\n                if (value > best_config.value) {\n                    best_config.value = value;\n                    best_config.root_pos = cand_root_pos;\n                    best_config.edge_dirs = cand_dirs;\n                    best_config.finger_assignments = assignments;\n                }\n            }\n        }\n    }\n    return best_config;\n}\n\nstring get_next_command(const GameState& state, const TargetConfig& target) {\n    Arm current_arm = state.arm;\n    string command(2 * state.arm.v_count, '.');\n\n    bool is_at_target_config = (current_arm.root_pos == target.root_pos);\n    if (is_at_target_config) {\n        for (const auto& [f_idx, f_pos] : target.finger_assignments) {\n            if (current_arm.edge_dir[f_idx] != target.edge_dirs[f_idx]) {\n                is_at_target_config = false;\n                break;\n            }\n        }\n    }\n\n    if (is_at_target_config) {\n        for (auto const& [f_idx, _] : target.finger_assignments) {\n            command[current_arm.v_count + f_idx] = 'P';\n        }\n        return command;\n    }\n\n    char best_move_c = '.';\n    int min_dist = manhattan(current_arm.root_pos, target.root_pos);\n    Point next_root_pos = current_arm.root_pos;\n\n    if (min_dist > 0) {\n        for (int i = 0; i < 4; ++i) {\n            Point new_pos = current_arm.root_pos + DIRS[i];\n            if (new_pos.r >= 0 && new_pos.r < N && new_pos.c >= 0 && new_pos.c < N) {\n                if (manhattan(new_pos, target.root_pos) < min_dist) {\n                    min_dist = manhattan(new_pos, target.root_pos);\n                    best_move_c = MOVE_CHARS[i];\n                    next_root_pos = new_pos;\n                }\n            }\n        }\n    }\n    command[0] = best_move_c;\n\n    for (int i = 1; i < current_arm.v_count; ++i) {\n        if (current_arm.parent[i] != 0) continue;\n        if (target.finger_assignments.find(i) == target.finger_assignments.end()) continue;\n        \n        Point finger_target_abs = target.root_pos + (REL_DIRS[target.edge_dirs[i]] * current_arm.length[i]);\n\n        char best_rot_c = '.';\n        int best_rot_dist = manhattan(next_root_pos + (REL_DIRS[current_arm.edge_dir[i]] * current_arm.length[i]), finger_target_abs);\n        \n        int l_dir = (current_arm.edge_dir[i] + 3) % 4;\n        int l_dist = manhattan(next_root_pos + (REL_DIRS[l_dir] * current_arm.length[i]), finger_target_abs);\n        if (l_dist < best_rot_dist) {\n            best_rot_dist = l_dist;\n            best_rot_c = 'L';\n        }\n\n        int r_dir = (current_arm.edge_dir[i] + 1) % 4;\n        int r_dist = manhattan(next_root_pos + (REL_DIRS[r_dir] * current_arm.length[i]), finger_target_abs);\n        if (r_dist < best_rot_dist) {\n            best_rot_c = 'R';\n        }\n        command[i] = best_rot_c;\n    }\n    return command;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    Timer timer;\n    cin >> N >> M >> V;\n    set<Point> sources, targets;\n    for (int i = 0; i < N; ++i) {\n        string row; cin >> row;\n        for (int j = 0; j < N; ++j) if (row[j] == '1') sources.insert({i, j});\n    }\n    for (int i = 0; i < N; ++i) {\n        string row; cin >> row;\n        for (int j = 0; j < N; ++j) if (row[j] == '1') targets.insert({i, j});\n    }\n\n    // --- Arm Design ---\n    int v_to_use = V;\n    vector<pair<int, int>> edges;\n    int num_fingers = v_to_use > 1 ? v_to_use - 1 : 0;\n    if (num_fingers > 0) {\n        int L_small = 1;\n        int L_large = max(2, (int)round(N / 3.0));\n        int num_small = num_fingers / 2;\n        for (int i = 0; i < num_small; ++i) {\n            edges.push_back({0, L_small});\n        }\n        for (int i = 0; i < num_fingers - num_small; ++i) {\n            edges.push_back({0, L_large});\n        }\n    }\n    \n    long long sum_r = 0, sum_c = 0; for(const auto& p : sources) { sum_r += p.r; sum_c += p.c; }\n    Point initial_root = {(int)round((double)sum_r/M), (int)round((double)sum_c/M)};\n    \n    cout << v_to_use << endl;\n    for (const auto& edge : edges) cout << edge.first << \" \" << edge.second << endl;\n    cout << initial_root.r << \" \" << initial_root.c << endl;\n\n    // --- Initial Planning (Matching) ---\n    map<Point, Point> s_to_t_map;\n    vector<Point> s_vec(sources.begin(), sources.end());\n    vector<Point> t_vec(targets.begin(), targets.end());\n    atcoder::mcf_graph<int, int> g(2 * M + 2);\n    int S_node = 2 * M, T_node = 2 * M + 1;\n    for (int i = 0; i < M; ++i) {\n        g.add_edge(S_node, i, 1, 0);\n        g.add_edge(M + i, T_node, 1, 0);\n        for (int j = 0; j < M; ++j) g.add_edge(i, M + j, 1, manhattan(s_vec[i], t_vec[j]));\n    }\n    g.flow(S_node, T_node, M);\n    for (auto e : g.edges()) {\n        if (e.from < M && e.to >= M && e.to < 2*M && e.flow > 0) s_to_t_map[s_vec[e.from]] = t_vec[e.to - M];\n    }\n\n    // --- Main Loop ---\n    Arm arm(v_to_use, initial_root, edges);\n    GameState state(arm, sources, targets, s_to_t_map);\n    \n    TargetConfig current_target;\n    int plan_life = 0;\n    const double TIME_LIMIT = 2.90;\n\n    int max_turns = 100000;\n    for (int turn = 0; turn < max_turns; ++turn) {\n        if (state.targets_to_fill.empty() || timer.get_elapsed_time() > TIME_LIMIT) break;\n\n        if (plan_life <= 0) {\n            TargetConfig pickup_config = find_best_config(state, true, timer, TIME_LIMIT);\n            TargetConfig dropoff_config = find_best_config(state, false, timer, TIME_LIMIT);\n\n            if (pickup_config.value > -1e17 || dropoff_config.value > -1e17) {\n                 if (pickup_config.value >= dropoff_config.value) current_target = pickup_config;\n                 else current_target = dropoff_config;\n                 plan_life = manhattan(state.arm.root_pos, current_target.root_pos) + 5;\n            } else { \n                string cmd(2 * v_to_use, '.'); cout << cmd << endl; continue;\n            }\n        }\n        \n        string command = get_next_command(state, current_target);\n        cout << command << endl;\n\n        state.arm.apply_command(command);\n        \n        bool action_taken = false;\n        for (int i = 0; i < v_to_use; ++i) {\n            if (command[v_to_use + i] == 'P') {\n                action_taken = true;\n                if (current_target.is_pickup) {\n                    Point s_pos = state.arm.abs_pos[i];\n                    state.sources_left.erase(s_pos);\n                    state.held_by_finger[i] = s_pos;\n                } else {\n                    Point s_pos = state.held_by_finger.at(i);\n                    state.targets_to_fill.erase(state.s_to_t_map.at(s_pos));\n                    state.held_by_finger.erase(i);\n                }\n            }\n        }\n        if(action_taken) plan_life = 0; else plan_life--;\n\n    }\n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n#include <random>\n#include <set>\n#include <map>\n#include <queue>\n\n// --- Utilities ---\nstruct Point {\n    int x, y;\n    bool operator<(const Point& other) const {\n        if (x != other.x) return x < other.x;\n        return y < other.y;\n    }\n     bool operator==(const Point& other) const {\n        return x == other.x && y == other.y;\n    }\n};\n\nlong long cross_product(Point a, Point b, Point c) {\n    return (long long)(b.x - a.x) * (c.y - a.y) - (long long)(b.y - a.y) * (c.x - a.x);\n}\n\n// Global timer\nstd::chrono::high_resolution_clock::time_point start_time;\n\n// --- Polygon Utilities ---\nstruct Polygon {\n    std::vector<Point> vertices;\n\n    bool is_inside(Point p) const {\n        if (vertices.empty()) return false;\n        int n = vertices.size();\n        bool inside = false;\n        for (int i = 0; i < n; ++i) {\n            const Point& p1 = vertices[i];\n            const Point& p2 = vertices[(i + 1) % n];\n            \n            if (p1.y == p2.y && p.y == p1.y && p.x >= std::min(p1.x, p2.x) && p.x <= std::max(p1.x, p2.x)) {\n                return true;\n            }\n            if (p1.x == p2.x && p.x == p1.x && p.y >= std::min(p1.y, p2.y) && p.y <= std::max(p1.y, p2.y)) {\n                return true;\n            }\n\n            if ((p1.y > p.y) != (p2.y > p.y)) {\n                double intersect_x = (double)(p2.x - p1.x) * (p.y - p1.y) / (double)(p2.y - p1.y) + p1.x;\n                if (p.x < intersect_x) {\n                    inside = !inside;\n                }\n            }\n        }\n        return inside;\n    }\n\n    long long calculate_perimeter() const {\n        if (vertices.size() < 2) return 0;\n        long long p = 0;\n        for (size_t i = 0; i < vertices.size(); ++i) {\n            const auto& v1 = vertices[i];\n            const auto& v2 = vertices[(i + 1) % vertices.size()];\n            p += std::abs(v1.x - v2.x) + std::abs(v1.y - v2.y);\n        }\n        return p;\n    }\n};\n\n// --- Problem Data ---\nint N;\nstd::vector<Point> mackerels;\nstd::vector<Point> sardines;\n\n// --- Main Algorithm ---\n\nusing GridPoint = std::pair<int, int>;\nconst int DX[] = {0, 1, 0, -1};\nconst int DY[] = {1, 0, -1, 0};\n\nPolygon generate_polygon_from_cells(const std::set<GridPoint>& cells, int cell_size) {\n    if (cells.empty()) return Polygon{};\n\n    std::map<Point, std::vector<Point>> adj;\n    for (const auto& cell : cells) {\n        int gx = cell.first;\n        int gy = cell.second;\n        Point p00 = {gx * cell_size, gy * cell_size};\n        Point p10 = {(gx + 1) * cell_size, gy * cell_size};\n        Point p01 = {gx * cell_size, (gy + 1) * cell_size};\n        Point p11 = {(gx + 1) * cell_size, (gy + 1) * cell_size};\n\n        if (cells.find({gx, gy + 1}) == cells.end()) { adj[p01].push_back(p11); adj[p11].push_back(p01); }\n        if (cells.find({gx, gy - 1}) == cells.end()) { adj[p10].push_back(p00); adj[p00].push_back(p10); }\n        if (cells.find({gx + 1, gy}) == cells.end()) { adj[p11].push_back(p10); adj[p10].push_back(p11); }\n        if (cells.find({gx - 1, gy}) == cells.end()) { adj[p00].push_back(p01); adj[p01].push_back(p00); }\n    }\n\n    if (adj.empty()) return Polygon{};\n\n    Point start_node = adj.begin()->first;\n     for(const auto& [p, _] : adj) {\n        if (p.y < start_node.y || (p.y == start_node.y && p.x < start_node.x)) {\n            start_node = p;\n        }\n    }\n\n    std::vector<Point> vertices;\n    Point current_node = start_node;\n    Point prev_node = {start_node.x, start_node.y - 1};\n\n    for (size_t i = 0; i < 2 * adj.size() + 5; ++i) {\n        vertices.push_back(current_node);\n        auto& neighbors = adj.at(current_node);\n\n        Point next_node = {-1, -1};\n        bool found_next = false;\n        long long min_cp = 5e18; // Large value\n\n        for(const auto& neighbor : neighbors){\n            if(neighbor == prev_node) continue;\n            long long cp = cross_product(prev_node, current_node, neighbor);\n            if (!found_next || cp < min_cp) {\n                min_cp = cp;\n                next_node = neighbor;\n                found_next = true;\n            }\n        }\n        \n        if (!found_next) { return Polygon{}; }\n        \n        prev_node = current_node;\n        current_node = next_node;\n        if (current_node == start_node) break;\n    }\n    \n    if (vertices.size() > 2) {\n        std::vector<Point> simplified;\n        for (size_t i = 0; i < vertices.size(); ++i) {\n            Point current_vertex = vertices[i];\n            if (simplified.size() < 2) {\n                simplified.push_back(current_vertex);\n            } else {\n                Point p_prev = simplified[simplified.size() - 2];\n                Point p_mid = simplified.back();\n                if (cross_product(p_prev, p_mid, current_vertex) == 0) {\n                    simplified.back() = current_vertex;\n                } else {\n                    simplified.push_back(current_vertex);\n                }\n            }\n        }\n        while (simplified.size() >= 3) {\n            Point p_prev = simplified[simplified.size() - 2];\n            Point p_mid = simplified.back();\n            Point p_curr = simplified.front();\n            if (cross_product(p_prev, p_mid, p_curr) == 0) {\n                simplified.pop_back();\n            } else {\n                break;\n            }\n        }\n         while (simplified.size() >= 3) {\n            Point p_prev = simplified.back();\n            Point p_mid = simplified.front();\n            Point p_curr = simplified[1];\n            if (cross_product(p_prev, p_mid, p_curr) == 0) {\n                simplified.front() = simplified.back();\n                simplified.pop_back();\n            } else {\n                break;\n            }\n        }\n        vertices = simplified;\n    }\n    return Polygon{vertices};\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    start_time = std::chrono::high_resolution_clock::now();\n\n    std::cin >> N;\n    mackerels.resize(N);\n    sardines.resize(N);\n    for (int i = 0; i < N; ++i) std::cin >> mackerels[i].x >> mackerels[i].y;\n    for (int i = 0; i < N; ++i) std::cin >> sardines[i].x >> sardines[i].y;\n    \n    int best_a = 0, best_b = 0;\n    Polygon best_polygon;\n    \n    std::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n    std::vector<int> cell_sizes = {1000, 500, 250, 200};\n    \n    for (size_t grid_idx = 0; grid_idx < cell_sizes.size(); ++grid_idx) {\n        int cell_size = cell_sizes[grid_idx];\n        long long time_limit_ms = 1950 * (grid_idx + 1) / cell_sizes.size();\n        \n        int grid_dim_x = 100001 / cell_size + 2;\n        int grid_dim_y = 100001 / cell_size + 2;\n        std::vector<std::vector<int>> grid_scores(grid_dim_x, std::vector<int>(grid_dim_y, 0));\n\n        for (const auto& p : mackerels) grid_scores[p.x / cell_size][p.y / cell_size]++;\n        for (const auto& s : sardines) grid_scores[s.x / cell_size][s.y / cell_size]--;\n        \n        std::vector<GridPoint> positive_cells;\n        for (int gx = 0; gx < grid_dim_x; ++gx) {\n            for (int gy = 0; gy < grid_dim_y; ++gy) {\n                if (grid_scores[gx][gy] > 0) {\n                    positive_cells.push_back({gx, gy});\n                }\n            }\n        }\n        std::sort(positive_cells.begin(), positive_cells.end(), [&](const GridPoint& a, const GridPoint& b){\n            return grid_scores[a.first][a.second] > grid_scores[b.first][b.second];\n        });\n\n        std::vector<std::vector<bool>> visited(grid_dim_x, std::vector<bool>(grid_dim_y, false));\n        int components_processed = 0;\n        \n        for (const auto& start_cell : positive_cells) {\n            if (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start_time).count() > time_limit_ms) break;\n            if (components_processed > 20) break;\n\n            int gx = start_cell.first;\n            int gy = start_cell.second;\n\n            if (!visited[gx][gy]) {\n                components_processed++;\n                std::set<GridPoint> component_cells;\n                std::queue<GridPoint> q;\n\n                q.push({gx, gy});\n                visited[gx][gy] = true;\n                long long initial_comp_score = 0;\n                while (!q.empty()) {\n                    GridPoint curr = q.front(); q.pop();\n                    component_cells.insert(curr);\n                    initial_comp_score += grid_scores[curr.first][curr.second];\n                    for (int i = 0; i < 4; ++i) {\n                        GridPoint next = {curr.first + DX[i], curr.second + DY[i]};\n                        if (next.first >= 0 && next.first < grid_dim_x && next.second >= 0 && next.second < grid_dim_y &&\n                            !visited[next.first][next.second] && grid_scores[next.first][next.second] > 0) {\n                            visited[next.first][next.second] = true;\n                            q.push(next);\n                        }\n                    }\n                }\n                if (component_cells.empty()) continue;\n\n                std::set<GridPoint> current_cells = component_cells;\n                \n                double T_start = std::max(1.0, (double)initial_comp_score / 5.0);\n                double T_end = 0.01;\n                double T = T_start;\n                \n                int max_iter = 8000;\n                for(int iter = 0; iter < max_iter; ++iter) {\n                    if (iter % 128 == 0) {\n                        T = T_start * pow(T_end / T_start, (double)iter / max_iter);\n                        if (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start_time).count() > time_limit_ms) break;\n                    }\n                    if (current_cells.empty()) break;\n                    \n                    std::vector<GridPoint> boundary_cells;\n                    for(const auto& cell : current_cells) {\n                        for(int i = 0; i < 4; ++i) {\n                            GridPoint neighbor = {cell.first + DX[i], cell.second + DY[i]};\n                            if (current_cells.find(neighbor) == current_cells.end()) {\n                                boundary_cells.push_back(cell);\n                                break;\n                            }\n                        }\n                    }\n                    if(boundary_cells.empty()) boundary_cells.assign(current_cells.begin(), current_cells.end());\n                    \n                    std::uniform_int_distribution<int> dist_cell_idx(0, boundary_cells.size() - 1);\n                    GridPoint rand_cell = boundary_cells[dist_cell_idx(rng)];\n\n                    std::uniform_int_distribution<int> dist_dir(0, 3);\n                    GridPoint cand_cell = {rand_cell.first + DX[dist_dir(rng)], rand_cell.second + DY[dist_dir(rng)]};\n                    if (cand_cell.first < 0 || cand_cell.first >= grid_dim_x || cand_cell.second < 0 || cand_cell.second >= grid_dim_y) continue;\n                    \n                    bool is_in = current_cells.count(cand_cell);\n                    long long delta_score = grid_scores[cand_cell.first][cand_cell.second];\n                    if (is_in) delta_score = -delta_score;\n                    if(is_in && current_cells.size() == 1) continue;\n\n                    std::uniform_real_distribution<double> prob_dist(0.0, 1.0);\n                    if (delta_score > 0 || prob_dist(rng) < std::exp(delta_score / T)) {\n                        if (is_in) current_cells.erase(cand_cell);\n                        else current_cells.insert(cand_cell);\n                    }\n                }\n                \n                if(!current_cells.empty()){\n                    bool changed = true;\n                    while(changed) {\n                        changed = false;\n                        for (int hx = 0; hx < grid_dim_x - 1; ++hx) {\n                            for (int hy = 0; hy < grid_dim_y - 1; ++hy) {\n                                bool s00 = current_cells.count({hx, hy});\n                                bool s10 = current_cells.count({hx + 1, hy});\n                                bool s01 = current_cells.count({hx, hy + 1});\n                                bool s11 = current_cells.count({hx + 1, hy + 1});\n                                if ((s00 && s11 && !s10 && !s01)) {\n                                    if (grid_scores[hx + 1][hy] > grid_scores[hx][hy + 1]) {\n                                        if (current_cells.find({hx + 1, hy}) == current_cells.end()) {\n                                            current_cells.insert({hx + 1, hy}); changed = true;\n                                        }\n                                    } else {\n                                        if (current_cells.find({hx, hy + 1}) == current_cells.end()) {\n                                            current_cells.insert({hx, hy + 1}); changed = true;\n                                        }\n                                    }\n                                } else if ((!s00 && !s11 && s10 && s01)) {\n                                    if (grid_scores[hx][hy] > grid_scores[hx + 1][hy + 1]) {\n                                        if (current_cells.find({hx, hy}) == current_cells.end()) {\n                                            current_cells.insert({hx, hy}); changed = true;\n                                        }\n                                    } else {\n                                        if (current_cells.find({hx + 1, hy + 1}) == current_cells.end()) {\n                                            current_cells.insert({hx + 1, hy + 1}); changed = true;\n                                        }\n                                    }\n                                }\n                            }\n                        }\n                    }\n\n                    Polygon p = generate_polygon_from_cells(current_cells, cell_size);\n                    if (p.vertices.size() >= 3 && p.vertices.size() <= 1000 && p.calculate_perimeter() <= 400000) {\n                        int current_a = 0, current_b = 0;\n                        for (const auto& m : mackerels) if (p.is_inside(m)) current_a++;\n                        for (const auto& s : sardines) if (p.is_inside(s)) current_b++;\n\n                        if (current_a - current_b > best_a - best_b) {\n                            best_a = current_a;\n                            best_b = current_b;\n                            best_polygon = p;\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    if (best_polygon.vertices.empty()) {\n        if (!mackerels.empty()) {\n            Point m = mackerels[0];\n            best_polygon.vertices = {{m.x, m.y}, {m.x + 1, m.y}, {m.x + 1, m.y + 1}, {m.x, m.y + 1}};\n        } else {\n             best_polygon.vertices = {{0,0}, {1,0}, {1,1}, {0,1}};\n        }\n    }\n\n    if (best_polygon.vertices.size() < 4) {\n         if (!mackerels.empty()) {\n            Point m = mackerels[0];\n            best_polygon.vertices = {{m.x, m.y}, {m.x + 1, m.y}, {m.x + 1, m.y + 1}, {m.x, m.y + 1}};\n         } else {\n             best_polygon.vertices = {{0,0}, {1,0}, {1,1}, {0,1}};\n         }\n    }\n    std::cout << best_polygon.vertices.size() << '\\n';\n    for (const auto& v : best_polygon.vertices) {\n        std::cout << v.x << \" \" << v.y << '\\n';\n    }\n\n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <string>\n#include <chrono>\n#include <random>\n#include <numeric>\n#include <algorithm>\n#include <map>\n#include <tuple>\n#include <cmath>\n#include <set>\n\n#include <Eigen/Dense>\n\n// --- Timer ---\nusing namespace std;\nusing namespace std::chrono;\n\nlong long start_time;\n\nlong long get_time() {\n    return duration_cast<milliseconds>(high_resolution_clock::now().time_since_epoch()).count();\n}\n\n// --- Random ---\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// --- Problem specific structs ---\nstruct Rect {\n    long long x, y, w, h;\n    int p_idx;\n};\n\nstruct Action {\n    int p, r;\n    char d;\n    int b;\n};\n\nusing Plan = vector<Action>;\n\n// --- Globals ---\nint N, T;\ndouble SIGMA;\nvector<double> w_obs, h_obs;\nvector<double> w_mean, h_mean;\nvector<tuple<Plan, long long, long long>> history;\nlong long global_best_score = -1;\nPlan global_best_plan;\n\n// O(plan.size() * plan.size()) simulation.\npair<long long, long long> simulate(const Plan& plan) {\n    if (plan.empty()) return {0,0};\n    vector<Rect> placed_rects;\n    long long W = 0, H = 0;\n    vector<int> p_to_idx(N, -1);\n\n    for (const auto& action : plan) {\n        long long w = round((action.r == 0) ? w_mean[action.p] : h_mean[action.p]);\n        long long h = round((action.r == 0) ? h_mean[action.p] : w_mean[action.p]);\n        long long new_x, new_y;\n        if (action.d == 'U') {\n            new_x = 0;\n            if (action.b != -1) {\n                const auto& ref_rect = placed_rects[p_to_idx[action.b]];\n                new_x = ref_rect.x + ref_rect.w;\n            }\n            new_y = 0;\n            for (const auto& rect : placed_rects) {\n                if (max(new_x, rect.x) < min(new_x + w, rect.x + rect.w)) {\n                    new_y = max(new_y, rect.y + rect.h);\n                }\n            }\n        } else { // 'L'\n            new_y = 0;\n            if (action.b != -1) {\n                const auto& ref_rect = placed_rects[p_to_idx[action.b]];\n                new_y = ref_rect.y + ref_rect.h;\n            }\n            new_x = 0;\n            for (const auto& rect : placed_rects) {\n                if (max(new_y, rect.y) < min(new_y + h, rect.y + rect.h)) {\n                    new_x = max(new_x, rect.x + rect.w);\n                }\n            }\n        }\n        p_to_idx[action.p] = placed_rects.size();\n        placed_rects.push_back({new_x, new_y, w, h, action.p});\n        W = max(W, new_x + w);\n        H = max(H, new_y + h);\n    }\n    return {W, H};\n}\n\nvoid update_estimates_by_lsq() {\n    int num_vars = 2 * N;\n    \n    vector<vector<pair<int, double>>> A_rows;\n    vector<double> b_vals;\n\n    for (int i = 0; i < N; ++i) {\n        A_rows.push_back({{i, 1.0}}); b_vals.push_back(w_obs[i]);\n        A_rows.push_back({{N + i, 1.0}}); b_vals.push_back(h_obs[i]);\n    }\n    for (const auto& [plan, W_prime, H_prime] : history) {\n        if(plan.empty()) continue;\n        \n        bool is_sum_plan_W = true;\n        if (plan[0].d != 'L') is_sum_plan_W = false;\n        for(size_t j=1; j<plan.size() && is_sum_plan_W; ++j) if(plan[j].d != 'L') is_sum_plan_W = false;\n        if(is_sum_plan_W) {\n            vector<pair<int, double>> row;\n            for (const auto& action : plan) {\n                if (action.r == 0) row.push_back({action.p, 1.0}); else row.push_back({N + action.p, 1.0});\n            }\n            if(!row.empty()){ A_rows.push_back(row); b_vals.push_back(W_prime); }\n        }\n\n        bool is_sum_plan_H = true;\n        if (plan[0].d != 'U') is_sum_plan_H = false;\n        for(size_t j=1; j<plan.size() && is_sum_plan_H; ++j) if(plan[j].d != 'U') is_sum_plan_H = false;\n        if(is_sum_plan_H){\n            vector<pair<int, double>> row;\n            for (const auto& action : plan) {\n                if (action.r == 0) row.push_back({N + action.p, 1.0}); else row.push_back({action.p, 1.0});\n            }\n            if(!row.empty()){ A_rows.push_back(row); b_vals.push_back(H_prime); }\n        }\n    }\n\n    int num_equations = A_rows.size();\n    if(num_equations == 0) return;\n    Eigen::MatrixXd A(num_equations, num_vars); Eigen::VectorXd b(num_equations); A.setZero();\n    for(int i=0; i<num_equations; ++i){\n        for(auto const& [col, val] : A_rows[i]) A(i, col) = val;\n        b(i) = b_vals[i];\n    }\n    \n    Eigen::VectorXd x = A.bdcSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(b);\n    for (int i = 0; i < N; ++i) {\n        w_mean[i] = max(1.0, x(i)); h_mean[i] = max(1.0, x(N + i));\n    }\n}\n\nPlan simple_greedy_search() {\n    Plan plan;\n    vector<Rect> placed_rects;\n    vector<int> p_to_idx(N, -1);\n    long long current_W = 0, current_H = 0;\n\n    for (int i = 0; i < N; ++i) {\n        int p = i;\n        Action best_action;\n        long long best_score = -1;\n\n        for (int r = 0; r < 2; ++r) {\n            long long w = round((r == 0) ? w_mean[p] : h_mean[p]);\n            long long h = round((r == 0) ? h_mean[p] : w_mean[p]);\n            for (char d : {'U', 'L'}) {\n                vector<int> b_candidates; b_candidates.push_back(-1);\n                const int B_SAMPLES = 8;\n                if (i > 0) {\n                    b_candidates.push_back(plan.back().p);\n                    uniform_int_distribution<int> dist(0, placed_rects.size() - 1);\n                    for (int k = 0; k < B_SAMPLES && k < placed_rects.size(); ++k) {\n                        b_candidates.push_back(placed_rects[dist(rng)].p_idx);\n                    }\n                }\n                sort(b_candidates.begin(), b_candidates.end());\n                b_candidates.erase(unique(b_candidates.begin(), b_candidates.end()), b_candidates.end());\n                \n                for (int b_p_idx : b_candidates) {\n                    long long new_x, new_y;\n                    if(d == 'U'){\n                        new_x = 0; if (b_p_idx != -1) new_x = placed_rects[p_to_idx[b_p_idx]].x + placed_rects[p_to_idx[b_p_idx]].w;\n                        new_y = 0;\n                        for(const auto& rect : placed_rects) if(max(new_x, rect.x) < min(new_x+w, rect.x+rect.w)) new_y = max(new_y, rect.y+rect.h);\n                    } else {\n                        new_y = 0; if (b_p_idx != -1) new_y = placed_rects[p_to_idx[b_p_idx]].y + placed_rects[p_to_idx[b_p_idx]].h;\n                        new_x = 0;\n                        for(const auto& rect : placed_rects) if(max(new_y, rect.y) < min(new_y+h, rect.y+rect.h)) new_x = max(new_x, rect.x+rect.w);\n                    }\n                    long long score = max(current_W, new_x+w) + max(current_H, new_y+h);\n                    if (best_score == -1 || score < best_score) {\n                        best_score = score; best_action = {p, r, d, b_p_idx};\n                    }\n                }\n            }\n        }\n        plan.push_back(best_action);\n        int r=best_action.r, b_p_idx=best_action.b; char d=best_action.d;\n        long long w = round((r == 0) ? w_mean[p] : h_mean[p]); long long h = round((r == 0) ? h_mean[p] : w_mean[p]);\n        long long new_x, new_y;\n        if(d == 'U'){\n            new_x = 0; if (b_p_idx!=-1) new_x = placed_rects[p_to_idx[b_p_idx]].x + placed_rects[p_to_idx[b_p_idx]].w;\n            new_y = 0;\n            for(const auto& rect : placed_rects) if(max(new_x, rect.x) < min(new_x+w, rect.x+rect.w)) new_y = max(new_y, rect.y+rect.h);\n        } else {\n            new_y = 0; if (b_p_idx!=-1) new_y = placed_rects[p_to_idx[b_p_idx]].y + placed_rects[p_to_idx[b_p_idx]].h;\n            new_x = 0;\n            for(const auto& rect : placed_rects) if(max(new_y, rect.y) < min(new_y+h, rect.y+rect.h)) new_x = max(new_x, rect.x+rect.w);\n        }\n        p_to_idx[p] = placed_rects.size();\n        placed_rects.push_back({new_x, new_y, w, h, p});\n        current_W = max(current_W, new_x+w); current_H = max(current_H, new_y+h);\n    }\n    return plan;\n}\n\nPlan simulated_annealing(Plan initial_plan, int time_limit_ms) {\n    long long turn_start_time = get_time();\n    Plan current_plan = initial_plan;\n    auto [W, H] = simulate(current_plan);\n    long long current_score = W + H;\n    Plan best_plan = current_plan;\n    long long best_score = current_score;\n    double start_temp = (double)current_score * 0.05; double end_temp = 0.1;\n\n    while(true) {\n        long long elapsed_time = get_time() - turn_start_time;\n        if (elapsed_time >= time_limit_ms) break;\n        \n        Plan neighbor_plan = current_plan;\n        int i = uniform_int_distribution<int>(0, N - 1)(rng);\n        \n        int change_type = uniform_int_distribution<int>(0, 2)(rng);\n        if (change_type == 0) { neighbor_plan[i].r = 1 - neighbor_plan[i].r; }\n        else if (change_type == 1) { neighbor_plan[i].d = (neighbor_plan[i].d == 'U' ? 'L' : 'U'); }\n        else {\n            if (i > 0) {\n                int b_p_idx = -1;\n                uniform_int_distribution<int> b_dist(-1, i - 1);\n                int b_idx = b_dist(rng);\n                if (b_idx != -1) b_p_idx = current_plan[b_idx].p;\n                neighbor_plan[i].b = b_p_idx;\n            }\n        }\n        \n        auto [nW, nH] = simulate(neighbor_plan);\n        long long neighbor_score = nW + nH;\n        double temp = start_temp * pow(end_temp / start_temp, (double)elapsed_time / max(1, time_limit_ms));\n        \n        if (neighbor_score < current_score || (temp > 1e-9 && uniform_real_distribution<double>(0.0, 1.0)(rng) < exp((double)(current_score - neighbor_score) / temp))) {\n            current_plan = neighbor_plan; current_score = neighbor_score;\n        }\n        if (current_score < best_score) {\n            best_score = current_score; best_plan = current_plan;\n        }\n    }\n    return best_plan;\n}\n\nvoid solve() {\n    cin >> N >> T >> SIGMA;\n    w_obs.resize(N); h_obs.resize(N); w_mean.resize(N); h_mean.resize(N);\n    for (int i = 0; i < N; ++i) { cin >> w_obs[i] >> h_obs[i]; w_mean[i] = w_obs[i]; h_mean[i] = h_obs[i]; }\n    \n    vector<Plan> exploratory_plans;\n    for (int k = 0; k < 2; ++k) {\n        Plan p_L, p_U;\n        for (int i = 0; i < N; ++i) {\n            p_L.push_back({i, (int)(rng() % 2), 'L', i > 0 ? i-1 : -1});\n            p_U.push_back({i, (int)(rng() % 2), 'U', i > 0 ? i-1 : -1});\n        }\n        exploratory_plans.push_back(p_L); exploratory_plans.push_back(p_U);\n    }\n    int K = min((int)exploratory_plans.size(), T / 2);\n\n    set<int> update_turns;\n    if (T > K) {\n        update_turns.insert(K - 1);\n        update_turns.insert(K + (T - K - 1) / 4);\n        update_turns.insert(K + (T - K - 1) / 2);\n        update_turns.insert(K + 3 * (T - K - 1) / 4);\n    }\n    \n    for (int t = 0; t < T; ++t) {\n        Plan p_to_submit;\n        if (t < K) {\n            p_to_submit = exploratory_plans[t];\n        } else {\n            long long time_left = 2750 - (get_time() - start_time);\n            long long time_per_turn = (T - t > 0) ? (time_left / (T - t)) : time_left;\n            \n            Plan initial_plan;\n            if (global_best_plan.empty()) {\n                initial_plan = simple_greedy_search();\n            } else {\n                initial_plan = global_best_plan;\n            }\n            \n            p_to_submit = simulated_annealing(initial_plan, max(1LL, time_per_turn));\n            \n            if (!global_best_plan.empty()) {\n                auto [w_cand, h_cand] = simulate(p_to_submit);\n                auto [w_best, h_best] = simulate(global_best_plan);\n                if (w_best + h_best < w_cand + h_cand) { p_to_submit = global_best_plan; }\n            }\n        }\n        \n        cout << p_to_submit.size() << endl;\n        for (const auto& action : p_to_submit) {\n            cout << action.p << \" \" << action.r << \" \" << action.d << \" \" << action.b << endl;\n        }\n\n        long long W_prime, H_prime; cin >> W_prime >> H_prime;\n        \n        history.emplace_back(p_to_submit, W_prime, H_prime);\n        if (update_turns.count(t)) {\n            update_estimates_by_lsq();\n        }\n        \n        long long current_score = W_prime + H_prime;\n        if (global_best_score == -1 || current_score < global_best_score) {\n            global_best_score = current_score; global_best_plan = p_to_submit;\n        }\n    }\n}\n\nint main() {\n    start_time = get_time();\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <cmath>\n#include <tuple>\n\nusing namespace std;\n\n// --- Utilities ---\nstruct XorShift {\n    unsigned int x, y, z, w;\n    XorShift(unsigned int seed) : x(seed), y(362436069), z(521288629), w(88675123) {}\n    unsigned int next() {\n        unsigned int t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));\n    }\n    int next_int(int n) {\n        if (n == 0) return 0;\n        return next() % n;\n    }\n    double next_double() {\n        return (double)next() / ((long long)1 << 32);\n    }\n};\n\nXorShift rnd(12345);\nauto start_time = chrono::steady_clock::now();\n\n// --- Problem data ---\nint N, M, H;\nvector<int> A;\nvector<pair<int, int>> edges;\nvector<vector<int>> adj;\n\n// --- Solution state and helpers ---\nstruct Solution {\n    vector<int> p;\n    long long score;\n\n    vector<vector<int>> children;\n    vector<int> h;\n    vector<int> max_d;\n    vector<long long> sum_A_sub;\n    vector<int> root_of;\n\n    Solution() {}\n\n    void init(int n_nodes) {\n        p.assign(n_nodes, -1);\n        children.assign(n_nodes, {});\n        h.assign(n_nodes, 0);\n        max_d.assign(n_nodes, 0);\n        sum_A_sub.assign(n_nodes, 0);\n        root_of.assign(n_nodes, -1);\n    }\n\n    void compute_properties() {\n        for(int i=0; i<N; ++i) children[i].clear();\n        vector<int> roots;\n        for (int i = 0; i < N; ++i) {\n            if (p[i] == -1) {\n                roots.push_back(i);\n            } else {\n                children[p[i]].push_back(i);\n            }\n        }\n\n        for (int r : roots) {\n            vector<int> q;\n            q.push_back(r);\n            root_of[r] = r;\n            h[r] = 0;\n            \n            int head = 0;\n            while(head < q.size()){\n                int u = q[head++];\n                for(int v : children[u]){\n                    h[v] = h[u] + 1;\n                    root_of[v] = r;\n                    q.push_back(v);\n                }\n            }\n            \n            reverse(q.begin(), q.end());\n            for(int u : q){\n                sum_A_sub[u] = A[u];\n                max_d[u] = 0;\n                for(int v : children[u]){\n                    sum_A_sub[u] += sum_A_sub[v];\n                    max_d[u] = max(max_d[u], max_d[v] + 1);\n                }\n            }\n        }\n        score = 0;\n        for(int i=0; i<N; ++i) {\n            if (h[i] > H) {\n                score = -1; // Invalid\n                return;\n            }\n            score += (long long)(h[i] + 1) * A[i];\n        }\n    }\n};\n\nvoid solve() {\n    Solution sol;\n    sol.init(N);\n    \n    // --- Greedy construction ---\n    double greedy_time_limit = 0.8;\n    int roots_count = N;\n    while(roots_count > 1) {\n        auto current_time = chrono::steady_clock::now();\n        double elapsed_time = chrono::duration_cast<chrono::milliseconds>(current_time - start_time).count() / 1000.0;\n        if (elapsed_time > greedy_time_limit) break;\n\n        sol.compute_properties();\n\n        double best_gain = -1.0;\n        int best_u = -1, best_v = -1;\n\n        for (const auto& edge : edges) {\n            int u1 = edge.first;\n            int v1 = edge.second;\n\n            if (sol.root_of[u1] == sol.root_of[v1]) continue;\n\n            // Try u1 -> v1\n            if (sol.p[v1] == -1) {\n                if (sol.h[u1] + 1 + sol.max_d[v1] <= H) {\n                    double gain = (double)(sol.h[u1] + 1) * sol.sum_A_sub[v1];\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        best_u = u1;\n                        best_v = v1;\n                    }\n                }\n            }\n            // Try v1 -> u1\n            if (sol.p[u1] == -1) {\n                if (sol.h[v1] + 1 + sol.max_d[u1] <= H) {\n                    double gain = (double)(sol.h[v1] + 1) * sol.sum_A_sub[u1];\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        best_u = v1;\n                        best_v = u1;\n                    }\n                }\n            }\n        }\n\n        if (best_u == -1) break;\n        sol.p[best_v] = best_u;\n        roots_count--;\n    }\n\n    sol.compute_properties();\n    Solution best_sol = sol;\n\n    // --- Simulated Annealing ---\n    double time_limit = 1.95;\n    double temp_start = 500.0, temp_end = 0.1;\n\n    while (true) {\n        auto current_time = chrono::steady_clock::now();\n        double elapsed_time = chrono::duration_cast<chrono::milliseconds>(current_time - start_time).count() / 1000.0;\n        if (elapsed_time > time_limit) break;\n\n        double progress = (elapsed_time - greedy_time_limit) / (time_limit - greedy_time_limit);\n        if (progress < 0) progress = 0;\n        if (progress > 1) progress = 1;\n\n        double temp = temp_start * pow(temp_end / temp_start, progress);\n\n        int v = rnd.next_int(N);\n        \n        vector<int> candidates = adj[v];\n        candidates.push_back(-1);\n        int u = candidates[rnd.next_int(candidates.size())];\n\n        int old_p = sol.p[v];\n        if (u == old_p) continue;\n        \n        bool is_ancestor = false;\n        if (u != -1) {\n            int curr = u;\n            while(curr != -1) {\n                if (curr == v) {\n                    is_ancestor = true;\n                    break;\n                }\n                curr = sol.p[curr];\n            }\n        }\n        if (is_ancestor) continue;\n        \n        int u_h = (u == -1) ? -1 : sol.h[u];\n        if (u_h + 1 + sol.max_d[v] > H) continue;\n\n        int old_p_h = (old_p == -1) ? -1 : sol.h[old_p];\n        long long score_delta = (long long)(u_h - old_p_h) * sol.sum_A_sub[v];\n\n        if (score_delta > 0 || (temp > 1e-9 && rnd.next_double() < exp(score_delta / temp))) {\n            sol.p[v] = u;\n            sol.compute_properties();\n            if (sol.score > best_sol.score) {\n                best_sol = sol;\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << best_sol.p[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N >> M >> H;\n    A.resize(N);\n    adj.resize(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        edges.push_back({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    solve();\n\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <array>\n#include <chrono>\n#include <queue>\n#include <memory>\n#include <unordered_map>\n#include <boost/container_hash/hash.hpp>\n\nusing namespace std;\nusing namespace std::chrono;\n\nconst int N = 20;\nconst int BEAM_WIDTH = 250; \nconst double TIME_LIMIT_MS = 1950.0;\n\nstruct Piece {\n    int id; \n    int r, c;\n    bool removed;\n};\n\nstruct MacroMove {\n    char dir;\n    int line_idx;\n    int cost;\n};\n\nstruct PiecePos {\n    int r, c;\n    bool operator<(const PiecePos& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n};\n\nstruct State {\n    shared_ptr<const vector<Piece>> onis;\n    shared_ptr<const vector<Piece>> fukus;\n    \n    vector<MacroMove> history;\n    int total_cost = 0;\n    int uncovered_count = 0;\n\n    double score = 0.0; // g + h\n\n    bool operator>(const State& other) const {\n        if (abs(score - other.score) > 1e-9) {\n            return score > other.score;\n        }\n        return total_cost > other.total_cost;\n    }\n};\n\n\nsize_t calculate_state_hash(const State& s) {\n    vector<PiecePos> positions;\n    positions.reserve(s.onis->size() + s.fukus->size());\n    for (const auto& p : *s.onis) if (!p.removed) positions.push_back({p.r, p.c});\n    for (const auto& p : *s.fukus) if (!p.removed) positions.push_back({p.r, p.c});\n    sort(positions.begin(), positions.end());\n\n    size_t seed = 0;\n    for(const auto& pos : positions) {\n        boost::hash_combine(seed, pos.r);\n        boost::hash_combine(seed, pos.c);\n    }\n    return seed;\n}\n\ndouble calculate_heuristic(const State& s) {\n    if (s.uncovered_count == 0) return 0.0;\n\n    double h = 0;\n    for (const auto& oni : *s.onis) {\n        if (oni.removed) continue;\n        \n        int min_cost = 1e9;\n        \n        bool safe_u = true;\n        for(const auto& fuku : *s.fukus) if (!fuku.removed && fuku.c == oni.c && fuku.r < oni.r) { safe_u = false; break; }\n        if(safe_u) min_cost = min(min_cost, oni.r + 1);\n\n        bool safe_d = true;\n        for(const auto& fuku : *s.fukus) if (!fuku.removed && fuku.c == oni.c && fuku.r > oni.r) { safe_d = false; break; }\n        if(safe_d) min_cost = min(min_cost, N - oni.r);\n\n        bool safe_l = true;\n        for(const auto& fuku : *s.fukus) if (!fuku.removed && fuku.r == oni.r && fuku.c < oni.c) { safe_l = false; break; }\n        if(safe_l) min_cost = min(min_cost, oni.c + 1);\n        \n        bool safe_r = true;\n        for(const auto& fuku : *s.fukus) if (!fuku.removed && fuku.r == oni.r && fuku.c > oni.c) { safe_r = false; break; }\n        if(safe_r) min_cost = min(min_cost, N - oni.c);\n\n        if (min_cost < 1e8) h += min_cost;\n        else return 1e18; // Unsolvable state\n    }\n    return h;\n}\n\nvector<MacroMove> generate_actions(const State& s) {\n    vector<MacroMove> actions;\n    \n    vector<vector<int>> onis_in_row(N), fukus_in_row(N);\n    vector<vector<int>> onis_in_col(N), fukus_in_col(N);\n    \n    for (const auto& oni : *s.onis) if (!oni.removed) { onis_in_row[oni.r].push_back(oni.id); onis_in_col[oni.c].push_back(oni.id); }\n    for (const auto& fuku : *s.fukus) if (!fuku.removed) { fukus_in_row[fuku.r].push_back(fuku.id); fukus_in_col[fuku.c].push_back(fuku.id); }\n\n    auto generate_for_line = [&](char dir, int idx) {\n        int cost = 0;\n        bool has_target = false;\n        \n        const auto& line_oni_ids = (dir == 'U' || dir == 'D') ? onis_in_col[idx] : onis_in_row[idx];\n        const auto& line_fuku_ids = (dir == 'U' || dir == 'D') ? fukus_in_col[idx] : fukus_in_row[idx];\n        \n        for (int oni_id : line_oni_ids) {\n            bool safe = true;\n            for (int fuku_id : line_fuku_ids) {\n                if ((dir == 'U' && (*s.fukus)[fuku_id].r < (*s.onis)[oni_id].r) ||\n                    (dir == 'D' && (*s.fukus)[fuku_id].r > (*s.onis)[oni_id].r) ||\n                    (dir == 'L' && (*s.fukus)[fuku_id].c < (*s.onis)[oni_id].c) ||\n                    (dir == 'R' && (*s.fukus)[fuku_id].c > (*s.onis)[oni_id].c)) {\n                    safe = false;\n                    break;\n                }\n            }\n            if (safe) {\n                has_target = true;\n                if(dir == 'U') cost = max(cost, (*s.onis)[oni_id].r + 1);\n                if(dir == 'D') cost = max(cost, N - (*s.onis)[oni_id].r);\n                if(dir == 'L') cost = max(cost, (*s.onis)[oni_id].c + 1);\n                if(dir == 'R') cost = max(cost, N - (*s.onis)[oni_id].c);\n            }\n        }\n        if (has_target) actions.push_back({dir, idx, cost});\n    };\n    \n    for (int i = 0; i < N; ++i) { generate_for_line('L', i); generate_for_line('R', i); }\n    for (int j = 0; j < N; ++j) { generate_for_line('U', j); generate_for_line('D', j); }\n\n    return actions;\n}\n\nState apply_action_to_state(const State& current, const MacroMove& action) {\n    State next;\n    next.history = current.history;\n    next.history.push_back(action);\n    next.total_cost = current.total_cost + action.cost;\n    next.uncovered_count = current.uncovered_count;\n\n    auto next_onis = make_shared<vector<Piece>>(*current.onis);\n    auto next_fukus = make_shared<vector<Piece>>(*current.fukus);\n\n    auto update_piece = [&](Piece& p) {\n        if (p.removed) return;\n        bool piece_removed = false;\n        switch(action.dir) {\n            case 'U': if (p.c == action.line_idx) { if (p.r < action.cost) piece_removed = true; else p.r -= action.cost; } break;\n            case 'D': if (p.c == action.line_idx) { if (p.r > N - 1 - action.cost) piece_removed = true; else p.r += action.cost; } break;\n            case 'L': if (p.r == action.line_idx) { if (p.c < action.cost) piece_removed = true; else p.c -= action.cost; } break;\n            case 'R': if (p.r == action.line_idx) { if (p.c > N - 1 - action.cost) piece_removed = true; else p.c += action.cost; } break;\n        }\n        if (piece_removed) {\n            p.removed = true;\n            if (p.id >= 0) next.uncovered_count--;\n        }\n    };\n\n    for (auto& oni : *next_onis) update_piece(oni);\n    for (auto& fuku : *next_fukus) update_piece(fuku);\n    \n    next.onis = next_onis;\n    next.fukus = next_fukus;\n\n    return next;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    auto start_time = high_resolution_clock::now();\n\n    int n_dummy;\n    cin >> n_dummy;\n\n    State initial_state;\n    auto initial_onis = make_shared<vector<Piece>>();\n    auto initial_fukus = make_shared<vector<Piece>>();\n    int oni_id_counter = 0;\n    int fuku_id_counter = 0;\n    for (int i = 0; i < N; ++i) {\n        string row_str;\n        cin >> row_str;\n        for (int j = 0; j < N; ++j) {\n            if (row_str[j] == 'x') {\n                initial_onis->push_back({oni_id_counter++, i, j, false});\n            } else if (row_str[j] == 'o') {\n                initial_fukus->push_back({fuku_id_counter++, i, j, false});\n            }\n        }\n    }\n    initial_state.onis = initial_onis;\n    initial_state.fukus = initial_fukus;\n    initial_state.uncovered_count = initial_state.onis->size();\n    \n    priority_queue<State, vector<State>, greater<State>> beam;\n    initial_state.score = calculate_heuristic(initial_state);\n    beam.push(initial_state);\n\n    State best_solution;\n    best_solution.total_cost = 1e9;\n    unordered_map<size_t, int> min_costs;\n\n    size_t initial_hash = calculate_state_hash(initial_state);\n    min_costs[initial_hash] = 0;\n\n    while(true) {\n        auto current_time = high_resolution_clock::now();\n        if (duration_cast<milliseconds>(current_time - start_time).count() > TIME_LIMIT_MS) break;\n        if (beam.empty()) break;\n\n        priority_queue<State, vector<State>, greater<State>> next_beam_candidates;\n        int beam_proc_count = 0;\n        while(!beam.empty() && beam_proc_count < BEAM_WIDTH) {\n            State current = beam.top();\n            beam.pop();\n\n            if (current.total_cost >= best_solution.total_cost) continue;\n            \n            size_t current_hash = calculate_state_hash(current);\n            if (min_costs.count(current_hash) && current.total_cost > min_costs[current_hash]) continue;\n\n            if (current.uncovered_count == 0) {\n                 if (current.total_cost < best_solution.total_cost) best_solution = current;\n                continue;\n            }\n\n            vector<MacroMove> possible_actions = generate_actions(current);\n\n            for (const auto& action : possible_actions) {\n                State next_state = apply_action_to_state(current, action);\n                size_t next_hash = calculate_state_hash(next_state);\n\n                if (!min_costs.count(next_hash) || next_state.total_cost < min_costs[next_hash]) {\n                    min_costs[next_hash] = next_state.total_cost;\n                    double h = calculate_heuristic(next_state);\n                    if (h > 1e17) continue;\n                    next_state.score = next_state.total_cost + h;\n                    next_beam_candidates.push(next_state);\n                }\n            }\n            beam_proc_count++;\n        }\n        \n        beam = priority_queue<State, vector<State>, greater<State>>();\n        int count = 0;\n        while (!next_beam_candidates.empty() && count < BEAM_WIDTH) {\n            beam.push(next_beam_candidates.top());\n            next_beam_candidates.pop();\n            count++;\n        }\n    }\n    \n    for (const auto& macro_move : best_solution.history) {\n        for (int i = 0; i < macro_move.cost; ++i) {\n            cout << macro_move.dir << \" \" << macro_move.line_idx << \"\\n\";\n        }\n    }\n\n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <tuple>\n\n// --- Start of Timer and RNG Utilities ---\nclass Timer {\n    std::chrono::high_resolution_clock::time_point start_time;\npublic:\n    Timer() {\n        start_time = std::chrono::high_resolution_clock::now();\n    }\n    double get_elapsed_sec() {\n        auto now = std::chrono::high_resolution_clock::now();\n        return std::chrono::duration_cast<std::chrono::duration<double>>(now - start_time).count();\n    }\n};\n\nclass XorShiftRng {\n    uint64_t x;\npublic:\n    XorShiftRng(uint64_t seed) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 13;\n        x ^= x >> 7;\n        x ^= x << 17;\n        return x;\n    }\n    int next_int(int max) { // [0, max-1]\n        if (max <= 0) return 0;\n        return next() % max;\n    }\n    double next_double() { // [0.0, 1.0)\n        return static_cast<double>(next()) / UINT64_MAX;\n    }\n};\n// --- End of Timer and RNG Utilities ---\n\nconst int N_CONST = 100;\nconst int L_CONST = 500000;\nconst double TIME_LIMIT_SEC = 1.95;\n\nstruct EvalResult {\n    long long error;\n    std::vector<int> t;\n    std::vector<int> count_a;\n    std::vector<int> count_b;\n};\n\nEvalResult evaluate(const std::vector<int>& a, const std::vector<int>& b, const std::vector<int>& T) {\n    std::vector<int> t(N_CONST, 0);\n    std::vector<int> count_a(N_CONST, 0);\n    std::vector<int> count_b(N_CONST, 0);\n    \n    int cleaner = 0;\n    t[cleaner]++;\n    \n    for (int k = 1; k < L_CONST; ++k) {\n        int last_cleaner = cleaner;\n        int count_of_last_cleaner = t[last_cleaner];\n        \n        if (count_of_last_cleaner % 2 != 0) {\n            cleaner = a[last_cleaner];\n            count_a[last_cleaner]++;\n        } else {\n            cleaner = b[last_cleaner];\n            count_b[last_cleaner]++;\n        }\n        t[cleaner]++;\n    }\n    \n    long long error = 0;\n    for (int i = 0; i < N_CONST; ++i) {\n        error += std::abs(static_cast<long long>(t[i]) - T[i]);\n    }\n    \n    return {error, std::move(t), std::move(count_a), std::move(count_b)};\n}\n\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    Timer timer;\n    \n    int n_in, l_in;\n    std::cin >> n_in >> l_in; \n    std::vector<int> T(N_CONST);\n    for (int i = 0; i < N_CONST; ++i) {\n        std::cin >> T[i];\n    }\n\n    uint64_t seed = std::chrono::high_resolution_clock::now().time_since_epoch().count();\n    XorShiftRng rng(seed);\n\n    // --- Initial solution ---\n    std::vector<int> a(N_CONST), b(N_CONST);\n    \n    std::vector<double> weights;\n    double total_weight = 0;\n    for(int i = 0; i < N_CONST; ++i) {\n        double w = T[i] > 0 ? static_cast<double>(T[i]) : 1.0;\n        weights.push_back(w);\n        total_weight += w;\n    }\n    auto select_weighted = [&](const std::vector<double>& w, double total_w) {\n        double r = rng.next_double() * total_w;\n        for(size_t i = 0; i < w.size(); ++i) {\n            r -= w[i];\n            if (r <= 0) return (int)i;\n        }\n        return (int)w.size() - 1;\n    };\n    for (int i = 0; i < N_CONST; ++i) {\n        a[i] = select_weighted(weights, total_weight);\n        b[i] = select_weighted(weights, total_weight);\n    }\n    \n    auto global_best_a = a;\n    auto global_best_b = b;\n    long long global_best_error = evaluate(a, b, T).error;\n\n    auto make_random_move = [&](std::vector<int>& target_a, std::vector<int>& target_b) {\n        int change_i = rng.next_int(N_CONST);\n        int change_ab = rng.next_int(2);\n        int new_val = rng.next_int(N_CONST);\n        if (change_ab == 0) target_a[change_i] = new_val;\n        else target_b[change_i] = new_val;\n    };\n\n    while (timer.get_elapsed_sec() < TIME_LIMIT_SEC) {\n        // --- One run of SA Local Search ---\n        auto current_eval = evaluate(a, b, T);\n        long long current_error = current_eval.error;\n        auto& current_t = current_eval.t;\n        auto& current_count_a = current_eval.count_a;\n        auto& current_count_b = current_eval.count_b;\n\n        auto run_best_a = a;\n        auto run_best_b = b;\n        long long run_best_error = current_error;\n\n        const double T_start = 3000.0;\n        const double T_end = 0.1;\n        const int ITERS_PER_RUN = 2500;\n\n        auto make_weighted_smart_move = [&](std::vector<int>& target_a, std::vector<int>& target_b) -> bool {\n            std::vector<std::pair<int, double>> over_candidates, under_candidates;\n            for (int i=0; i<N_CONST; ++i) {\n                if (current_t[i] > T[i]) over_candidates.push_back({i, (double)current_t[i] - T[i]});\n                else if (current_t[i] < T[i]) under_candidates.push_back({i, (double)T[i] - current_t[i]});\n            }\n            if (over_candidates.empty() || under_candidates.empty()) return false;\n            \n            double total_over_w = 0; for(const auto& p : over_candidates) total_over_w += p.second;\n            double r_over = rng.next_double() * total_over_w;\n            int v = -1;\n            for(const auto& p : over_candidates) { r_over -= p.second; if(r_over <= 0) {v = p.first; break;} }\n            if (v == -1) v = over_candidates.back().first;\n\n            double total_under_w = 0; for(const auto& p : under_candidates) total_under_w += p.second;\n            double r_under = rng.next_double() * total_under_w;\n            int w = -1;\n            for(const auto& p : under_candidates) { r_under -= p.second; if(r_under <= 0) {w = p.first; break;} }\n            if (w == -1) w = under_candidates.back().first;\n            \n            std::vector<std::tuple<int, int, double>> active_edges;\n            for (int u = 0; u < N_CONST; ++u) {\n                if (a[u] == v && current_count_a[u] > 0) active_edges.emplace_back(u, 0, current_count_a[u]);\n                if (b[u] == v && current_count_b[u] > 0) active_edges.emplace_back(u, 1, current_count_b[u]);\n            }\n            if (active_edges.empty()) return false;\n\n            double total_edge_w = 0; for(const auto& t : active_edges) total_edge_w += std::get<2>(t);\n            double r_edge = rng.next_double() * total_edge_w;\n            const auto* edge_to_change = &active_edges.back();\n            for(const auto& t : active_edges) { r_edge -= std::get<2>(t); if(r_edge <= 0) {edge_to_change = &t; break;} }\n\n            int u = std::get<0>(*edge_to_change), ab = std::get<1>(*edge_to_change);\n            if (ab == 0) target_a[u] = w; else target_b[u] = w;\n            return true;\n        };\n\n        for (int i = 0; i < ITERS_PER_RUN && timer.get_elapsed_sec() < TIME_LIMIT_SEC; ++i) {\n            double progress = (double)i / ITERS_PER_RUN;\n            double temp = T_start * std::pow(T_end / T_start, progress);\n\n            std::vector<int> next_a = a, next_b = b;\n            \n            if (rng.next_double() < 0.05) {\n                make_random_move(next_a, next_b);\n            } else {\n                if (!make_weighted_smart_move(next_a, next_b)) {\n                    make_random_move(next_a, next_b);\n                }\n            }\n            \n            auto neighbor_eval = evaluate(next_a, next_b, T);\n            long long neighbor_error = neighbor_eval.error;\n            double delta_e = static_cast<double>(neighbor_error) - current_error;\n\n            if (delta_e <= 0 || rng.next_double() < std::exp(-delta_e / temp)) {\n                a = std::move(next_a);\n                b = std::move(next_b);\n                current_error = neighbor_error;\n                current_t = std::move(neighbor_eval.t);\n                current_count_a = std::move(neighbor_eval.count_a);\n                current_count_b = std::move(neighbor_eval.count_b);\n                if (current_error < run_best_error) {\n                    run_best_error = current_error;\n                    run_best_a = a;\n                    run_best_b = b;\n                }\n            }\n        }\n\n        // Update global best\n        if (run_best_error < global_best_error) {\n            global_best_error = run_best_error;\n            global_best_a = run_best_a;\n            global_best_b = run_best_b;\n        }\n\n        // Perturbation for next run\n        a = run_best_a;\n        b = run_best_b;\n        const int PERTURB_STRENGTH = 10;\n        for (int k = 0; k < PERTURB_STRENGTH; ++k) {\n            make_random_move(a, b);\n        }\n    }\n\n    for (int i = 0; i < N_CONST; ++i) {\n        std::cout << global_best_a[i] << \" \" << global_best_b[i] << \"\\n\";\n    }\n    \n    return 0;\n}","ahc045":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <set>\n#include <map>\n#include <queue>\n#include <tuple>\n#include <chrono>\n\n// Start timer\nauto start_time = std::chrono::high_resolution_clock::now();\ndouble time_limit = 1.95; // seconds\n\nstruct City {\n    int id;\n    long long lx, rx, ly, ry;\n    long long cx, cy;\n};\n\n// Z-order curve (Morton code)\nuint64_t z_order(uint32_t x, uint32_t y) {\n    uint64_t z = 0;\n    x &= 0x7FFF; // Max coord is 10000, 15 bits are enough\n    y &= 0x7FFF;\n    for (int i = 0; i < 15; ++i) {\n        z |= (static_cast<uint64_t>(x) & (1u << i)) << (i + 1);\n        z |= (static_cast<uint64_t>(y) & (1u << i)) << i;\n    }\n    return z;\n}\n\nstruct DSU {\n    std::vector<int> parent;\n    DSU(int n) {\n        parent.resize(n);\n        std::iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int i) {\n        if (parent[i] == i)\n            return i;\n        return parent[i] = find(parent[i]);\n    }\n    void unite(int i, int j) {\n        int root_i = find(i);\n        int root_j = find(j);\n        if (root_i != root_j) {\n            parent[root_i] = root_j;\n        }\n    }\n};\n\n// Use expected squared distance for estimations\nlong double expected_dist_sq(const City& a, const City& b) {\n    long double w_a = a.rx - a.lx;\n    long double w_b = b.rx - b.lx;\n    long double h_a = a.ry - a.ly;\n    long double h_b = b.ry - b.ly;\n\n    long double var_x_a = w_a * w_a / 12.0;\n    long double var_x_b = w_b * w_b / 12.0;\n    long double var_y_a = h_a * h_a / 12.0;\n    long double var_y_b = h_b * h_b / 12.0;\n\n    long double mean_x_a = a.lx + w_a / 2.0;\n    long double mean_x_b = b.lx + w_b / 2.0;\n    long double mean_y_a = a.ly + h_a / 2.0;\n    long double mean_y_b = b.ly + h_b / 2.0;\n    \n    long double dx = mean_x_a - mean_x_b;\n    long double dy = mean_y_a - mean_y_b;\n    \n    return var_x_a + var_x_b + dx * dx + var_y_a + var_y_b + dy * dy;\n}\n\nstd::vector<std::pair<int, int>> do_query(const std::vector<int>& c) {\n    std::cout << \"? \" << c.size();\n    for (int city_id : c) {\n        std::cout << \" \" << city_id;\n    }\n    std::cout << std::endl;\n\n    std::vector<std::pair<int, int>> edges;\n    if (c.size() > 1) {\n        for (size_t i = 0; i < c.size() - 1; ++i) {\n            int u, v;\n            std::cin >> u >> v;\n            edges.emplace_back(u, v);\n        }\n    }\n    return edges;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    \n    std::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\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<City> cities(N);\n    for (int i = 0; i < N; ++i) {\n        cities[i].id = i;\n        std::cin >> cities[i].lx >> cities[i].rx >> cities[i].ly >> cities[i].ry;\n        cities[i].cx = (cities[i].lx + cities[i].rx) / 2;\n        cities[i].cy = (cities[i].ly + cities[i].ry) / 2;\n    }\n\n    // 1. Grouping\n    std::vector<int> city_indices(N);\n    std::iota(city_indices.begin(), city_indices.end(), 0);\n    std::sort(city_indices.begin(), city_indices.end(), [&](int a, int b) {\n        return z_order(cities[a].cx, cities[a].cy) < z_order(cities[b].cx, cities[b].cy);\n    });\n    \n    std::vector<std::vector<int>> groups(M);\n    int current_city_idx = 0;\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < G[i]; ++j) {\n            groups[i].push_back(city_indices[current_city_idx++]);\n        }\n    }\n    \n    // 2. Querying\n    int queries_left = Q;\n    DSU global_dsu(N);\n    std::vector<std::pair<int, int>> known_edges_per_group[M];\n    \n    // Phase 0: Initial queries for small groups\n    for(int k=0; k<M; ++k) {\n        if (queries_left > 0 && G[k] >= 2 && G[k] <= L) {\n            auto edges = do_query(groups[k]);\n            queries_left--;\n            for (const auto& edge : edges) {\n                known_edges_per_group[k].push_back(edge);\n                global_dsu.unite(edge.first, edge.second);\n            }\n        }\n    }\n\n    // Phase 1: Connectivity for large groups\n    std::vector<std::tuple<long double, int, int, int>> mst_edges_to_verify;\n    for (int k = 0; k < M; ++k) {\n        if (G[k] <= L) continue;\n        const auto& group_cities = groups[k];\n        std::vector<std::tuple<long double, int, int>> candidate_edges;\n        for (size_t i = 0; i < group_cities.size(); ++i) {\n            for (size_t j = i + 1; j < group_cities.size(); ++j) {\n                int u = group_cities[i];\n                int v = group_cities[j];\n                candidate_edges.emplace_back(expected_dist_sq(cities[u], cities[v]), u, v);\n            }\n        }\n        std::sort(candidate_edges.begin(), candidate_edges.end());\n\n        DSU mst_dsu(N);\n        for (const auto& [w, u, v] : candidate_edges) {\n            if (mst_dsu.find(u) != mst_dsu.find(v)) {\n                mst_dsu.unite(u, v);\n                mst_edges_to_verify.emplace_back(w, u, v, k);\n            }\n        }\n    }\n    std::sort(mst_edges_to_verify.begin(), mst_edges_to_verify.end());\n\n    for (const auto& [w, u, v, k] : mst_edges_to_verify) {\n        if (queries_left == 0) break;\n        auto now = std::chrono::high_resolution_clock::now();\n        if (std::chrono::duration<double>(now - start_time).count() > time_limit) break;\n\n        if (global_dsu.find(u) != global_dsu.find(v)) {\n            std::vector<int> query_cities;\n            query_cities.push_back(u);\n            query_cities.push_back(v);\n            \n            long long mid_x = (cities[u].cx + cities[v].cx) / 2;\n            long long mid_y = (cities[u].cy + cities[v].cy) / 2;\n            \n            std::vector<std::pair<long long, int>> dist_to_mid;\n            for (int city_id : groups[k]) {\n                if (city_id == u || city_id == v) continue;\n                long long dx = cities[city_id].cx - mid_x;\n                long long dy = cities[city_id].cy - mid_y;\n                dist_to_mid.push_back({dx * dx + dy * dy, city_id});\n            }\n            std::sort(dist_to_mid.begin(), dist_to_mid.end());\n            for (size_t i = 0; i < dist_to_mid.size() && query_cities.size() < (size_t)L; ++i) {\n                query_cities.push_back(dist_to_mid[i].second);\n            }\n\n            auto edges = do_query(query_cities);\n            queries_left--;\n            for (const auto& edge : edges) {\n                known_edges_per_group[k].push_back(edge);\n                global_dsu.unite(edge.first, edge.second);\n            }\n        }\n    }\n    \n    // Phase 2: Improvement for large groups\n    if (queries_left > 0) {\n        std::vector<std::tuple<long double, int, int, int>> improvement_candidates;\n        for (int k = 0; k < M; ++k) {\n            if (G[k] <= L) continue;\n\n            DSU group_dsu_known(N);\n            for(const auto& edge : known_edges_per_group[k]){\n                group_dsu_known.unite(edge.first, edge.second);\n            }\n\n            std::map<int, std::vector<int>> components;\n            for (int city_id : groups[k]) {\n                components[group_dsu_known.find(city_id)].push_back(city_id);\n            }\n\n            if (components.size() > 1) {\n                std::vector<std::tuple<long double, int, int>> component_edges;\n                auto it1 = components.begin();\n                while (it1 != components.end()) {\n                    auto it2 = std::next(it1);\n                    while (it2 != components.end()) {\n                        for (int c1 : it1->second) {\n                            for (int c2 : it2->second) {\n                                component_edges.emplace_back(expected_dist_sq(cities[c1], cities[c2]), c1, c2);\n                            }\n                        }\n                        it2++;\n                    }\n                    it1++;\n                }\n                std::sort(component_edges.begin(), component_edges.end());\n                \n                for (const auto& [w, c1, c2] : component_edges) {\n                    if (group_dsu_known.find(c1) != group_dsu_known.find(c2)) {\n                        group_dsu_known.unite(c1, c2);\n                        improvement_candidates.emplace_back(w, c1, c2, k);\n                    }\n                }\n            }\n        }\n        std::sort(improvement_candidates.rbegin(), improvement_candidates.rend()); \n\n        for (const auto& [w, u, v, k] : improvement_candidates) {\n            if (queries_left == 0) break;\n            auto now = std::chrono::high_resolution_clock::now();\n            if (std::chrono::duration<double>(now - start_time).count() > time_limit) break;\n\n            std::vector<int> query_cities;\n            query_cities.push_back(u);\n            query_cities.push_back(v);\n            \n            long long mid_x = (cities[u].cx + cities[v].cx) / 2;\n            long long mid_y = (cities[u].cy + cities[v].cy) / 2;\n            \n            std::vector<std::pair<long long, int>> dist_to_mid;\n            for (int city_id : groups[k]) {\n                if (city_id == u || city_id == v) continue;\n                long long dx = cities[city_id].cx - mid_x;\n                long long dy = cities[city_id].cy - mid_y;\n                dist_to_mid.push_back({dx * dx + dy * dy, city_id});\n            }\n            std::sort(dist_to_mid.begin(), dist_to_mid.end());\n            for (size_t i = 0; i < dist_to_mid.size() && query_cities.size() < (size_t)L; ++i) {\n                query_cities.push_back(dist_to_mid[i].second);\n            }\n            \n            auto edges = do_query(query_cities);\n            queries_left--;\n            for (const auto& edge : edges) {\n                known_edges_per_group[k].push_back(edge);\n            }\n        }\n    }\n\n\n    // 3. Output\n    std::cout << \"!\" << std::endl;\n    for (int k = 0; k < M; ++k) {\n        for (size_t i = 0; i < groups[k].size(); ++i) {\n            std::cout << groups[k][i] << (i == groups[k].size() - 1 ? \"\" : \" \");\n        }\n        std::cout << std::endl;\n\n        if (G[k] > 1) {\n            std::vector<std::pair<int, int>> final_edges;\n            DSU group_dsu(N);\n            \n            std::sort(known_edges_per_group[k].begin(), known_edges_per_group[k].end());\n            known_edges_per_group[k].erase(std::unique(known_edges_per_group[k].begin(), known_edges_per_group[k].end()), known_edges_per_group[k].end());\n\n            for (const auto& edge : known_edges_per_group[k]) {\n                if (group_dsu.find(edge.first) != group_dsu.find(edge.second)) {\n                    group_dsu.unite(edge.first, edge.second);\n                    final_edges.push_back(edge);\n                }\n            }\n\n            if ((int)final_edges.size() < G[k] - 1) {\n                std::map<int, std::vector<int>> components;\n                for (int city_id : groups[k]) {\n                    components[group_dsu.find(city_id)].push_back(city_id);\n                }\n\n                if (components.size() > 1) {\n                    std::vector<std::tuple<long double, int, int>> component_edges;\n                    auto it1 = components.begin();\n                    while (it1 != components.end()) {\n                        auto it2 = std::next(it1);\n                        while (it2 != components.end()) {\n                            for (int c1 : it1->second) {\n                                for (int c2 : it2->second) {\n                                    component_edges.emplace_back(expected_dist_sq(cities[c1], cities[c2]), c1, c2);\n                                }\n                            }\n                            it2++;\n                        }\n                        it1++;\n                    }\n                    std::sort(component_edges.begin(), component_edges.end());\n                    \n                    for (const auto& [w, c1, c2] : component_edges) {\n                        if (group_dsu.find(c1) != group_dsu.find(c2)) {\n                            group_dsu.unite(c1, c2);\n                            final_edges.emplace_back(c1, c2);\n                        }\n                        if ((int)final_edges.size() >= G[k] - 1) break;\n                    }\n                }\n            }\n\n            for (const auto& edge : final_edges) {\n                std::cout << edge.first << \" \" << edge.second << std::endl;\n            }\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <map>\n#include <set>\n#include <cmath>\n#include <algorithm>\n#include <tuple>\n\nusing namespace std;\n\nconst int N = 20;\nconst int M = 40;\nconst int K = 20; // Max blocks allowed\n\nstruct Pos {\n    int r, c;\n    bool operator<(const Pos& other) const { if (r != other.r) return r < other.r; return c < other.c; }\n    bool operator==(const Pos& other) const { return r == other.r && c == other.c; }\n};\n\nint manhattan_distance(const Pos& a, const Pos& b) { return abs(a.r - b.r) + abs(a.c - b.c); }\nbool is_valid(const Pos& p) { return p.r >= 0 && p.r < N && p.c >= 0 && p.c < N; }\n\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\nconst char dir_char[] = {'U', 'D', 'L', 'R'};\n\nstruct Action { char act, dir; };\n\nmap<Pos, int> dijkstra(const Pos& start, const set<Pos>& blocks) {\n    map<Pos, int> dist;\n    priority_queue<pair<int, Pos>, vector<pair<int, Pos>>, greater<pair<int, Pos>>> pq;\n    if (blocks.count(start)) return dist;\n    dist[start] = 0;\n    pq.push({0, start});\n    while (!pq.empty()) {\n        auto [cost, pos] = pq.top(); pq.pop();\n        if (cost > dist.at(pos)) continue;\n        for (int i = 0; i < 4; ++i) { // Move\n            Pos next_pos = {pos.r + dr[i], pos.c + dc[i]};\n            if (is_valid(next_pos) && !blocks.count(next_pos)) {\n                int next_cost = cost + 1;\n                if (!dist.count(next_pos) || next_cost < dist.at(next_pos)) {\n                    dist[next_pos] = next_cost; pq.push({next_cost, next_pos});\n                }\n            }\n        }\n        for (int i = 0; i < 4; ++i) { // Slide\n            Pos stop_pos = pos; Pos next_pos = {stop_pos.r + dr[i], stop_pos.c + dc[i]};\n            while (is_valid(next_pos) && !blocks.count(next_pos)) { stop_pos = next_pos; next_pos = {stop_pos.r + dr[i], stop_pos.c + dc[i]}; }\n            if (stop_pos == pos) continue;\n            int next_cost = cost + 1;\n            if (!dist.count(stop_pos) || next_cost < dist.at(stop_pos)) {\n                dist[stop_pos] = next_cost; pq.push({next_cost, stop_pos});\n            }\n        }\n    }\n    return dist;\n}\n\npair<int, vector<Action>> a_star_full(const Pos& start, const Pos& end, const set<Pos>& blocks) {\n    if (start == end) return {0, {}};\n    if (blocks.count(end)) return {1000000, {}};\n    map<Pos, int> dist; map<Pos, Action> parent_action; map<Pos, Pos> parent_pos;\n    priority_queue<pair<int, Pos>, vector<pair<int, Pos>>, greater<pair<int, Pos>>> pq;\n    dist[start] = 0; pq.push({manhattan_distance(start, end), start});\n    while (!pq.empty()) {\n        auto [est_cost_pq, pos] = pq.top(); pq.pop();\n        int cost = dist.at(pos);\n        if (dist.count(pos) && cost > dist.at(pos)) continue;\n        if (pos == end) {\n            vector<Action> actions; Pos curr = end;\n            while (!(curr == start)) { actions.push_back(parent_action.at(curr)); curr = parent_pos.at(curr); }\n            reverse(actions.begin(), actions.end()); return {cost, actions};\n        }\n        for (int i = 0; i < 4; ++i) { // Move\n            Pos next_pos = {pos.r + dr[i], pos.c + dc[i]};\n            if (is_valid(next_pos) && !blocks.count(next_pos)) {\n                int next_cost = cost + 1;\n                if (!dist.count(next_pos) || next_cost < dist.at(next_pos)) {\n                    dist[next_pos] = next_cost; parent_pos[next_pos] = pos; parent_action[next_pos] = {'M', dir_char[i]};\n                    pq.push({next_cost + manhattan_distance(next_pos, end), next_pos});\n                }\n            }\n        }\n        for (int i = 0; i < 4; ++i) { // Slide\n            Pos stop_pos = pos; Pos next_pos = {stop_pos.r + dr[i], stop_pos.c + dc[i]};\n            while (is_valid(next_pos) && !blocks.count(next_pos)) { stop_pos = next_pos; next_pos = {stop_pos.r + dr[i], stop_pos.c + dc[i]}; }\n            if (stop_pos == pos) continue;\n            int next_cost = cost + 1;\n            if (!dist.count(stop_pos) || next_cost < dist.at(stop_pos)) {\n                dist[stop_pos] = next_cost; parent_pos[stop_pos] = pos; parent_action[stop_pos] = {'S', dir_char[i]};\n                pq.push({next_cost + manhattan_distance(stop_pos, end), stop_pos});\n            }\n        }\n    }\n    return {1000000, {}};\n}\n\nPos find_block_to_evict(const set<Pos>& current_blocks, int future_target_idx, const vector<Pos>& all_targets) {\n    Pos to_evict; long long max_score = -1;\n    for (const auto& b : current_blocks) {\n        long long current_score = 0;\n        for (size_t i = future_target_idx; i < all_targets.size(); ++i) current_score += manhattan_distance(b, all_targets[i]);\n        if (current_score > max_score) { max_score = current_score; to_evict = b; }\n    }\n    return to_evict;\n}\n\nstruct Plan {\n    char type; int cost; set<Pos> final_blocks;\n    vector<Action> path_actions;\n    Pos alter_block, alter_adj;\n};\n\nint main() {\n    ios_base::sync_with_stdio(false); cin.tie(NULL);\n    int N_in, M_in; cin >> N_in >> M_in;\n    vector<Pos> targets(M); for (int i = 0; i < M; ++i) cin >> targets[i].r >> targets[i].c;\n\n    Pos current_pos = targets[0];\n    set<Pos> blocks;\n    vector<Action> total_actions;\n\n    for (int k = 0; k < M - 1; ++k) {\n        Pos start_node = current_pos; Pos end_node = targets[k + 1];\n\n        vector<Plan> best_plans; int min_cost = 1000000;\n\n        // Baseline plan\n        auto [cost, path] = a_star_full(start_node, end_node, blocks);\n        if (cost < min_cost) { min_cost = cost; best_plans.clear(); }\n        if (cost == min_cost) best_plans.push_back({'B', cost, blocks, path, {}, {}});\n\n        auto dist_from_start = dijkstra(start_node, blocks);\n        map<Pos, int> dist_from_end_for_penalty;\n        if (blocks.size() >= K) dist_from_end_for_penalty = dijkstra(end_node, blocks);\n\n        set<Pos> cand_stop_points;\n        cand_stop_points.insert(end_node);\n        cand_stop_points.insert({start_node.r, end_node.c});\n        cand_stop_points.insert({end_node.r, start_node.c});\n        if (k + 2 < M) {\n            Pos next_target = targets[k+2];\n            cand_stop_points.insert(next_target);\n            cand_stop_points.insert({end_node.r, next_target.c});\n            cand_stop_points.insert({next_target.r, end_node.c});\n        }\n        \n        set<Pos> cand_add_blocks;\n        for(const auto& sp : cand_stop_points) {\n            for(int i=0; i<4; ++i) {\n                Pos b = {sp.r + dr[i], sp.c + dc[i]};\n                if (is_valid(b)) cand_add_blocks.insert(b);\n            }\n        }\n\n        // Add-1 plans\n        for (const auto& b : cand_add_blocks) {\n            if (blocks.count(b)) continue;\n            set<Pos> next_blocks = blocks; next_blocks.insert(b);\n            auto dist_to_end = dijkstra(end_node, next_blocks);\n            for (int i = 0; i < 4; ++i) {\n                Pos adj_b = {b.r - dr[i], b.c - dc[i]};\n                if (is_valid(adj_b) && !blocks.count(adj_b) && dist_from_start.count(adj_b) && dist_to_end.count(adj_b)) {\n                    int current_cost = dist_from_start.at(adj_b) + 1 + dist_to_end.at(adj_b);\n                    int penalized_cost = current_cost;\n                    if (blocks.size() >= K) {\n                        Pos to_evict = find_block_to_evict(next_blocks, k + 2, targets);\n                        int eviction_penalty = 1000000;\n                        for (int i_ev = 0; i_ev < 4; ++i_ev) {\n                            Pos adj_ev = {to_evict.r - dr[i_ev], to_evict.c - dc[i_ev]};\n                            if (is_valid(adj_ev) && adj_ev != b && dist_from_end_for_penalty.count(adj_ev)) {\n                                eviction_penalty = min(eviction_penalty, dist_from_end_for_penalty.at(adj_ev) + 1);\n                            }\n                        }\n                        penalized_cost += (eviction_penalty < 1000000) ? eviction_penalty : N*N;\n                    }\n                    if (penalized_cost < min_cost) { min_cost = penalized_cost; best_plans.clear(); }\n                    if (penalized_cost == min_cost) best_plans.push_back({'A', current_cost, next_blocks, {}, b, adj_b});\n                }\n            }\n        }\n\n        // Remove-1 plans\n        for (const auto& b : blocks) {\n            set<Pos> next_blocks = blocks; next_blocks.erase(b);\n            auto dist_to_end = dijkstra(end_node, next_blocks);\n            for (int i = 0; i < 4; ++i) {\n                Pos adj_b = {b.r - dr[i], b.c - dc[i]};\n                if (is_valid(adj_b) && !blocks.count(adj_b) && dist_from_start.count(adj_b) && dist_to_end.count(adj_b)) {\n                    int rem_cost = dist_from_start.at(adj_b) + 1 + dist_to_end.at(adj_b);\n                    if (rem_cost < min_cost) { min_cost = rem_cost; best_plans.clear(); }\n                    if (rem_cost == min_cost) best_plans.push_back({'R', rem_cost, next_blocks, {}, b, adj_b});\n                }\n            }\n        }\n        \n        Plan final_plan = best_plans[0];\n        if (best_plans.size() > 1 && k + 2 < M) {\n            int best_future_cost = 1000000;\n            Pos next_end_node = targets[k + 2];\n            for (const auto& plan : best_plans) {\n                auto [future_cost, _] = a_star_full(end_node, next_end_node, plan.final_blocks);\n                if (future_cost < best_future_cost) { best_future_cost = future_cost; final_plan = plan; }\n            }\n        }\n        \n        if (final_plan.type == 'B') {\n            total_actions.insert(total_actions.end(), final_plan.path_actions.begin(), final_plan.path_actions.end());\n        } else {\n            auto [c1, p1] = a_star_full(start_node, final_plan.alter_adj, blocks);\n            total_actions.insert(total_actions.end(), p1.begin(), p1.end());\n            char alter_dir = ' ';\n            for (int j=0; j<4; ++j) if(final_plan.alter_block.r==final_plan.alter_adj.r+dr[j] && final_plan.alter_block.c==final_plan.alter_adj.c+dc[j]) alter_dir=dir_char[j];\n            total_actions.push_back({'A', alter_dir});\n            auto [c2, p2] = a_star_full(final_plan.alter_adj, end_node, final_plan.final_blocks);\n            total_actions.insert(total_actions.end(), p2.begin(), p2.end());\n        }\n        blocks = final_plan.final_blocks;\n        current_pos = end_node;\n\n        if (blocks.size() > K) {\n            Pos to_evict = find_block_to_evict(blocks, k + 2, targets);\n            Pos adj_to_evict; int min_dist = 1000000;\n            auto dist_from_curr = dijkstra(current_pos, blocks);\n            for (int i = 0; i < 4; ++i) {\n                Pos adj_b = {to_evict.r - dr[i], to_evict.c - dc[i]};\n                if (is_valid(adj_b) && !blocks.count(adj_b) && dist_from_curr.count(adj_b)) {\n                    if (dist_from_curr.at(adj_b) < min_dist) { min_dist = dist_from_curr.at(adj_b); adj_to_evict = adj_b; }\n                }\n            }\n            if (min_dist < 1000000) {\n                auto [c, p] = a_star_full(current_pos, adj_to_evict, blocks);\n                total_actions.insert(total_actions.end(), p.begin(), p.end());\n                current_pos = adj_to_evict;\n                char alter_dir = ' ';\n                for(int j=0; j<4; ++j) if(to_evict.r==current_pos.r+dr[j] && to_evict.c==current_pos.c+dc[j]) alter_dir=dir_char[j];\n                total_actions.push_back({'A', alter_dir});\n                blocks.erase(to_evict);\n            }\n        }\n    }\n\n    for (const auto& action : total_actions) cout << action.act << \" \" << action.dir << \"\\n\";\n    return 0;\n}"},"16":{"ahc001":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <cfloat>\n#include <chrono>\n#include <random>\n\n// --- Utilities and Structs ---\nstruct Company {\n    int id;\n    int x, y;\n    long long r;\n};\n\nstruct Rect {\n    int x1, y1, x2, y2;\n};\n\nstruct PointBox {\n    int min_x = 10001, min_y = 10001, max_x = -1, max_y = -1;\n    void update(const Company& c) {\n        min_x = std::min(min_x, c.x);\n        min_y = std::min(min_y, c.y);\n        max_x = std::max(max_x, c.x);\n        max_y = std::max(max_y, c.y);\n    }\n    void merge(const PointBox& other) {\n        min_x = std::min(min_x, other.min_x);\n        min_y = std::min(min_y, other.min_y);\n        max_x = std::max(max_x, other.max_x);\n        max_y = std::max(max_y, other.max_y);\n    }\n};\n\nstruct Node {\n    bool is_leaf = false;\n    int company_id = -1;\n\n    // For internal nodes\n    int parent = -1;\n    bool is_vertical = false;\n    int split_coord = 0;\n    int children[2] = {-1, -1};\n    std::vector<int> company_indices;\n    PointBox pbox;\n};\n\n// --- Global State ---\nint N;\nstd::vector<Company> companies;\nstd::vector<bool> is_in_partition1; // Temporary helper for partitioning\n\n// --- For SA ---\nstd::vector<Node> tree;\nstd::vector<int> internal_node_indices;\nstd::mt19937 rnd;\nstd::chrono::time_point<std::chrono::high_resolution_clock> start_time_chrono;\nstd::vector<Rect> best_result;\ndouble best_score = -1.0;\nstd::vector<Rect> current_result;\ndouble current_score;\n\n// --- Helper Functions ---\ndouble get_time() {\n    return std::chrono::duration<double>(std::chrono::high_resolution_clock::now() - start_time_chrono).count();\n}\n\ndouble calculate_satisfaction(long long s, long long r) {\n    if (s <= 0 || r <= 0) return 0;\n    double ratio = std::min((double)s / r, (double)r / s);\n    double error = 1.0 - ratio;\n    return 1.0 - error * error;\n}\n\ndouble calculate_total_score(const std::vector<Rect>& rects) {\n    double total_sat = 0;\n    for (int i = 0; i < N; ++i) {\n        long long s = (long long)(rects[i].x2 - rects[i].x1) * (rects[i].y2 - rects[i].y1);\n        total_sat += calculate_satisfaction(s, companies[i].r);\n    }\n    return total_sat;\n}\n\n// --- Core Algorithm: Greedy Construction + SA ---\n\nint build_tree(int x1, int y1, int x2, int y2, std::vector<int>& indices_by_x, std::vector<int>& indices_by_y, int parent_idx) {\n    int n = indices_by_x.size();\n    int current_node_idx = tree.size();\n    tree.emplace_back();\n    tree[current_node_idx].parent = parent_idx;\n    \n    if (n == 0) return -1;\n\n    if (n == 1) {\n        int company_idx = indices_by_x[0];\n        tree[current_node_idx].is_leaf = true;\n        tree[current_node_idx].company_id = company_idx;\n        tree[current_node_idx].company_indices = {company_idx};\n        tree[current_node_idx].pbox.update(companies[company_idx]);\n        return current_node_idx;\n    }\n\n    int best_k_v = -1, best_x_split = -1;\n    double min_badness_v = DBL_MAX;\n    long long total_r = 0;\n    for (int idx : indices_by_x) total_r += companies[idx].r;\n    \n    if (companies[indices_by_x.front()].x < companies[indices_by_x.back()].x) {\n        long long current_r_sum = 0;\n        for (int k = 1; k < n; ++k) {\n            current_r_sum += companies[indices_by_x[k - 1]].r;\n            if (companies[indices_by_x[k - 1]].x < companies[indices_by_x[k]].x) {\n                double target_ratio = (double)current_r_sum / total_r;\n                double ideal_x_split = x1 + (double)(x2 - x1) * target_ratio;\n                int lower_bound = companies[indices_by_x[k - 1]].x + 1;\n                int upper_bound = companies[indices_by_x[k]].x;\n                \n                std::vector<int> candidates;\n                candidates.push_back(std::max(lower_bound, std::min(upper_bound, (int)round(ideal_x_split))));\n                candidates.push_back(lower_bound);\n                candidates.push_back(upper_bound);\n                std::sort(candidates.begin(), candidates.end());\n                candidates.erase(std::unique(candidates.begin(), candidates.end()), candidates.end());\n\n                for (int x_split : candidates) {\n                    double actual_ratio = (x2 - x1 == 0) ? 0.5 : (double)(x_split - x1) / (x2 - x1);\n                    double badness = std::pow(actual_ratio - target_ratio, 2);\n                    if (badness < min_badness_v) {\n                        min_badness_v = badness;\n                        best_k_v = k;\n                        best_x_split = x_split;\n                    }\n                }\n            }\n        }\n    }\n\n    int best_k_h = -1, best_y_split = -1;\n    double min_badness_h = DBL_MAX;\n    if (companies[indices_by_y.front()].y < companies[indices_by_y.back()].y) {\n        long long current_r_sum = 0;\n        for (int k = 1; k < n; ++k) {\n            current_r_sum += companies[indices_by_y[k - 1]].r;\n            if (companies[indices_by_y[k - 1]].y < companies[indices_by_y[k]].y) {\n                double target_ratio = (double)current_r_sum / total_r;\n                double ideal_y_split = y1 + (double)(y2 - y1) * target_ratio;\n                int lower_bound = companies[indices_by_y[k - 1]].y + 1;\n                int upper_bound = companies[indices_by_y[k]].y;\n\n                std::vector<int> candidates;\n                candidates.push_back(std::max(lower_bound, std::min(upper_bound, (int)round(ideal_y_split))));\n                candidates.push_back(lower_bound);\n                candidates.push_back(upper_bound);\n                std::sort(candidates.begin(), candidates.end());\n                candidates.erase(std::unique(candidates.begin(), candidates.end()), candidates.end());\n                \n                for (int y_split : candidates) {\n                     double actual_ratio = (y2 - y1 == 0) ? 0.5 : (double)(y_split - y1) / (y2 - y1);\n                     double badness = std::pow(actual_ratio - target_ratio, 2);\n                     if (badness < min_badness_h) {\n                         min_badness_h = badness;\n                         best_k_h = k;\n                         best_y_split = y_split;\n                     }\n                }\n            }\n        }\n    }\n\n    bool perform_vertical_split;\n    if (best_k_v == -1) {\n        perform_vertical_split = false;\n    } else if (best_k_h == -1) {\n        perform_vertical_split = true;\n    } else {\n        constexpr double TIE_TOLERANCE = 1.05;\n        if (min_badness_v < min_badness_h * TIE_TOLERANCE && min_badness_h < min_badness_v * TIE_TOLERANCE) {\n            perform_vertical_split = (x2 - x1) >= (y2 - y1);\n        } else {\n            perform_vertical_split = min_badness_v < min_badness_h;\n        }\n    }\n    \n    internal_node_indices.push_back(current_node_idx);\n    tree[current_node_idx].is_vertical = perform_vertical_split;\n    \n    if (perform_vertical_split) {\n        tree[current_node_idx].split_coord = best_x_split;\n        int k = best_k_v;\n        for (int i = 0; i < k; ++i) is_in_partition1[indices_by_x[i]] = true;\n        for (int i = k; i < n; ++i) is_in_partition1[indices_by_x[i]] = false;\n        std::vector<int> left_x(indices_by_x.begin(), indices_by_x.begin() + k);\n        std::vector<int> right_x(indices_by_x.begin() + k, indices_by_x.end());\n        std::vector<int> left_y, right_y;\n        for (int idx : indices_by_y) (is_in_partition1[idx] ? left_y : right_y).push_back(idx);\n        tree[current_node_idx].children[0] = build_tree(x1, y1, best_x_split, y2, left_x, left_y, current_node_idx);\n        tree[current_node_idx].children[1] = build_tree(best_x_split, y1, x2, y2, right_x, right_y, current_node_idx);\n    } else {\n        tree[current_node_idx].split_coord = best_y_split;\n        int k = best_k_h;\n        for (int i = 0; i < k; ++i) is_in_partition1[indices_by_y[i]] = true;\n        for (int i = k; i < n; ++i) is_in_partition1[indices_by_y[i]] = false;\n        std::vector<int> bottom_y(indices_by_y.begin(), indices_by_y.begin() + k);\n        std::vector<int> top_y(indices_by_y.begin() + k, indices_by_y.end());\n        std::vector<int> bottom_x, top_x;\n        for (int idx : indices_by_x) (is_in_partition1[idx] ? bottom_x : top_x).push_back(idx);\n        tree[current_node_idx].children[0] = build_tree(x1, y1, x2, best_y_split, bottom_x, bottom_y, current_node_idx);\n        tree[current_node_idx].children[1] = build_tree(x1, best_y_split, x2, y2, top_x, top_y, current_node_idx);\n    }\n\n    tree[current_node_idx].pbox = tree[tree[current_node_idx].children[0]].pbox;\n    tree[current_node_idx].pbox.merge(tree[tree[current_node_idx].children[1]].pbox);\n    tree[current_node_idx].company_indices = tree[tree[current_node_idx].children[0]].company_indices;\n    tree[current_node_idx].company_indices.insert(\n        tree[current_node_idx].company_indices.end(),\n        tree[tree[current_node_idx].children[1]].company_indices.begin(),\n        tree[tree[current_node_idx].children[1]].company_indices.end()\n    );\n    return current_node_idx;\n}\n\nvoid recompute_rects(int node_idx, const Rect& bbox, std::vector<Rect>& target_rects) {\n    if (node_idx == -1) return;\n    const auto& node = tree[node_idx];\n    if (node.is_leaf) {\n        target_rects[node.company_id] = bbox;\n        return;\n    }\n    if (node.is_vertical) {\n        recompute_rects(node.children[0], {bbox.x1, bbox.y1, node.split_coord, bbox.y2}, target_rects);\n        recompute_rects(node.children[1], {node.split_coord, bbox.y1, bbox.x2, bbox.y2}, target_rects);\n    } else {\n        recompute_rects(node.children[0], {bbox.x1, bbox.y1, bbox.x2, node.split_coord}, target_rects);\n        recompute_rects(node.children[1], {bbox.x1, node.split_coord, bbox.x2, bbox.y2}, target_rects);\n    }\n}\n\nRect get_bbox(int node_idx) {\n    if (tree[node_idx].parent == -1) return {0, 0, 10000, 10000};\n    const auto& parent = tree[tree[node_idx].parent];\n    Rect parent_bbox = get_bbox(tree[node_idx].parent);\n    bool is_child0 = (parent.children[0] == node_idx);\n    if (parent.is_vertical) {\n        return is_child0 ? Rect{parent_bbox.x1, parent_bbox.y1, parent.split_coord, parent_bbox.y2}\n                         : Rect{parent.split_coord, parent_bbox.y1, parent_bbox.x2, parent_bbox.y2};\n    } else {\n        return is_child0 ? Rect{parent_bbox.x1, parent_bbox.y1, parent_bbox.x2, parent.split_coord}\n                         : Rect{parent_bbox.x1, parent.split_coord, parent_bbox.x2, parent_bbox.y2};\n    }\n}\n\n\nvoid simulated_annealing() {\n    const double TIME_LIMIT = 4.95;\n    \n    current_score = calculate_total_score(current_result);\n    best_score = current_score;\n    best_result = current_result;\n    \n    double T_start = 0.1, T_end = 1e-9;\n    \n    std::uniform_int_distribution<int> node_dist(0, internal_node_indices.size() - 1);\n    std::uniform_real_distribution<double> accept_dist(0.0, 1.0);\n\n    while (true) {\n        double elapsed_time = get_time();\n        if (elapsed_time > TIME_LIMIT) break;\n\n        int node_idx = internal_node_indices[node_dist(rnd)];\n        auto& node = tree[node_idx];\n        \n        int c_old = node.split_coord;\n        int c_min, c_max;\n        if (node.is_vertical) {\n            c_min = tree[node.children[0]].pbox.max_x + 1;\n            c_max = tree[node.children[1]].pbox.min_x;\n        } else {\n            c_min = tree[node.children[0]].pbox.max_y + 1;\n            c_max = tree[node.children[1]].pbox.min_y;\n        }\n        \n        if (c_min > c_max) continue;\n        int range = c_max - c_min;\n        if (range == 0) continue;\n        \n        double progress = elapsed_time / TIME_LIMIT;\n        double W = std::max(1.0, 0.25 * static_cast<double>(range) * (1.0 - progress));\n        \n        std::uniform_int_distribution<int> delta_dist(-(int)W, (int)W);\n        int c_new = c_old + delta_dist(rnd);\n        c_new = std::max(c_min, std::min(c_max, c_new));\n\n        if (c_new == c_old) continue;\n        \n        double score_before_move = 0;\n        for (int company_idx : node.company_indices) {\n            const auto& rect = current_result[company_idx];\n            long long s = (long long)(rect.x2 - rect.x1) * (rect.y2 - rect.y1);\n            score_before_move += calculate_satisfaction(s, companies[company_idx].r);\n        }\n\n        node.split_coord = c_new;\n        Rect bbox = get_bbox(node_idx);\n        recompute_rects(node_idx, bbox, current_result);\n        \n        double score_after_move = 0;\n        for (int company_idx : node.company_indices) {\n            const auto& rect = current_result[company_idx];\n            long long s = (long long)(rect.x2 - rect.x1) * (rect.y2 - rect.y1);\n            score_after_move += calculate_satisfaction(s, companies[company_idx].r);\n        }\n\n        double delta_score = score_after_move - score_before_move;\n        double T = T_start * std::pow(T_end / T_start, progress);\n\n        if (delta_score > 0 || accept_dist(rnd) < std::exp(delta_score / T)) { // Accept\n            current_score += delta_score;\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_result = current_result;\n            }\n        } else { // Reject\n            node.split_coord = c_old;\n            recompute_rects(node_idx, bbox, current_result);\n        }\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    start_time_chrono = std::chrono::high_resolution_clock::now();\n    \n    rnd.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());\n    \n    std::cin >> N;\n    companies.resize(N);\n    is_in_partition1.resize(N);\n    tree.reserve(2 * N);\n\n    std::vector<int> indices_by_x(N), indices_by_y(N);\n    for (int i = 0; i < N; ++i) {\n        companies[i].id = i;\n        std::cin >> companies[i].x >> companies[i].y >> companies[i].r;\n        indices_by_x[i] = i;\n        indices_by_y[i] = i;\n    }\n\n    std::sort(indices_by_x.begin(), indices_by_x.end(), [&](int a, int b) {\n        if (companies[a].x != companies[b].x) return companies[a].x < companies[b].x;\n        return companies[a].y < companies[b].y;\n    });\n    std::sort(indices_by_y.begin(), indices_by_y.end(), [&](int a, int b) {\n        if (companies[a].y != companies[b].y) return companies[a].y < companies[b].y;\n        return companies[a].x < companies[b].x;\n    });\n\n    int root_node = build_tree(0, 0, 10000, 10000, indices_by_x, indices_by_y, -1);\n    \n    current_result.resize(N);\n    recompute_rects(root_node, {0, 0, 10000, 10000}, current_result);\n\n    simulated_annealing();\n\n    for (int i = 0; i < N; ++i) {\n        std::cout << best_result[i].x1 << \" \" << best_result[i].y1 << \" \" << best_result[i].x2 << \" \" << best_result[i].y2 << \"\\n\";\n    }\n\n    return 0;\n}","ahc002":"#include <iostream>\n#include <vector>\n#include <string>\n#include <map>\n#include <utility>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n\n// Fast I/O\nvoid fast_io() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n}\n\n// Timer\nstruct Timer {\n    std::chrono::steady_clock::time_point start_time;\n    Timer() : start_time(std::chrono::steady_clock::now()) {}\n    long long get_ms() {\n        return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count();\n    }\n};\n\nconstexpr int N = 50;\n\n#ifdef LOCAL_TEST\nconstexpr int TIME_LIMIT_MS = 1980;\nconstexpr int BEAM_WIDTH = 200;\n#else\nconstexpr int TIME_LIMIT_MS = 1980;\nconstexpr int BEAM_WIDTH = 2000;\n#endif\n\nint si, sj;\nint t[N][N];\nint p[N][N];\n\nstruct Tile {\n    int id;\n    std::vector<std::pair<int, int>> squares;\n};\n\nint tile_id_map[N][N];\nstd::vector<Tile> tiles;\nint M; // number of tiles\n\nstruct State {\n    long long score;\n    std::pair<int, int> pos;\n    std::vector<bool> visited_tiles;\n\n    int prev_idx_in_history;\n    std::string path_segment;\n};\n\nchar get_move_char(const std::pair<int, int>& from, const std::pair<int, int>& to) {\n    if (to.first == from.first - 1 && to.second == from.second) return 'U';\n    if (to.first == from.first + 1 && to.second == from.second) return 'D';\n    if (to.second == from.second - 1 && to.first == from.first) return 'L';\n    if (to.second == from.second + 1 && to.first == from.first) return 'R';\n    return ' '; // Should not happen\n}\n\nvoid solve() {\n    Timer timer;\n\n    std::cin >> si >> sj;\n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) std::cin >> t[i][j];\n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) std::cin >> p[i][j];\n\n    std::map<int, int> raw_id_to_my_id;\n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) {\n        if (raw_id_to_my_id.find(t[i][j]) == raw_id_to_my_id.end()) {\n            raw_id_to_my_id[t[i][j]] = raw_id_to_my_id.size();\n        }\n    }\n    M = raw_id_to_my_id.size();\n    tiles.resize(M);\n    for (int i=0; i<M; ++i) tiles[i].id = i;\n\n    for (int i=0; i<N; ++i) for(int j=0; j<N; ++j) {\n        int my_id = raw_id_to_my_id[t[i][j]];\n        tile_id_map[i][j] = my_id;\n        tiles[my_id].squares.push_back({i,j});\n    }\n\n    State initial_state;\n    int start_tile_id = tile_id_map[si][sj];\n    const auto& start_tile = tiles[start_tile_id];\n    \n    initial_state.score = 0;\n    initial_state.visited_tiles.assign(M, false);\n    initial_state.visited_tiles[start_tile_id] = true;\n    initial_state.prev_idx_in_history = -1;\n\n    std::pair<int, int> current_pos = {si, sj};\n    initial_state.score += p[si][sj];\n\n    if (start_tile.squares.size() == 2) {\n        std::pair<int, int> other_pos = (start_tile.squares[0] == current_pos) ? start_tile.squares[1] : start_tile.squares[0];\n        char move = get_move_char(current_pos, other_pos);\n        initial_state.path_segment += move;\n        initial_state.score += p[other_pos.first][other_pos.second];\n        current_pos = other_pos;\n    }\n    initial_state.pos = current_pos;\n\n    long long best_score = initial_state.score;\n    std::pair<int, int> best_state_locus = {0, 0};\n\n    std::vector<std::vector<State>> history;\n    std::vector<State> beam;\n    beam.push_back(std::move(initial_state));\n    history.push_back(std::move(beam));\n    \n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n    char move_chars[] = {'U', 'D', 'L', 'R'};\n\n    while (timer.get_ms() < TIME_LIMIT_MS) {\n        const auto& current_beam = history.back();\n        std::vector<State> candidates;\n        \n        for (int i = 0; i < current_beam.size(); ++i) {\n            const auto& s = current_beam[i];\n            int r = s.pos.first;\n            int c = s.pos.second;\n\n            for (int k = 0; k < 4; ++k) {\n                int nr = r + dr[k];\n                int nc = c + dc[k];\n\n                if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n\n                int next_tile_id = tile_id_map[nr][nc];\n                if (s.visited_tiles[next_tile_id]) continue;\n\n                State new_s;\n                new_s.visited_tiles = s.visited_tiles;\n                new_s.visited_tiles[next_tile_id] = true;\n\n                std::string path_ext;\n                long long score_ext = 0;\n                std::pair<int, int> next_pos = {nr, nc};\n\n                path_ext += move_chars[k];\n                score_ext += p[nr][nc];\n\n                const auto& next_tile = tiles[next_tile_id];\n                if (next_tile.squares.size() == 2) {\n                    std::pair<int, int> other_pos = (next_tile.squares[0] == next_pos) ? next_tile.squares[1] : next_tile.squares[0];\n                    char move = get_move_char(next_pos, other_pos);\n                    path_ext += move;\n                    score_ext += p[other_pos.first][other_pos.second];\n                    next_pos = other_pos;\n                }\n                \n                new_s.score = s.score + score_ext;\n                new_s.pos = next_pos;\n                new_s.path_segment = path_ext;\n                new_s.prev_idx_in_history = i;\n                candidates.push_back(std::move(new_s));\n            }\n        }\n\n        if (candidates.empty()) break;\n\n        size_t sort_end_idx = std::min((size_t)candidates.size(), (size_t)BEAM_WIDTH);\n        std::partial_sort(candidates.begin(), candidates.begin() + sort_end_idx, candidates.end(), \n            [](const State& a, const State& b){ return a.score > b.score; });\n\n        std::vector<State> next_beam;\n        next_beam.reserve(sort_end_idx);\n        for (int i = 0; i < sort_end_idx; ++i) {\n            next_beam.push_back(std::move(candidates[i]));\n        }\n        \n        if (next_beam[0].score > best_score) {\n            best_score = next_beam[0].score;\n            best_state_locus = {(int)history.size(), 0};\n        }\n        history.push_back(std::move(next_beam));\n    }\n    \n    std::string final_path = \"\";\n    int hist_idx = best_state_locus.first;\n    int beam_idx = best_state_locus.second;\n    while (hist_idx >= 0) {\n        const auto& s = history[hist_idx][beam_idx];\n        final_path = s.path_segment + final_path;\n        if (s.prev_idx_in_history == -1) break;\n        beam_idx = s.prev_idx_in_history;\n        hist_idx--;\n    }\n    std::cout << final_path << std::endl;\n}\n\nint main() {\n    fast_io();\n    solve();\n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <numeric>\n#include <random>\n#include <algorithm>\n#include <iomanip>\n#include <chrono>\n\n// Constants\nconstexpr int GRID_SIZE = 30;\nconstexpr int NUM_QUERIES = 1000;\n\n// Grid coordinates\nstruct Point {\n    int r, c;\n    bool operator==(const Point& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Point& other) const {\n        return !(*this == other);\n    }\n};\n\n// For priority queue in Dijkstra\nstruct State {\n    Point pos;\n    double dist;\n\n    bool operator>(const State& other) const {\n        return dist > other.dist;\n    }\n};\n\n// Global state for our estimates and models\ndouble est_h[GRID_SIZE][GRID_SIZE - 1]; // Raw estimates\ndouble est_v[GRID_SIZE - 1][GRID_SIZE];\ndouble model_h[GRID_SIZE][GRID_SIZE - 1]; // Smoothed/model-based estimates\ndouble model_v[GRID_SIZE - 1][GRID_SIZE];\nint updates_h[GRID_SIZE][GRID_SIZE - 1];\nint updates_v[GRID_SIZE - 1][GRID_SIZE];\nint global_M = 1; // Start with assumption M=1, decide definitively later\n\n// Randomness\nstd::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// Helper function to check bounds\nbool is_valid(int r, int c) {\n    return r >= 0 && r < GRID_SIZE && c >= 0 && c < GRID_SIZE;\n}\n\n// For model fitting\nstruct ModelFitResult {\n    double sse1 = 0.0;\n    double sse2 = 1e18;\n    int split_point = -1;\n    double mean1 = 5000.0;\n    double mean_l = 5000.0, mean_r = 5000.0;\n    int n_pts = 0;\n};\n\n// Dijkstra's algorithm\nPoint parent[GRID_SIZE][GRID_SIZE];\nchar move_char[GRID_SIZE][GRID_SIZE];\ndouble dist[GRID_SIZE][GRID_SIZE];\n\nstd::string find_path(Point start, Point goal, int k) {\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            dist[i][j] = 1e18;\n        }\n    }\n\n    std::priority_queue<State, std::vector<State>, std::greater<State>> pq;\n    dist[start.r][start.c] = 0;\n    pq.push({start, 0.0});\n\n    double progress = static_cast<double>(k) / (NUM_QUERIES - 1);\n    double C_k = 0.3 * (1.0 - std::pow(progress, 1.5));\n    if (k > NUM_QUERIES - 50) C_k = 0;\n    \n    double lambda_k = 500.0 * std::pow(1.0 - progress, 2.0);\n\n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n    char moves[] = {'U', 'D', 'L', 'R'};\n    \n    std::uniform_real_distribution<double> dist_expl(1.0 - C_k, 1.0 + C_k);\n\n    while (!pq.empty()) {\n        State current = pq.top();\n        pq.pop();\n        Point pos = current.pos;\n\n        if (current.dist > dist[pos.r][pos.c]) continue;\n        if (pos == goal) break;\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = pos.r + dr[i];\n            int nc = pos.c + dc[i];\n            if (!is_valid(nr, nc)) continue;\n\n            double edge_cost;\n            int updates_count;\n            if (i == 0) { // Up\n                edge_cost = model_v[nr][nc]; updates_count = updates_v[nr][nc];\n            } else if (i == 1) { // Down\n                edge_cost = model_v[pos.r][pos.c]; updates_count = updates_v[pos.r][pos.c];\n            } else if (i == 2) { // Left\n                edge_cost = model_h[nr][nc]; updates_count = updates_h[nr][nc];\n            } else { // Right\n                edge_cost = model_h[pos.r][pos.c]; updates_count = updates_h[pos.r][pos.c];\n            }\n            \n            double noisy_cost = edge_cost * dist_expl(rng);\n            double ucb_bonus = lambda_k / std::sqrt(updates_count + 1.0);\n            noisy_cost -= ucb_bonus;\n            \n            if (dist[pos.r][pos.c] + std::max(1.0, noisy_cost) < dist[nr][nc]) {\n                dist[nr][nc] = dist[pos.r][pos.c] + std::max(1.0, noisy_cost);\n                parent[nr][nc] = pos;\n                move_char[nr][nc] = moves[i];\n                pq.push({{nr, nc}, dist[nr][nc]});\n            }\n        }\n    }\n\n    std::string path_str = \"\";\n    Point current = goal;\n    while (current != start) {\n        path_str += move_char[current.r][current.c];\n        current = parent[current.r][current.c];\n    }\n    std::reverse(path_str.begin(), path_str.end());\n    return path_str;\n}\n\nvoid update_estimates(const std::string& path_str, Point start, long long noisy_path_length, int k) {\n    if (path_str.empty()) return;\n\n    double estimated_length = 0;\n    double Z = 0.0;\n    \n    Point current = start;\n    for (char move : path_str) {\n        Point next = current;\n        if (move == 'U') {\n            next.r--; estimated_length += est_v[next.r][next.c]; Z += 1.0 / (updates_v[next.r][next.c] + 1.0);\n        } else if (move == 'D') {\n            estimated_length += est_v[current.r][current.c]; Z += 1.0 / (updates_v[current.r][current.c] + 1.0); next.r++;\n        } else if (move == 'L') {\n            next.c--; estimated_length += est_h[next.r][next.c]; Z += 1.0 / (updates_h[next.r][next.c] + 1.0);\n        } else {\n            estimated_length += est_h[current.r][current.c]; Z += 1.0 / (updates_h[current.r][current.c] + 1.0); next.c++;\n        }\n        current = next;\n    }\n    \n    if (Z < 1e-9) return;\n\n    double error = static_cast<double>(noisy_path_length) - estimated_length;\n    double alpha_k = 0.5 * std::pow(0.01, static_cast<double>(k) / (NUM_QUERIES - 1));\n    double base_update = alpha_k * error / Z;\n\n    current = start;\n    for (char move : path_str) {\n        Point next = current;\n        if (move == 'U') {\n            next.r--; double w = 1.0 / (updates_v[next.r][next.c] + 1.0);\n            est_v[next.r][next.c] = std::clamp(est_v[next.r][next.c] + base_update * w, 500.0, 10000.0);\n            updates_v[next.r][next.c]++;\n        } else if (move == 'D') {\n            double w = 1.0 / (updates_v[current.r][current.c] + 1.0);\n            est_v[current.r][current.c] = std::clamp(est_v[current.r][current.c] + base_update * w, 500.0, 10000.0);\n            updates_v[current.r][current.c]++; next.r++;\n        } else if (move == 'L') {\n            next.c--; double w = 1.0 / (updates_h[next.r][next.c] + 1.0);\n            est_h[next.r][next.c] = std::clamp(est_h[next.r][next.c] + base_update * w, 500.0, 10000.0);\n            updates_h[next.r][next.c]++;\n        } else {\n            double w = 1.0 / (updates_h[current.r][current.c] + 1.0);\n            est_h[current.r][current.c] = std::clamp(est_h[current.r][current.c] + base_update * w, 500.0, 10000.0);\n            updates_h[current.r][current.c]++; next.c++;\n        }\n        current = next;\n    }\n}\n\nModelFitResult calculate_ss(const std::vector<std::pair<int, double>>& indexed_vals, int row_or_col_size) {\n    ModelFitResult res;\n    res.n_pts = indexed_vals.size();\n    if (res.n_pts == 0) return res;\n\n    double total_sum = 0, total_sq_sum = 0;\n    for (const auto& p : indexed_vals) {\n        total_sum += p.second; total_sq_sum += p.second * p.second;\n    }\n\n    res.mean1 = total_sum / res.n_pts;\n    res.sse1 = total_sq_sum - total_sum * res.mean1;\n    res.split_point = -1;\n    res.sse2 = res.sse1;\n\n    if (res.n_pts >= 4) {\n        double current_best_sse2 = 1e18;\n        \n        double sum_l = 0, sq_sum_l = 0;\n        int count_l = 0;\n        int val_idx = 0;\n        \n        for (int split = 1; split < row_or_col_size; ++split) {\n            while(val_idx < res.n_pts && indexed_vals[val_idx].first < split) {\n                sum_l += indexed_vals[val_idx].second;\n                sq_sum_l += indexed_vals[val_idx].second * indexed_vals[val_idx].second;\n                count_l++;\n                val_idx++;\n            }\n            \n            int count_r = res.n_pts - count_l;\n            if (count_l < 2 || count_r < 2) continue;\n\n            double mean_l = sum_l / count_l;\n            double sse_l = sq_sum_l - sum_l * mean_l;\n            \n            double sum_r = total_sum - sum_l;\n            double sq_sum_r = total_sq_sum - sq_sum_l;\n            double mean_r = sum_r / count_r;\n            double sse_r = sq_sum_r - sum_r * mean_r;\n            \n            if (sse_l + sse_r < current_best_sse2) {\n                current_best_sse2 = sse_l + sse_r;\n                res.split_point = split;\n                res.mean_l = mean_l;\n                res.mean_r = mean_r;\n            }\n        }\n        if (res.split_point != -1) res.sse2 = current_best_sse2;\n    }\n    return res;\n}\n\n\nvoid update_model(int k) {\n    if (k == 200) {\n        double total_bic_m1 = 0, total_bic_m2 = 0;\n        for (int i = 0; i < GRID_SIZE; ++i) {\n            std::vector<std::pair<int, double>> indexed_vals;\n            for(int j=0; j<GRID_SIZE-1; ++j) if(updates_h[i][j]>0) indexed_vals.push_back({j, est_h[i][j]});\n            auto res = calculate_ss(indexed_vals, GRID_SIZE - 1);\n            if (res.n_pts <= 1) continue;\n            total_bic_m1 += res.n_pts * log(std::max(1e-9, res.sse1 / res.n_pts)) + 1.0 * log(res.n_pts);\n            total_bic_m2 += res.n_pts * log(std::max(1e-9, res.sse2 / res.n_pts)) + 3.0 * log(res.n_pts);\n        }\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            std::vector<std::pair<int, double>> indexed_vals;\n            for(int i=0; i<GRID_SIZE-1; ++i) if(updates_v[i][j]>0) indexed_vals.push_back({i, est_v[i][j]});\n            auto res = calculate_ss(indexed_vals, GRID_SIZE - 1);\n            if (res.n_pts <= 1) continue;\n            total_bic_m1 += res.n_pts * log(std::max(1e-9, res.sse1 / res.n_pts)) + 1.0 * log(res.n_pts);\n            total_bic_m2 += res.n_pts * log(std::max(1e-9, res.sse2 / res.n_pts)) + 3.0 * log(res.n_pts);\n        }\n        if (total_bic_m2 < total_bic_m1) global_M = 2; else global_M = 1;\n    }\n    \n    for (int i = 0; i < GRID_SIZE; ++i) {\n        std::vector<std::pair<int, double>> indexed_vals;\n        for(int j=0; j<GRID_SIZE-1; ++j) if(updates_h[i][j]>0) indexed_vals.push_back({j, est_h[i][j]});\n        auto res = calculate_ss(indexed_vals, GRID_SIZE - 1);\n        if (res.n_pts == 0) continue;\n        \n        if (global_M == 2 && res.split_point != -1) {\n            for(int j=0; j<res.split_point; ++j) model_h[i][j] = res.mean_l;\n            for(int j=res.split_point; j<GRID_SIZE-1; ++j) model_h[i][j] = res.mean_r;\n        } else {\n            for(int j=0; j<GRID_SIZE-1; ++j) model_h[i][j] = res.mean1;\n        }\n    }\n    for (int j = 0; j < GRID_SIZE; ++j) {\n        std::vector<std::pair<int, double>> indexed_vals;\n        for(int i=0; i<GRID_SIZE-1; ++i) if(updates_v[i][j]>0) indexed_vals.push_back({i, est_v[i][j]});\n        auto res = calculate_ss(indexed_vals, GRID_SIZE - 1);\n        if (res.n_pts == 0) continue;\n\n        if (global_M == 2 && res.split_point != -1) {\n            for(int i=0; i<res.split_point; ++i) model_v[i][j] = res.mean_l;\n            for(int i=res.split_point; i<GRID_SIZE-1; ++i) model_v[i][j] = res.mean_r;\n        } else {\n            for(int i=0; i<GRID_SIZE-1; ++i) model_v[i][j] = res.mean1;\n        }\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE - 1; ++j) {\n            est_h[i][j] = model_h[i][j] = 5000.0; updates_h[i][j] = 0;\n        }\n    }\n    for (int i = 0; i < GRID_SIZE - 1; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            est_v[i][j] = model_v[i][j] = 5000.0; updates_v[i][j] = 0;\n        }\n    }\n\n    for (int k = 0; k < NUM_QUERIES; ++k) {\n        Point start, goal;\n        std::cin >> start.r >> start.c >> goal.r >> goal.c;\n\n        std::string path = find_path(start, goal, k);\n        std::cout << path << std::endl;\n\n        long long noisy_path_length;\n        std::cin >> noisy_path_length;\n\n        update_estimates(path, start, noisy_path_length, k);\n        update_model(k);\n    }\n\n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <chrono>\n#include <random>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <map>\n#include <cstring>\n\n// --- Constants and Globals ---\nconstexpr int N_CONST = 20;\nconstexpr int NUM_CHARS = 8;\nconstexpr long long W_CONFLICT = 10000;\nconst double TIME_LIMIT = 2.95;\n\nint N_in, M;\nstd::vector<std::string> S;\nstd::vector<int> S_len;\nstd::vector<std::vector<int>> S_int;\n\nstd::mt19937 rng;\nstd::chrono::steady_clock::time_point start_time;\n\nstruct Placement {\n    int r, c, dir; // dir=0: horizontal, dir=1: vertical\n    bool operator==(const Placement& other) const {\n        return r == other.r && c == other.c && dir == other.dir;\n    }\n};\n\n// --- State Representation ---\nstd::vector<Placement> current_placements;\nstd::vector<Placement> best_placements;\nlong long current_energy;\nlong long best_energy;\n\nint counts[N_CONST][N_CONST][NUM_CHARS];\nint covered_count[N_CONST][N_CONST];\n\nint best_counts[N_CONST][N_CONST][NUM_CHARS];\nint best_covered_count[N_CONST][N_CONST];\n\n// --- Utilities ---\nint ctoi(char c) { return c - 'A'; }\nchar itoc(int i) { return (char)('A' + i); }\n\n// --- Core Logic ---\nstd::pair<long long, int> get_cell_energy_contrib(int r, int c) {\n    if (covered_count[r][c] == 0) return {0, 0};\n    int max_c = 0;\n    for (int k = 0; k < NUM_CHARS; ++k) max_c = std::max(max_c, counts[r][c][k]);\n    long long conflict_contrib = covered_count[r][c] - max_c;\n    return {conflict_contrib, 1};\n}\n\nvoid update_state_for_move(int str_idx, const Placement& p, int sign) {\n    const auto& s = S_int[str_idx];\n    int len = S_len[str_idx];\n    if (p.dir == 0) { // Horizontal\n        for (int i = 0; i < len; ++i) {\n            counts[p.r][(p.c + i) % N_CONST][s[i]] += sign;\n            covered_count[p.r][(p.c + i) % N_CONST] += sign;\n        }\n    } else { // Vertical\n        for (int i = 0; i < len; ++i) {\n            counts[(p.r + i) % N_CONST][p.c][s[i]] += sign;\n            covered_count[(p.r + i) % N_CONST][p.c] += sign;\n        }\n    }\n}\n\nlong long calculate_delta_energy(int str_idx, const Placement& old_p, const Placement& new_p) {\n    long long delta = 0;\n    const auto& s = S_int[str_idx];\n    int len = S_len[str_idx];\n    \n    std::vector<std::pair<int, int>> affected_coords;\n    if (old_p.dir == 0) for (int i=0; i<len; ++i) affected_coords.push_back({old_p.r, (old_p.c+i)%N_CONST});\n    else for (int i=0; i<len; ++i) affected_coords.push_back({(old_p.r+i)%N_CONST, old_p.c});\n    \n    if (new_p.dir == 0) for (int i=0; i<len; ++i) affected_coords.push_back({new_p.r, (new_p.c+i)%N_CONST});\n    else for (int i=0; i<len; ++i) affected_coords.push_back({(new_p.r+i)%N_CONST, new_p.c});\n\n    std::sort(affected_coords.begin(), affected_coords.end());\n    affected_coords.erase(std::unique(affected_coords.begin(), affected_coords.end()), affected_coords.end());\n\n    for (const auto& cell : affected_coords) {\n        int r = cell.first; int c = cell.second;\n        auto [conflicts_before, covered_before] = get_cell_energy_contrib(r, c);\n        delta -= (conflicts_before * W_CONFLICT + covered_before);\n\n        int old_p_char = -1, new_p_char = -1;\n        if (old_p.dir == 0) { if (r == old_p.r && (c - old_p.c + N_CONST)%N_CONST < len) old_p_char = s[(c-old_p.c+N_CONST)%N_CONST]; }\n        else { if (c == old_p.c && (r - old_p.r + N_CONST)%N_CONST < len) old_p_char = s[(r-old_p.r+N_CONST)%N_CONST]; }\n        if (new_p.dir == 0) { if (r == new_p.r && (c - new_p.c + N_CONST)%N_CONST < len) new_p_char = s[(c-new_p.c+N_CONST)%N_CONST]; }\n        else { if (c == new_p.c && (r - new_p.r + N_CONST)%N_CONST < len) new_p_char = s[(r-new_p.r+N_CONST)%N_CONST]; }\n        \n        int new_covered_total = covered_count[r][c];\n        if(old_p_char != -1) new_covered_total--;\n        if(new_p_char != -1) new_covered_total++;\n\n        if (new_covered_total > 0) {\n            int max_c = 0;\n            for (int k=0; k<NUM_CHARS; ++k) {\n                int current_cnt = counts[r][c][k];\n                if(k == old_p_char) current_cnt--; if(k == new_p_char) current_cnt++;\n                max_c = std::max(max_c, current_cnt);\n            }\n            long long conflicts_after = new_covered_total - max_c;\n            delta += (conflicts_after * W_CONFLICT + 1);\n        }\n    }\n    return delta;\n}\n\nPlacement find_best_move(int str_idx) {\n    Placement old_p = current_placements[str_idx];\n    Placement best_p = old_p;\n    long long min_delta = 1e18;\n    for (int r = 0; r < N_CONST; ++r) for (int c = 0; c < N_CONST; ++c) for (int dir = 0; dir < 2; ++dir) {\n        Placement p_candidate = {r, c, dir};\n        long long delta = calculate_delta_energy(str_idx, old_p, p_candidate);\n        if (delta < min_delta) { min_delta = delta; best_p = p_candidate; }\n    }\n    return best_p;\n}\n\nvoid greedy_initialization() {\n    current_placements.resize(M);\n    std::vector<int> p(M); std::iota(p.begin(), p.end(), 0);\n    std::sort(p.begin(), p.end(), [&](int i, int j){ return S_len[i] > S_len[j]; });\n    std::vector<std::vector<int>> grid(N_CONST, std::vector<int>(N_CONST, -1));\n    for (int str_idx : p) {\n        Placement best_p; int min_conflicts = 1e9;\n        for (int r=0;r<N_CONST;++r) for(int c=0;c<N_CONST;++c) for(int dir=0;dir<2;++dir) {\n            int current_conflicts = 0; const auto& s = S_int[str_idx]; int len = S_len[str_idx];\n            if(dir==0) for(int i=0;i<len;++i) if (grid[r][(c+i)%N_CONST]!=-1 && grid[r][(c+i)%N_CONST]!=s[i]) current_conflicts++;\n            else for(int i=0;i<len;++i) if (grid[(r+i)%N_CONST][c]!=-1 && grid[(r+i)%N_CONST][c]!=s[i]) current_conflicts++;\n            if(current_conflicts < min_conflicts) { min_conflicts=current_conflicts; best_p={r,c,dir}; }\n        }\n        current_placements[str_idx] = best_p; const auto& s = S_int[str_idx]; int len = S_len[str_idx];\n        if (best_p.dir == 0) for(int i=0; i<len; ++i) grid[best_p.r][(best_p.c+i)%N_CONST] = s[i];\n        else for(int i=0; i<len; ++i) grid[(best_p.r+i)%N_CONST][best_p.c] = s[i];\n    }\n}\n\nvoid solve() {\n    start_time = std::chrono::steady_clock::now();\n    rng.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());\n    S_int.resize(M); S_len.resize(M);\n    for (int i=0; i<M; ++i) {\n        S_len[i]=S[i].length(); S_int[i].resize(S_len[i]);\n        for(int j=0; j<S_len[i]; ++j) S_int[i][j]=ctoi(S[i][j]);\n    }\n\n    greedy_initialization();\n    for (int i=0; i<M; ++i) update_state_for_move(i, current_placements[i], +1);\n    \n    // Initial Refinement\n    for (int iter = 0; iter < 2; ++iter) for (int i = 0; i < M; ++i) {\n        Placement old_p = current_placements[i]; Placement best_p = find_best_move(i);\n        if (!(best_p == old_p)) {\n            update_state_for_move(i, old_p, -1); update_state_for_move(i, best_p, +1);\n            current_placements[i] = best_p;\n        }\n    }\n    \n    current_energy = 0;\n    for (int r=0;r<N_CONST;++r) for (int c=0;c<N_CONST;++c){\n        auto [conf, cov] = get_cell_energy_contrib(r,c); current_energy += conf*W_CONFLICT + cov;\n    }\n    best_energy = current_energy; best_placements = current_placements;\n    memcpy(best_counts, counts, sizeof(counts)); memcpy(best_covered_count, covered_count, sizeof(covered_count));\n\n    double start_temp=5000.0, end_temp=0.1;\n    int iters_since_best = 0; const int STAGNATION_LIMIT = M * 100;\n    \n    while (true) {\n        auto now = std::chrono::steady_clock::now();\n        double elapsed_time = std::chrono::duration_cast<std::chrono::duration<double>>(now - start_time).count();\n        if (elapsed_time > TIME_LIMIT) break;\n\n        double temp = start_temp * std::pow(end_temp / start_temp, elapsed_time / TIME_LIMIT);\n        int str_idx;\n        \n        if (current_energy / W_CONFLICT == 0) { // Phase 2: Optimize coverage\n            if (std::uniform_real_distribution<>(0.0, 1.0)(rng) < 0.95) {\n                int best_cand_idx = -1; int max_score = -1;\n                for(int i=0; i < 20; ++i) {\n                    int cand_idx = std::uniform_int_distribution<int>(0, M - 1)(rng); int score = 0;\n                    const auto& p = current_placements[cand_idx]; int len = S_len[cand_idx];\n                    if (p.dir==0) for(int j=0;j<len;++j) if(covered_count[p.r][(p.c+j)%N_CONST]==1) score++;\n                    else for(int j=0;j<len;++j) if(covered_count[(p.r+j)%N_CONST][p.c]==1) score++;\n                    if(score > max_score){ max_score = score; best_cand_idx = cand_idx; }\n                }\n                str_idx = best_cand_idx != -1 ? best_cand_idx : std::uniform_int_distribution<int>(0, M - 1)(rng);\n            } else str_idx = std::uniform_int_distribution<int>(0, M - 1)(rng);\n        } else { // Phase 1: Resolve conflicts\n            if (std::uniform_real_distribution<>(0.0, 1.0)(rng) < 0.05) str_idx = std::uniform_int_distribution<int>(0, M - 1)(rng);\n            else {\n                std::vector<std::pair<int, int>> conflicted_cells;\n                for(int r=0; r<N_CONST; ++r) for(int c=0; c<N_CONST; ++c) if(get_cell_energy_contrib(r,c).first > 0) conflicted_cells.emplace_back(r, c);\n                if (!conflicted_cells.empty()) {\n                    auto [r0,c0] = conflicted_cells[std::uniform_int_distribution<int>(0, conflicted_cells.size()-1)(rng)];\n                    std::vector<int> candidates;\n                    for(int i=0; i<M; ++i) { const auto& p=current_placements[i]; int len=S_len[i];\n                        if((p.dir==0&&p.r==r0&&(c0-p.c+N_CONST)%N_CONST<len)||(p.dir==1&&p.c==c0&&(r0-p.r+N_CONST)%N_CONST<len)) candidates.push_back(i);\n                    }\n                    if (!candidates.empty()) str_idx = candidates[std::uniform_int_distribution<int>(0, candidates.size()-1)(rng)];\n                    else str_idx = std::uniform_int_distribution<int>(0, M-1)(rng);\n                } else str_idx = std::uniform_int_distribution<int>(0, M-1)(rng);\n            }\n        }\n\n        Placement old_p = current_placements[str_idx]; Placement new_p;\n        double p_powerful = 0.2 + 0.6*(elapsed_time/TIME_LIMIT);\n        if (std::uniform_real_distribution<>(0.0,1.0)(rng) < p_powerful) new_p = find_best_move(str_idx);\n        else {\n            double p_local = 0.1 + 0.8 * (elapsed_time/TIME_LIMIT);\n            if (std::uniform_real_distribution<>(0.0, 1.0)(rng) < p_local) {\n                 new_p = old_p; int move_type = std::uniform_int_distribution<int>(0,2)(rng);\n                 if (move_type==0) new_p.r=(new_p.r+std::uniform_int_distribution<int>(-2,2)(rng)+N_CONST)%N_CONST;\n                 else if (move_type==1) new_p.c=(new_p.c+std::uniform_int_distribution<int>(-2,2)(rng)+N_CONST)%N_CONST;\n                 else new_p.dir=1-new_p.dir;\n            } else new_p = {std::uniform_int_distribution<int>(0,N_CONST-1)(rng), std::uniform_int_distribution<int>(0,N_CONST-1)(rng), std::uniform_int_distribution<int>(0,1)(rng)};\n        }\n        \n        if (old_p == new_p) continue;\n        long long delta_energy = calculate_delta_energy(str_idx, old_p, new_p);\n        if (delta_energy <= 0 || std::uniform_real_distribution<double>(0.0,1.0)(rng) < std::exp(-delta_energy/temp)) {\n            current_energy += delta_energy;\n            update_state_for_move(str_idx, old_p, -1); update_state_for_move(str_idx, new_p, +1);\n            current_placements[str_idx] = new_p;\n            if (current_energy < best_energy) {\n                best_energy = current_energy; best_placements = current_placements;\n                memcpy(best_counts, counts, sizeof(counts)); memcpy(best_covered_count, covered_count, sizeof(covered_count));\n                iters_since_best = 0;\n            }\n        }\n        iters_since_best++;\n        if (best_energy >= W_CONFLICT && iters_since_best > STAGNATION_LIMIT) {\n            current_placements = best_placements; memcpy(counts, best_counts, sizeof(counts)); memcpy(covered_count, best_covered_count, sizeof(covered_count));\n            current_energy = best_energy;\n            std::vector<int> conflicted_strings; std::vector<bool> is_conflicted_str(M, false);\n            for(int r=0;r<N_CONST;++r) for(int c=0;c<N_CONST;++c) if(get_cell_energy_contrib(r,c).first > 0)\n                for(int i=0;i<M;++i) if(!is_conflicted_str[i]){ const auto& p=current_placements[i]; int len=S_len[i];\n                    if((p.dir==0&&p.r==r&&(c-p.c+N_CONST)%N_CONST<len)||(p.dir==1&&p.c==c&&(r-p.r+N_CONST)%N_CONST<len)){\n                        conflicted_strings.push_back(i); is_conflicted_str[i]=true;\n                    }\n                }\n            if(!conflicted_strings.empty()){\n                std::shuffle(conflicted_strings.begin(), conflicted_strings.end(), rng);\n                int num_to_kick = std::max(3, M / 50);\n                for (int i=0; i<num_to_kick && i<conflicted_strings.size(); ++i) {\n                    int kick_idx = conflicted_strings[i]; Placement kick_old_p = current_placements[kick_idx]; Placement kick_new_p;\n                    if (std::uniform_real_distribution<>(0.0, 1.0)(rng) < 0.5) kick_new_p = find_best_move(kick_idx);\n                    else kick_new_p = {std::uniform_int_distribution<int>(0,N_CONST-1)(rng), std::uniform_int_distribution<int>(0,N_CONST-1)(rng), std::uniform_int_distribution<int>(0,1)(rng)};\n                    if(!(kick_old_p == kick_new_p)){\n                        long long kick_delta = calculate_delta_energy(kick_idx, kick_old_p, kick_new_p);\n                        update_state_for_move(kick_idx, kick_old_p, -1); update_state_for_move(kick_idx, kick_new_p, +1);\n                        current_placements[kick_idx] = kick_new_p; current_energy += kick_delta;\n                    }\n                }\n            }\n            if(current_energy < best_energy) {\n                best_energy = current_energy; best_placements = current_placements;\n                memcpy(best_counts, counts, sizeof(counts)); memcpy(best_covered_count, covered_count, sizeof(covered_count));\n            }\n            iters_since_best = 0;\n        }\n    }\n\n    std::vector<std::string> final_grid(N_CONST, std::string(N_CONST, '.'));\n    for (int r=0;r<N_CONST;++r) for(int c=0;c<N_CONST;++c) if(best_covered_count[r][c] > 0) {\n        int max_k=-1, max_cnt=0;\n        for (int k=0;k<NUM_CHARS;++k) if (best_counts[r][c][k]>max_cnt) {max_cnt=best_counts[r][c][k]; max_k=k;}\n        if (max_k != -1) final_grid[r][c]=itoc(max_k);\n    }\n    for (int i=0;i<N_CONST;++i) std::cout<<final_grid[i]<<std::endl;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false); std::cin.tie(NULL);\n    std::cin >> N_in >> M;\n    S.resize(M);\n    for (int i=0; i<M; ++i) std::cin >> S[i];\n    solve();\n    return 0;\n}","ahc005":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <map>\n#include <set>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <cmath>\n\nusing namespace std;\n\n// Timer\nchrono::high_resolution_clock::time_point start_time;\nconst double TIME_LIMIT_MS = 2900.0;\n\n// PRNG\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// Constants\nconst int INF = 1e9;\nconst int DR[] = {-1, 1, 0, 0};\nconst int DC[] = {0, 0, -1, 1};\n\n// Globals\nint N, si, sj;\nvector<string> grid;\nvector<pair<int, int>> road_squares;\nmap<pair<int, int>, int> coord_to_id;\nvector<vector<pair<int, int>>> adj;\n\nstruct Segment {\n    int id;\n    vector<pair<int, int>> squares;\n};\nvector<Segment> segments;\n\n// Pre-computation functions\nvoid find_road_squares_and_build_graph() {\n    int current_id = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != '#') {\n                road_squares.push_back({i, j});\n                coord_to_id[{i, j}] = current_id++;\n            }\n        }\n    }\n\n    adj.resize(road_squares.size());\n    for (size_t i = 0; i < road_squares.size(); ++i) {\n        auto [r, c] = road_squares[i];\n        for (int move = 0; move < 4; ++move) {\n            int nr = r + DR[move];\n            int nc = c + DC[move];\n            if (nr >= 0 && nr < N && nc >= 0 && nc < N && grid[nr][nc] != '#') {\n                int neighbor_id = coord_to_id.at({nr, nc});\n                int cost = grid[nr][nc] - '0';\n                adj[i].push_back({neighbor_id, cost});\n            }\n        }\n    }\n}\n\nvoid find_segments() {\n    set<pair<int, int>> visited_horz, visited_vert;\n    int seg_id_counter = 0;\n    for (const auto& p : road_squares) {\n        if (!visited_horz.count(p)) {\n            Segment seg;\n            seg.id = seg_id_counter++;\n            int r = p.first, c = p.second;\n            int c_start = c;\n            while (c_start > 0 && grid[r][c_start - 1] != '#') c_start--;\n            int c_end = c;\n            while (c_end < N - 1 && grid[r][c_end + 1] != '#') c_end++;\n            for (int j = c_start; j <= c_end; ++j) {\n                seg.squares.push_back({r, j});\n                visited_horz.insert({r, j});\n            }\n            segments.push_back(seg);\n        }\n        if (!visited_vert.count(p)) {\n            Segment seg;\n            seg.id = seg_id_counter++;\n            int r = p.first, c = p.second;\n            int r_start = r;\n            while (r_start > 0 && grid[r_start - 1][c] != '#') r_start--;\n            int r_end = r;\n            while (r_end < N - 1 && grid[r_end + 1][c] != '#') r_end++;\n            for (int i = r_start; i <= r_end; ++i) {\n                seg.squares.push_back({i, c});\n                visited_vert.insert({i, c});\n            }\n            segments.push_back(seg);\n        }\n    }\n}\n\npair<vector<int>, vector<int>> dijkstra(int start_node_id) {\n    int n = road_squares.size();\n    vector<int> dist(n, INF);\n    vector<int> parent(n, -1);\n    dist[start_node_id] = 0;\n\n    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;\n    pq.push({0, start_node_id});\n\n    while (!pq.empty()) {\n        auto [d, u] = pq.top();\n        pq.pop();\n        if (d > dist[u]) continue;\n        for (auto& edge : adj[u]) {\n            int v = edge.first;\n            int weight = edge.second;\n            if (dist[u] + weight < dist[v]) {\n                dist[v] = dist[u] + weight;\n                parent[v] = u;\n                pq.push({dist[v], v});\n            }\n        }\n    }\n    return {dist, parent};\n}\n\nlong long calculate_tour_cost(const vector<int>& tour, const vector<vector<int>>& dist_matrix) {\n    if (tour.empty()) return 0;\n    long long cost = 0;\n    for (size_t i = 0; i < tour.size(); ++i) {\n        cost += dist_matrix[tour[i]][tour[(i + 1) % tour.size()]];\n    }\n    return cost;\n}\n\nvoid two_opt_local_search(vector<int>& tour, int n, const vector<vector<int>>& dist_matrix) {\n    if (n < 4) return;\n    bool improved = true;\n    int check_counter = 0;\n    while(improved) {\n        improved = false;\n        for (int i = 0; i <= n - 2; ++i) {\n            for (int j = i + 2; j < n; ++j) {\n                 if ((++check_counter & 1023) == 0) {\n                    if (chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count() > TIME_LIMIT_MS - 50) {\n                        return;\n                    }\n                 }\n\n                 if (i == 0 && j == n - 1) continue; \n                 int u1 = tour[i];\n                 int v1 = tour[i+1];\n                 int u2 = tour[j];\n                 int v2 = tour[(j+1)%n];\n                 \n                 if((long long)dist_matrix[u1][v1] + dist_matrix[u2][v2] > (long long)dist_matrix[u1][u2] + dist_matrix[v1][v2]) {\n                     reverse(tour.begin() + i + 1, tour.begin() + j + 1);\n                     improved = true;\n                     goto next_two_opt_iteration;\n                 }\n            }\n        }\n        next_two_opt_iteration:;\n    }\n}\n\nvoid three_cut_perturbation(vector<int>& tour, int n) {\n    if (n < 6) return;\n\n    int p1 = uniform_int_distribution<int>(0, n - 4)(rng);\n    int p2 = uniform_int_distribution<int>(p1 + 1, n - 3)(rng);\n    int p3 = uniform_int_distribution<int>(p2 + 1, n - 2)(rng);\n    \n    vector<int> next_tour;\n    next_tour.reserve(n);\n\n    // Segments: A(0..p1), B(p1+1..p2), C(p2+1..p3), D(p3+1..n-1)\n    // Reorder: A-C-B-D\n    for (int i = 0; i <= p1; ++i) next_tour.push_back(tour[i]);\n    for (int i = p2 + 1; i <= p3; ++i) next_tour.push_back(tour[i]);\n    for (int i = p1 + 1; i <= p2; ++i) next_tour.push_back(tour[i]);\n    for (int i = p3 + 1; i < n; ++i) next_tour.push_back(tour[i]);\n    \n    tour = next_tour;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    start_time = chrono::high_resolution_clock::now();\n\n    cin >> N >> si >> sj;\n    grid.resize(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n\n    find_road_squares_and_build_graph();\n    find_segments();\n    \n    set<pair<int, int>> key_points_set;\n    key_points_set.insert({si, sj});\n    for (const auto& seg : segments) {\n        key_points_set.insert(seg.squares.front());\n        key_points_set.insert(seg.squares.back());\n    }\n    for (size_t i = 0; i < road_squares.size(); ++i) {\n        if (adj[i].size() > 2) key_points_set.insert(road_squares[i]);\n    }\n    \n    vector<pair<int, int>> key_points(key_points_set.begin(), key_points_set.end());\n    map<pair<int, int>, int> kp_to_idx;\n    for(size_t i=0; i<key_points.size(); ++i) kp_to_idx[key_points[i]] = i;\n\n    vector<vector<int>> kp_covers(key_points.size());\n    for(size_t i=0; i<key_points.size(); ++i) {\n        for(const auto& seg : segments) {\n            for(const auto& sq : seg.squares) {\n                if(sq == key_points[i]) { kp_covers[i].push_back(seg.id); break; }\n            }\n        }\n    }\n    \n    set<int> uncovered_segments;\n    for (const auto& seg : segments) uncovered_segments.insert(seg.id);\n    set<int> selected_kp_indices;\n\n    while(!uncovered_segments.empty()) {\n        int best_kp_idx = -1; int max_covered = -1;\n        for(size_t i=0; i<key_points.size(); ++i) {\n            if (selected_kp_indices.count(i)) continue;\n            int current_covered = 0;\n            for(int seg_id : kp_covers[i]) if (uncovered_segments.count(seg_id)) current_covered++;\n            if(current_covered > max_covered) { max_covered = current_covered; best_kp_idx = i; }\n        }\n        if (best_kp_idx == -1) break;\n        selected_kp_indices.insert(best_kp_idx);\n        for(int seg_id : kp_covers[best_kp_idx]) uncovered_segments.erase(seg_id);\n    }\n    \n    map<int, int> coverage_count;\n    for(const auto& seg : segments) coverage_count[seg.id] = 0;\n    for(int kp_idx : selected_kp_indices) for(int seg_id : kp_covers[kp_idx]) coverage_count[seg_id]++;\n    vector<int> selected_kp_vec(selected_kp_indices.begin(), selected_kp_indices.end());\n    bool changed = true;\n    while(changed) {\n        changed = false;\n        shuffle(selected_kp_vec.begin(), selected_kp_vec.end(), rng);\n        auto it = selected_kp_vec.begin();\n        while(it != selected_kp_vec.end()) {\n            int kp_to_remove = *it;\n            bool is_redundant = true;\n            for (int seg_id : kp_covers[kp_to_remove]) {\n                if (coverage_count[seg_id] == 1) { is_redundant = false; break; }\n            }\n            if (is_redundant) {\n                for (int seg_id : kp_covers[kp_to_remove]) coverage_count[seg_id]--;\n                it = selected_kp_vec.erase(it);\n                changed = true;\n            } else { ++it; }\n        }\n    }\n    \n    set<pair<int, int>> target_kps_set;\n    for(int idx : selected_kp_vec) target_kps_set.insert(key_points[idx]);\n    target_kps_set.insert({si, sj});\n\n    vector<pair<int, int>> V_tsp_coords(target_kps_set.begin(), target_kps_set.end());\n    int num_tsp_nodes = V_tsp_coords.size();\n    map<pair<int, int>, int> tsp_coord_to_idx;\n    for(int i=0; i<num_tsp_nodes; ++i) tsp_coord_to_idx[V_tsp_coords[i]] = i;\n\n    vector<vector<int>> dist_matrix(num_tsp_nodes, vector<int>(num_tsp_nodes));\n    vector<vector<int>> parents_matrix(num_tsp_nodes, vector<int>(road_squares.size()));\n    for(int i=0; i<num_tsp_nodes; ++i) {\n        int start_node_id = coord_to_id.at(V_tsp_coords[i]);\n        auto [dist, parent] = dijkstra(start_node_id);\n        parents_matrix[i] = parent;\n        for(int j=0; j<num_tsp_nodes; ++j) {\n            dist_matrix[i][j] = dist[coord_to_id.at(V_tsp_coords[j])];\n        }\n    }\n\n    int start_tsp_idx = tsp_coord_to_idx.at({si, sj});\n    vector<int> best_tour;\n    if(num_tsp_nodes > 0){\n        vector<int> tour;\n        tour.push_back(start_tsp_idx);\n        vector<bool> visited(num_tsp_nodes, false);\n        visited[start_tsp_idx] = true;\n        int current_idx = start_tsp_idx;\n        while(tour.size() < (size_t)num_tsp_nodes) {\n            int next_idx = -1, min_dist = INF;\n            for(int i=0; i<num_tsp_nodes; ++i) {\n                if(!visited[i] && dist_matrix[current_idx][i] < min_dist) {\n                    min_dist = dist_matrix[current_idx][i]; next_idx = i;\n                }\n            }\n            if (next_idx == -1) break;\n            tour.push_back(next_idx); visited[next_idx] = true; current_idx = next_idx;\n        }\n        best_tour = tour;\n    }\n    \n    vector<int> current_tour = best_tour;\n    two_opt_local_search(current_tour, num_tsp_nodes, dist_matrix);\n    \n    best_tour = current_tour;\n    long long best_cost = calculate_tour_cost(best_tour, dist_matrix);\n    long long current_cost = best_cost;\n\n    const int acceptance_delta = 5;\n\n    while(true) {\n        if (chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count() > TIME_LIMIT_MS) break;\n\n        vector<int> next_tour = current_tour;\n        three_cut_perturbation(next_tour, num_tsp_nodes);\n        two_opt_local_search(next_tour, num_tsp_nodes, dist_matrix);\n        long long next_cost = calculate_tour_cost(next_tour, dist_matrix);\n        \n        if (next_cost < best_cost) {\n            best_tour = next_tour;\n            best_cost = next_cost;\n        }\n\n        if (next_cost < current_cost + acceptance_delta) {\n             current_tour = next_tour;\n             current_cost = next_cost;\n        }\n    }\n\n    auto it = find(best_tour.begin(), best_tour.end(), start_tsp_idx);\n    if (it != best_tour.end()) rotate(best_tour.begin(), it, best_tour.end());\n\n    string path_str = \"\";\n    if (!best_tour.empty()) {\n        for(size_t i=0; i<best_tour.size(); ++i) {\n            int u_idx = best_tour[i], v_idx = best_tour[(i+1)%best_tour.size()];\n            int u_id = coord_to_id.at(V_tsp_coords[u_idx]), v_id = coord_to_id.at(V_tsp_coords[v_idx]);\n            vector<int> path;\n            for(int curr=v_id; curr!=-1 && curr!=u_id; curr=parents_matrix[u_idx][curr]) path.push_back(curr);\n            reverse(path.begin(), path.end());\n            pair<int, int> last_coord = V_tsp_coords[u_idx];\n            for(int node_id : path) {\n                auto [r, c] = road_squares[node_id];\n                if(r < last_coord.first) path_str += 'U'; else if(r > last_coord.first) path_str += 'D';\n                else if(c < last_coord.second) path_str += 'L'; else path_str += 'R';\n                last_coord = {r, c};\n            }\n        }\n    }\n    cout << path_str << endl;\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <string>\n#include <sstream>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <functional>\n#include <limits>\n\n#include <atcoder/mincostflow>\n\n// Constants\nconstexpr int N_TASKS = 1000;\nconstexpr int M_MEMBERS = 20;\nconstexpr int MAX_DAYS = 2000;\n\n// Hyperparameters\nconst double INITIAL_SKILL_ESTIMATE = 0.0;\nconst double SKILL_UPDATE_LEARNING_RATE = 0.15;\nconst double EXPLORATION_DECAY_DAYS = 450.0; // Tuned\nconst double EXPLORATION_LAMBDA_0 = 0.5;\nconst double OVERESTIMATE_CORRECTION_FACTOR = 0.1;\nconst int CANDIDATE_TASK_POOL_SIZE = 3 * M_MEMBERS;\nconst double NOVELTY_WEIGHT = 200.0; // Tuned\nconst double UNCERTAINTY_WEIGHT = 300.0; // Tuned\n\n// Problem data\nint K, R;\nstd::vector<std::vector<int>> D; // Task difficulties\nstd::vector<std::vector<int>> adj; // Task dependencies (u -> v means u must be done before v)\nstd::vector<std::vector<int>> rev_adj; // Reverse dependencies\n\n// State\nenum class TaskStatus { NOT_STARTED, IN_PROGRESS, COMPLETED };\nstd::vector<TaskStatus> task_status;\nint completed_task_count;\n\nstruct Member {\n    bool is_busy = false;\n    int task_id = -1;\n    int start_day = -1;\n};\nstd::vector<Member> members;\n\nstd::vector<std::vector<double>> estimated_skills;\nstd::vector<std::vector<int>> skill_lower_bounds;\nstd::vector<std::vector<int>> max_d_seen;\nstd::vector<std::vector<int>> skill_update_counts;\n\n// --- Function Declarations ---\ndouble estimate_work(int task_id, int member_id);\ndouble estimate_time(int task_id, int member_id);\nvoid read_initial_input();\nvoid initialize_state();\nvoid update_skills(int member_id, int task_id, int duration);\n\n// --- Main Logic ---\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int N_dummy, M_dummy;\n    std::cin >> N_dummy >> M_dummy;\n    \n    read_initial_input();\n    initialize_state();\n\n    for (int day = 1; day <= MAX_DAYS; ++day) {\n        std::vector<int> free_members_ids;\n        for (int i = 0; i < M_MEMBERS; ++i) {\n            if (!members[i].is_busy) {\n                free_members_ids.push_back(i);\n            }\n        }\n\n        std::vector<std::pair<int, int>> assignments;\n        if (!free_members_ids.empty()) {\n            std::vector<int> schedulable_tasks_ids;\n            for (int i = 0; i < N_TASKS; ++i) {\n                if (task_status[i] == TaskStatus::NOT_STARTED) {\n                    bool all_deps_done = true;\n                    for (int dep : rev_adj[i]) {\n                        if (task_status[dep] != TaskStatus::COMPLETED) {\n                            all_deps_done = false;\n                            break;\n                        }\n                    }\n                    if (all_deps_done) {\n                        schedulable_tasks_ids.push_back(i);\n                    }\n                }\n            }\n            if (!schedulable_tasks_ids.empty()) {\n                std::vector<double> best_time_for_task(N_TASKS);\n                for (int i = 0; i < N_TASKS; ++i) {\n                    if (task_status[i] == TaskStatus::COMPLETED) {\n                        best_time_for_task[i] = 0;\n                    } else {\n                        double min_t = 1e9;\n                        // STABILITY IMPROVEMENT: Use all members for a stable heuristic\n                        for (int member_id = 0; member_id < M_MEMBERS; ++member_id) {\n                            min_t = std::min(min_t, estimate_time(i, member_id));\n                        }\n                        best_time_for_task[i] = min_t;\n                    }\n                }\n                std::vector<double> dlp(N_TASKS, 0.0);\n                for (int i = N_TASKS - 1; i >= 0; --i) {\n                    double max_succ_dlp = 0.0;\n                    for (int neighbor : adj[i]) {\n                        max_succ_dlp = std::max(max_succ_dlp, dlp[neighbor]);\n                    }\n                    dlp[i] = best_time_for_task[i] + max_succ_dlp;\n                }\n\n                std::sort(schedulable_tasks_ids.begin(), schedulable_tasks_ids.end(), [&](int a, int b) {\n                    if (std::abs(dlp[a] - dlp[b]) > 1e-9) return dlp[a] > dlp[b];\n                    return a < b;\n                });\n                if (schedulable_tasks_ids.size() > CANDIDATE_TASK_POOL_SIZE) {\n                    schedulable_tasks_ids.resize(CANDIDATE_TASK_POOL_SIZE);\n                }\n\n                int num_free_members = free_members_ids.size();\n                int num_cand_tasks = schedulable_tasks_ids.size();\n                \n                std::vector<std::vector<long long>> costs(num_free_members, std::vector<long long>(num_cand_tasks));\n                long long min_cost = std::numeric_limits<long long>::max();\n                double lambda = EXPLORATION_LAMBDA_0 * exp(-(double)day / EXPLORATION_DECAY_DAYS);\n\n                for (int i = 0; i < num_free_members; ++i) {\n                    int member_id = free_members_ids[i];\n                    for (int j = 0; j < num_cand_tasks; ++j) {\n                        int task_id = schedulable_tasks_ids[j];\n                        double t_est = estimate_time(task_id, member_id);\n                        double novelty_bonus = 0;\n                        for (int k = 0; k < K; ++k) {\n                            novelty_bonus += std::max(0, D[task_id][k] - max_d_seen[member_id][k]);\n                        }\n                        double uncertainty_bonus = 0;\n                        for(int k=0; k<K; ++k){\n                            if(D[task_id][k] > 0){\n                                uncertainty_bonus += 1.0 / (1.0 + skill_update_counts[member_id][k]);\n                            }\n                        }\n                        long long current_cost = static_cast<long long>(round(100.0 * t_est - lambda * (NOVELTY_WEIGHT * novelty_bonus + UNCERTAINTY_WEIGHT * uncertainty_bonus)));\n                        costs[i][j] = current_cost;\n                        min_cost = std::min(min_cost, current_cost);\n                    }\n                }\n\n                long long cost_shift = (min_cost < 0) ? -min_cost : 0;\n\n                atcoder::mcf_graph<int, long long> graph(num_free_members + num_cand_tasks + 2);\n                int s = num_free_members + num_cand_tasks;\n                int t = s + 1;\n                for (int i = 0; i < num_free_members; ++i) graph.add_edge(s, i, 1, 0);\n                for (int i = 0; i < num_cand_tasks; ++i) graph.add_edge(num_free_members + i, t, 1, 0);\n                for (int i = 0; i < num_free_members; ++i) {\n                    for (int j = 0; j < num_cand_tasks; ++j) {\n                        graph.add_edge(i, num_free_members + j, 1, costs[i][j] + cost_shift);\n                    }\n                }\n\n                graph.flow(s, t, std::min(num_free_members, num_cand_tasks));\n                for (const auto& edge : graph.edges()) {\n                    if (edge.from >= 0 && edge.from < num_free_members && \n                        edge.to >= num_free_members && edge.to < s && edge.flow > 0) {\n                        int member_idx = edge.from;\n                        int task_idx = edge.to - num_free_members;\n                        assignments.emplace_back(free_members_ids[member_idx], schedulable_tasks_ids[task_idx]);\n                    }\n                }\n            }\n        }\n        \n        std::cout << assignments.size();\n        for (const auto& p : assignments) {\n            int member_id = p.first;\n            int task_id = p.second;\n            std::cout << \" \" << member_id + 1 << \" \" << task_id + 1;\n            members[member_id] = {true, task_id, day};\n            task_status[task_id] = TaskStatus::IN_PROGRESS;\n        }\n        std::cout << std::endl;\n\n        int n_finished;\n        std::cin >> n_finished;\n        if (n_finished == -1) break;\n        \n        for (int i = 0; i < n_finished; ++i) {\n            int finished_member_id;\n            std::cin >> finished_member_id;\n            --finished_member_id;\n\n            int task_id = members[finished_member_id].task_id;\n            int start_day = members[finished_member_id].start_day;\n            int duration = day - start_day + 1;\n\n            members[finished_member_id] = {false, -1, -1};\n            task_status[task_id] = TaskStatus::COMPLETED;\n            completed_task_count++;\n            \n            update_skills(finished_member_id, task_id, duration);\n        }\n    }\n    return 0;\n}\n\n// --- Function Implementations ---\ndouble estimate_work(int task_id, int member_id) {\n    double work = 0;\n    for (int k = 0; k < K; ++k) {\n        work += std::max(0.0, (double)D[task_id][k] - estimated_skills[member_id][k]);\n    }\n    return work;\n}\n\ndouble estimate_time(int task_id, int member_id) {\n    double work = estimate_work(task_id, member_id);\n    if (work < 1e-9) {\n        return 1.0;\n    }\n    double expected_time = 0;\n    for (int r = -3; r <= 3; ++r) {\n        expected_time += std::max(1.0, work + r);\n    }\n    return expected_time / 7.0;\n}\n\nvoid read_initial_input() {\n    std::cin >> K >> R;\n    D.resize(N_TASKS, std::vector<int>(K));\n    for (int i = 0; i < N_TASKS; ++i) {\n        for (int j = 0; j < K; ++j) {\n            std::cin >> D[i][j];\n        }\n    }\n    adj.assign(N_TASKS, std::vector<int>());\n    rev_adj.assign(N_TASKS, std::vector<int>());\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        std::cin >> u >> v;\n        --u; --v;\n        adj[u].push_back(v);\n        rev_adj[v].push_back(u);\n    }\n}\n\nvoid initialize_state() {\n    task_status.assign(N_TASKS, TaskStatus::NOT_STARTED);\n    completed_task_count = 0;\n    members.resize(M_MEMBERS);\n    estimated_skills.assign(M_MEMBERS, std::vector<double>(K, INITIAL_SKILL_ESTIMATE));\n    skill_lower_bounds.assign(M_MEMBERS, std::vector<int>(K, 0));\n    max_d_seen.assign(M_MEMBERS, std::vector<int>(K, 0));\n    skill_update_counts.assign(M_MEMBERS, std::vector<int>(K, 0));\n}\n\nvoid update_skills(int member_id, int task_id, int duration) {\n    for (int k = 0; k < K; ++k) {\n        max_d_seen[member_id][k] = std::max(max_d_seen[member_id][k], D[task_id][k]);\n        if (D[task_id][k] > 0) {\n            skill_update_counts[member_id][k]++;\n        }\n    }\n\n    double predicted_w = estimate_work(task_id, member_id);\n    \n    if (duration == 1) {\n        for (int k = 0; k < K; ++k) {\n            skill_lower_bounds[member_id][k] = std::max(skill_lower_bounds[member_id][k], D[task_id][k]);\n            estimated_skills[member_id][k] = std::max(estimated_skills[member_id][k], (double)skill_lower_bounds[member_id][k]);\n        }\n    } else {\n        double observed_w = duration;\n        \n        if (predicted_w < 1e-6) { // Predicted T=1, but was wrong\n            std::vector<int> candidate_k;\n            for(int k=0; k<K; ++k) if(D[task_id][k] > 0) candidate_k.push_back(k);\n            if (!candidate_k.empty()) {\n                std::vector<double> blame_weights;\n                double total_blame = 0;\n                for (int k : candidate_k) {\n                    double weight = exp(-OVERESTIMATE_CORRECTION_FACTOR * (estimated_skills[member_id][k] - D[task_id][k]));\n                    blame_weights.push_back(weight);\n                    total_blame += weight;\n                }\n                if (total_blame > 1e-9) {\n                    for (size_t i = 0; i < candidate_k.size(); ++i) {\n                        int k = candidate_k[i];\n                        double blamed_deficiency = observed_w * blame_weights[i] / total_blame;\n                        double target_s_k = (double)D[task_id][k] - blamed_deficiency;\n                        \n                        double adaptive_lr_factor = (1.0 + 1.0 / (1.0 + skill_update_counts[member_id][k]));\n                        double effective_lr = std::min(0.99, SKILL_UPDATE_LEARNING_RATE * adaptive_lr_factor);\n                        \n                        estimated_skills[member_id][k] = (1.0 - effective_lr) * estimated_skills[member_id][k] + effective_lr * target_s_k;\n                    }\n                }\n            }\n        } else { // Standard update\n            double error = observed_w - predicted_w;\n            double total_predicted_deficiency = 0;\n            for (int k = 0; k < K; ++k) {\n                if (D[task_id][k] > estimated_skills[member_id][k]) {\n                    total_predicted_deficiency += (D[task_id][k] - estimated_skills[member_id][k]);\n                }\n            }\n            if (total_predicted_deficiency > 1e-9) {\n                 for (int k = 0; k < K; ++k) {\n                     if (D[task_id][k] > estimated_skills[member_id][k]) {\n                        double current_deficiency = D[task_id][k] - estimated_skills[member_id][k];\n                        double adjustment = error * (current_deficiency / total_predicted_deficiency);\n\n                        double adaptive_lr_factor = (1.0 + 1.0 / (1.0 + skill_update_counts[member_id][k]));\n                        double effective_lr = SKILL_UPDATE_LEARNING_RATE * adaptive_lr_factor;\n\n                        estimated_skills[member_id][k] -= effective_lr * adjustment;\n                    }\n                }\n            }\n        }\n    }\n\n    for (int k = 0; k < K; ++k) {\n        estimated_skills[member_id][k] = std::max((double)skill_lower_bounds[member_id][k], estimated_skills[member_id][k]);\n        estimated_skills[member_id][k] = std::max(0.0, estimated_skills[member_id][k]);\n    }\n    \n    std::cout << \"#s \" << member_id + 1;\n    for (int k = 0; k < K; ++k) {\n        std::cout << \" \" << static_cast<int>(round(estimated_skills[member_id][k]));\n    }\n    std::cout << std::endl;\n}","ahc006":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n#include <chrono>\n#include <random>\n\nclass Xoshiro256pp {\npublic:\n    using result_type = uint64_t;\n    static constexpr result_type min() { return std::numeric_limits<result_type>::min(); }\n    static constexpr result_type max() { return std::numeric_limits<result_type>::max(); }\n\n    Xoshiro256pp() : Xoshiro256pp(std::random_device{}()) {}\n    explicit Xoshiro256pp(uint64_t seed) {\n        s[0] = seed; s[1] = 0; s[2] = 0; s[3] = 0;\n    }\n\n    result_type operator()() {\n        const uint64_t result = rotl(s[0] + s[3], 23) + s[0];\n        const uint64_t t = s[1] << 17;\n        s[2] ^= s[0]; s[3] ^= s[1]; s[1] ^= s[2]; s[0] ^= s[3];\n        s[2] ^= t; s[3] = rotl(s[3], 45);\n        return result;\n    }\n\n    int next_int(int min, int max) {\n        if (min > max) return min;\n        return min + operator()() % (uint64_t)(max - min + 1);\n    }\n\n    double next_double() {\n        return (operator()() >> 11) * (1.0 / (1ULL << 53));\n    }\n\nprivate:\n    static inline uint64_t rotl(const uint64_t x, int k) {\n        return (x << k) | (x >> (64 - k));\n    }\n    uint64_t s[4];\n};\n\nXoshiro256pp rng;\n\nstruct Point {\n    int x, y;\n};\n\nstruct Order {\n    int id;\n    Point p, d;\n};\n\nconst int NUM_ORDERS_TOTAL = 1000;\nconst int ORDERS_TO_DELIVER = 50;\nconst int PATH_LEN = ORDERS_TO_DELIVER * 2;\nconst Point OFFICE = {400, 400};\nstd::vector<Order> ALL_ORDERS;\n\nint manhattan(Point p1, Point p2) {\n    return std::abs(p1.x - p2.x) + std::abs(p1.y - p2.y);\n}\n\nstruct State {\n    std::vector<int> selected_g_indices;\n    std::vector<int> path;\n    std::vector<int> pos;\n    long long cost;\n\n    State() : pos(PATH_LEN) {}\n\n    void update_pos() {\n        for (int i = 0; i < PATH_LEN; ++i) {\n            pos[path[i]] = i;\n        }\n    }\n};\n\nPoint get_coord(int node_id, const std::vector<int>& selected_g_indices) {\n    if (node_id < ORDERS_TO_DELIVER) {\n        return ALL_ORDERS[selected_g_indices[node_id]].p;\n    } else {\n        return ALL_ORDERS[selected_g_indices[node_id - ORDERS_TO_DELIVER]].d;\n    }\n}\n\nlong long calculate_full_cost(const std::vector<int>& path, const std::vector<int>& selected_g_indices) {\n    if (path.empty()) return 0;\n    long long total_dist = 0;\n    total_dist += manhattan(OFFICE, get_coord(path[0], selected_g_indices));\n    for (size_t i = 0; i < path.size() - 1; ++i) {\n        total_dist += manhattan(get_coord(path[i], selected_g_indices), get_coord(path[i+1], selected_g_indices));\n    }\n    total_dist += manhattan(get_coord(path.back(), selected_g_indices), OFFICE);\n    return total_dist;\n}\n\nlong long calculate_replace_delta(int local_idx, int new_g_idx, const State& state) {\n    int g_idx_to_remove = state.selected_g_indices[local_idx];\n    int p_node = local_idx, d_node = local_idx + ORDERS_TO_DELIVER;\n    int p_pos = state.pos[p_node], d_pos = state.pos[d_node];\n\n    Point p_old = ALL_ORDERS[g_idx_to_remove].p, d_old = ALL_ORDERS[g_idx_to_remove].d;\n    Point p_new = ALL_ORDERS[new_g_idx].p, d_new = ALL_ORDERS[new_g_idx].d;\n    \n    Point p_prev = (p_pos == 0) ? OFFICE : get_coord(state.path[p_pos-1], state.selected_g_indices);\n    Point p_next = get_coord(state.path[p_pos+1], state.selected_g_indices);\n    Point d_prev = get_coord(state.path[d_pos-1], state.selected_g_indices);\n    Point d_next = (d_pos == PATH_LEN-1) ? OFFICE : get_coord(state.path[d_pos+1], state.selected_g_indices);\n\n    if (d_pos == p_pos + 1) {\n        return manhattan(p_prev, p_new) + manhattan(p_new, d_new) + manhattan(d_new, d_next)\n             - (manhattan(p_prev, p_old) + manhattan(p_old, d_old) + manhattan(d_old, d_next));\n    } else {\n        return (manhattan(p_prev, p_new) + manhattan(p_new, p_next) - manhattan(p_prev, p_old) - manhattan(p_old, p_next))\n             + (manhattan(d_prev, d_new) + manhattan(d_new, d_next) - manhattan(d_prev, d_old) - manhattan(d_old, d_next));\n    }\n}\n\nvoid solve() {\n    auto start_time = std::chrono::steady_clock::now();\n\n    ALL_ORDERS.resize(NUM_ORDERS_TOTAL);\n    for (int i = 0; i < NUM_ORDERS_TOTAL; ++i) {\n        ALL_ORDERS[i].id = i + 1;\n        std::cin >> ALL_ORDERS[i].p.x >> ALL_ORDERS[i].p.y >> ALL_ORDERS[i].d.x >> ALL_ORDERS[i].d.y;\n    }\n    \n    State current_state;\n    std::vector<int> order_indices(NUM_ORDERS_TOTAL);\n    std::iota(order_indices.begin(), order_indices.end(), 0);\n    std::sort(order_indices.begin(), order_indices.end(), [&](int a, int b) {\n        Point center_a = {(ALL_ORDERS[a].p.x + ALL_ORDERS[a].d.x) / 2, (ALL_ORDERS[a].p.y + ALL_ORDERS[a].d.y) / 2};\n        Point center_b = {(ALL_ORDERS[b].p.x + ALL_ORDERS[b].d.x) / 2, (ALL_ORDERS[b].p.y + ALL_ORDERS[b].d.y) / 2};\n        return manhattan(OFFICE, center_a) < manhattan(OFFICE, center_b);\n    });\n    current_state.selected_g_indices.assign(order_indices.begin(), order_indices.begin() + ORDERS_TO_DELIVER);\n\n    for (int i = 0; i < ORDERS_TO_DELIVER; ++i) {\n        int p_node = i, d_node = i + ORDERS_TO_DELIVER;\n        long long min_p_cost_increase = -1; int best_p_pos = 0;\n        for (int j = 0; j <= (int)current_state.path.size(); ++j) {\n            Point prev = (j == 0) ? OFFICE : get_coord(current_state.path[j-1], current_state.selected_g_indices);\n            Point next = (j == (int)current_state.path.size()) ? OFFICE : get_coord(current_state.path[j], current_state.selected_g_indices);\n            long long cost_increase = manhattan(prev, get_coord(p_node, current_state.selected_g_indices)) + manhattan(get_coord(p_node, current_state.selected_g_indices), next) - manhattan(prev, next);\n            if (min_p_cost_increase == -1 || cost_increase < min_p_cost_increase) { min_p_cost_increase = cost_increase; best_p_pos = j; }\n        }\n        current_state.path.insert(current_state.path.begin() + best_p_pos, p_node);\n        long long min_d_cost_increase = -1; int best_d_pos = 0;\n        for (int j = best_p_pos + 1; j <= (int)current_state.path.size(); ++j) {\n            Point prev = get_coord(current_state.path[j-1], current_state.selected_g_indices);\n            Point next = (j == (int)current_state.path.size()) ? OFFICE : get_coord(current_state.path[j], current_state.selected_g_indices);\n            long long cost_increase = manhattan(prev, get_coord(d_node, current_state.selected_g_indices)) + manhattan(get_coord(d_node, current_state.selected_g_indices), next) - manhattan(prev, next);\n            if (min_d_cost_increase == -1 || cost_increase < min_d_cost_increase) { min_d_cost_increase = cost_increase; best_d_pos = j; }\n        }\n        current_state.path.insert(current_state.path.begin() + best_d_pos, d_node);\n    }\n    \n    current_state.cost = calculate_full_cost(current_state.path, current_state.selected_g_indices);\n    current_state.update_pos();\n    State best_state = current_state;\n\n    std::vector<int> not_selected_g_indices;\n    std::vector<bool> is_selected_flags(NUM_ORDERS_TOTAL, false);\n    for(int g_idx : current_state.selected_g_indices) is_selected_flags[g_idx] = true;\n    for(int i=0; i<NUM_ORDERS_TOTAL; ++i) if(!is_selected_flags[i]) not_selected_g_indices.push_back(i);\n    \n    double T_start = 5000, T_end = 2, time_limit = 1.95;\n    \n    while (true) {\n        auto current_time = std::chrono::steady_clock::now();\n        double elapsed_time = std::chrono::duration<double>(current_time - start_time).count();\n        if (elapsed_time > time_limit) break;\n        double T = T_start * std::pow(T_end / T_start, elapsed_time / time_limit);\n        \n        double move_type = rng.next_double();\n        \n        if (move_type < 0.4) {\n            int local_idx_to_remove = rng.next_int(0, ORDERS_TO_DELIVER - 1);\n            int g_idx_to_remove = current_state.selected_g_indices[local_idx_to_remove];\n            int best_not_selected_vec_idx = -1, best_new_g_idx = -1;\n            long long best_delta = -1;\n            const int K = 20;\n            for (int k = 0; k < K; ++k) {\n                int not_selected_vec_idx = rng.next_int(0, not_selected_g_indices.size() - 1);\n                int new_g_idx = not_selected_g_indices[not_selected_vec_idx];\n                long long current_delta = calculate_replace_delta(local_idx_to_remove, new_g_idx, current_state);\n                if (best_delta == -1 || current_delta < best_delta) {\n                    best_delta = current_delta;\n                    best_not_selected_vec_idx = not_selected_vec_idx;\n                    best_new_g_idx = new_g_idx;\n                }\n            }\n            if (best_delta < 0 || rng.next_double() < std::exp(-best_delta / T)) {\n                current_state.selected_g_indices[local_idx_to_remove] = best_new_g_idx;\n                not_selected_g_indices[best_not_selected_vec_idx] = g_idx_to_remove;\n                current_state.cost += best_delta;\n                if (current_state.cost < best_state.cost) best_state = current_state;\n            }\n        } else if (move_type < 0.65) {\n            int i = rng.next_int(0, PATH_LEN-1), j = rng.next_int(0, PATH_LEN-1);\n            if (i >= j) std::swap(i, j); if (j <= i) continue;\n            bool possible = true;\n            for (int k=0; k<ORDERS_TO_DELIVER; ++k) if (current_state.pos[k]>=i && current_state.pos[k]<=j && current_state.pos[k+ORDERS_TO_DELIVER]>=i && current_state.pos[k+ORDERS_TO_DELIVER]<=j) { possible=false; break; }\n            if (!possible) continue;\n            Point pi=get_coord(current_state.path[i], current_state.selected_g_indices), pj=get_coord(current_state.path[j], current_state.selected_g_indices);\n            Point pi_prev=(i>0)?get_coord(current_state.path[i-1], current_state.selected_g_indices):OFFICE;\n            Point pj_next=(j<PATH_LEN-1)?get_coord(current_state.path[j+1], current_state.selected_g_indices):OFFICE;\n            long long delta = manhattan(pi_prev, pj) + manhattan(pi, pj_next) - manhattan(pi_prev, pi) - manhattan(pj, pj_next);\n            if (delta < 0 || rng.next_double() < std::exp(-delta / T)) {\n                std::reverse(current_state.path.begin() + i, current_state.path.begin() + j + 1);\n                for(int k=i; k<=j; ++k) current_state.pos[current_state.path[k]] = k;\n                current_state.cost += delta;\n                if (current_state.cost < best_state.cost) best_state = current_state;\n            }\n        } else if (move_type < 0.9) {\n            int i = rng.next_int(0, PATH_LEN-1), node_to_move = current_state.path[i];\n            int order_idx = node_to_move % ORDERS_TO_DELIVER;\n            int min_j = (node_to_move < ORDERS_TO_DELIVER) ? 0 : current_state.pos[order_idx]+1;\n            int max_j = (node_to_move < ORDERS_TO_DELIVER) ? current_state.pos[order_idx+ORDERS_TO_DELIVER] : PATH_LEN;\n            if (max_j-min_j <= 1) continue;\n            int j = rng.next_int(min_j, max_j);\n            if (j == i || j == i+1) continue;\n            \n            long long delta;\n            Point Pi = get_coord(node_to_move, current_state.selected_g_indices);\n            if (j > i) {\n                Point Pi_m1 = (i > 0) ? get_coord(current_state.path[i-1], current_state.selected_g_indices) : OFFICE;\n                Point Pi_p1 = get_coord(current_state.path[i+1], current_state.selected_g_indices);\n                Point Pj_m1 = get_coord(current_state.path[j-1], current_state.selected_g_indices);\n                Point Pj = (j < PATH_LEN) ? get_coord(current_state.path[j], current_state.selected_g_indices) : OFFICE;\n                delta = (manhattan(Pi_m1, Pi_p1) + manhattan(Pj_m1, Pi) + manhattan(Pi, Pj)) - (manhattan(Pi_m1, Pi) + manhattan(Pi, Pi_p1) + manhattan(Pj_m1, Pj));\n            } else { // j < i\n                Point Pi_m1 = get_coord(current_state.path[i-1], current_state.selected_g_indices);\n                Point Pi_p1 = (i < PATH_LEN-1) ? get_coord(current_state.path[i+1], current_state.selected_g_indices) : OFFICE;\n                Point Pj_m1 = (j > 0) ? get_coord(current_state.path[j-1], current_state.selected_g_indices) : OFFICE;\n                Point Pj = get_coord(current_state.path[j], current_state.selected_g_indices);\n                delta = (manhattan(Pj_m1, Pi) + manhattan(Pi, Pj) + manhattan(Pi_m1, Pi_p1)) - (manhattan(Pj_m1, Pj) + manhattan(Pi_m1, Pi) + manhattan(Pi, Pi_p1));\n            }\n\n            if (delta < 0 || rng.next_double() < std::exp(-delta / T)) {\n                current_state.path.erase(current_state.path.begin() + i);\n                current_state.path.insert(current_state.path.begin() + (j > i ? j-1 : j), node_to_move);\n                current_state.update_pos(); current_state.cost += delta;\n                if (current_state.cost < best_state.cost) best_state = current_state;\n            }\n        } else {\n            int i = rng.next_int(0, PATH_LEN - 1), j = rng.next_int(0, PATH_LEN - 1);\n            if (i >= j) std::swap(i,j); if (i == j) continue;\n            int u = current_state.path[i], v = current_state.path[j];\n            if (u % ORDERS_TO_DELIVER == v % ORDERS_TO_DELIVER) continue;\n            if ((u<ORDERS_TO_DELIVER && j>current_state.pos[u+ORDERS_TO_DELIVER]) || (u>=ORDERS_TO_DELIVER && j<current_state.pos[u-ORDERS_TO_DELIVER])) continue;\n            if ((v<ORDERS_TO_DELIVER && i>current_state.pos[v+ORDERS_TO_DELIVER]) || (v>=ORDERS_TO_DELIVER && i<current_state.pos[v-ORDERS_TO_DELIVER])) continue;\n            long long delta = 0;\n            Point Pu = get_coord(u, current_state.selected_g_indices), Pv = get_coord(v, current_state.selected_g_indices);\n            Point Pu_prev = (i>0)?get_coord(current_state.path[i-1], current_state.selected_g_indices):OFFICE;\n            Point Pv_next = (j<PATH_LEN-1)?get_coord(current_state.path[j+1], current_state.selected_g_indices):OFFICE;\n            if (j == i + 1) {\n                delta = manhattan(Pu_prev, Pv) + manhattan(Pu, Pv_next) - manhattan(Pu_prev, Pu) - manhattan(Pv, Pv_next);\n            } else {\n                Point Pu_next = get_coord(current_state.path[i+1], current_state.selected_g_indices);\n                Point Pv_prev = get_coord(current_state.path[j-1], current_state.selected_g_indices);\n                delta = (manhattan(Pu_prev, Pv) + manhattan(Pv, Pu_next) - (manhattan(Pu_prev, Pu) + manhattan(Pu, Pu_next)))\n                      + (manhattan(Pv_prev, Pu) + manhattan(Pu, Pv_next) - (manhattan(Pv_prev, Pv) + manhattan(Pv, Pv_next)));\n            }\n            if (delta < 0 || rng.next_double() < std::exp(-delta / T)) {\n                std::swap(current_state.path[i], current_state.path[j]);\n                current_state.pos[u] = j; current_state.pos[v] = i;\n                current_state.cost += delta;\n                if (current_state.cost < best_state.cost) best_state = current_state;\n            }\n        }\n    }\n    \n    std::cout << ORDERS_TO_DELIVER;\n    for (int g_idx : best_state.selected_g_indices) std::cout << \" \" << ALL_ORDERS[g_idx].id;\n    std::cout << std::endl;\n    std::cout << best_state.path.size() + 2 << \" \" << OFFICE.x << \" \" << OFFICE.y;\n    for (int node_id : best_state.path) {\n        Point p = get_coord(node_id, best_state.selected_g_indices);\n        std::cout << \" \" << p.x << \" \" << p.y;\n    }\n    std::cout << \" \" << OFFICE.x << \" \" << OFFICE.y << std::endl;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <map>\n#include <tuple>\n#include <iterator> // For std::make_move_iterator\n#include <utility>  // For std::pair\n\n// Using AtCoder Library's DSU\n#include <atcoder/dsu>\n\nstruct Point {\n    int x, y;\n};\n\nstruct Edge {\n    int u, v, id;\n    int original_d;\n};\n\nlong long dist_sq(const Point& p1, const Point& p2) {\n    long long dx = p1.x - p2.x;\n    long long dy = p1.y - p2.y;\n    return dx * dx + dy * dy;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    const int N = 400;\n    const int M = 1995;\n\n    std::vector<Point> vertices(N);\n    for (int i = 0; i < N; ++i) {\n        std::cin >> vertices[i].x >> vertices[i].y;\n    }\n\n    std::vector<Edge> edges(M);\n    std::map<std::pair<int, int>, int> edge_to_id;\n    for (int i = 0; i < M; ++i) {\n        edges[i].id = i;\n        std::cin >> edges[i].u >> edges[i].v;\n        edges[i].original_d = std::round(std::sqrt(dist_sq(vertices[edges[i].u], vertices[edges[i].v])));\n        edge_to_id[{edges[i].u, edges[i].v}] = i;\n    }\n\n    // --- Preprocessing ---\n    std::vector<int> importance(M, 0);\n    {\n        std::vector<std::tuple<int, int, int>> all_possible_edges;\n        all_possible_edges.reserve(N * (N - 1) / 2);\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) {\n                int d = std::round(std::sqrt(dist_sq(vertices[i], vertices[j])));\n                all_possible_edges.emplace_back(d, i, j);\n            }\n        }\n        std::sort(all_possible_edges.begin(), all_possible_edges.end());\n\n        std::vector<bool> used_in_mst(all_possible_edges.size(), false);\n        for (int k = 1; k <= 5; ++k) {\n            atcoder::dsu dsu_mst(N);\n            int edges_in_tree = 0;\n            for (size_t i = 0; i < all_possible_edges.size(); ++i) {\n                if (used_in_mst[i]) continue;\n                auto [d, u, v] = all_possible_edges[i];\n                if (dsu_mst.same(u, v)) continue;\n                dsu_mst.merge(u, v);\n                used_in_mst[i] = true;\n                if (edge_to_id.count({u, v})) {\n                    int original_id = edge_to_id.at({u, v});\n                    if (importance[original_id] == 0) {\n                        importance[original_id] = k;\n                    }\n                }\n                edges_in_tree++;\n                if (edges_in_tree == N - 1) break;\n            }\n        }\n    }\n\n    std::map<std::pair<int, int>, int> edge_id_by_pair;\n    for (int i = 0; i < M; ++i) {\n        edge_id_by_pair[{edges[i].u, edges[i].v}] = i;\n    }\n\n    // --- Main Loop ---\n    atcoder::dsu dsu_main(N);\n    std::vector<std::vector<int>> component_members(N);\n    for(int i = 0; i < N; ++i) {\n        component_members[i] = {i};\n    }\n\n    for (int i = 0; i < M; ++i) {\n        int l;\n        std::cin >> l;\n\n        int u = edges[i].u;\n        int v = edges[i].v;\n\n        if (dsu_main.same(u, v)) {\n            std::cout << 0 << std::endl;\n            continue;\n        }\n\n        int root_u = dsu_main.leader(u);\n        int root_v = dsu_main.leader(v);\n\n        auto find_top2_d_alternatives = \n            [&](const std::vector<int>& comp1, const std::vector<int>& comp2, int current_edge_id) {\n            int min_d1 = -1, min_d2 = -1;\n            for (int member1 : comp1) {\n                for (int member2 : comp2) {\n                    int p1 = std::min(member1, member2);\n                    int p2 = std::max(member1, member2);\n                    auto it = edge_id_by_pair.find({p1, p2});\n                    if (it != edge_id_by_pair.end()) {\n                        int edge_idx = it->second;\n                        if (edge_idx > current_edge_id) {\n                            int d_val = edges[edge_idx].original_d;\n                            if (min_d1 == -1 || d_val < min_d1) {\n                                min_d2 = min_d1;\n                                min_d1 = d_val;\n                            } else if (min_d2 == -1 || d_val < min_d2) {\n                                min_d2 = d_val;\n                            }\n                        }\n                    }\n                }\n            }\n            return std::pair{min_d1, min_d2};\n        };\n        \n        std::pair<int, int> top2_alts;\n        if (component_members[root_u].size() < component_members[root_v].size()) {\n            top2_alts = find_top2_d_alternatives(component_members[root_u], component_members[root_v], i);\n        } else {\n            top2_alts = find_top2_d_alternatives(component_members[root_v], component_members[root_u], i);\n        }\n        auto [min_d1, min_d2] = top2_alts;\n\n        bool take_edge = false;\n        if (min_d1 == -1) {\n            take_edge = true;\n        } else {\n            int imp = importance[i];\n            if (imp == 0) imp = 6;\n\n            double risk_factor;\n            if (min_d2 == -1) {\n                risk_factor = 1.15; // Only one alternative, high risk, be more lenient.\n            } else {\n                double ratio = std::min(static_cast<double>(min_d2) / min_d1, 3.0);\n                // Revert to the peak-performing risk factor from V12\n                risk_factor = 0.825 + 0.35 * (ratio - 1.0); \n            }\n            \n            double alpha_k;\n            switch(imp) {\n                case 1: alpha_k = 1.4; break; case 2: alpha_k = 1.2; break;\n                case 3: alpha_k = 1.0; break; case 4: alpha_k = 0.85; break;\n                case 5: alpha_k = 0.7; break; default: alpha_k = 0.6; break;\n            }\n\n            double progress = static_cast<double>(i) / (M - 1);\n            \n            // New time_factor logic: less punishing for important edges early on.\n            double time_factor_base = 0.7;\n            if (imp == 1) time_factor_base = 0.9;\n            else if (imp == 2) time_factor_base = 0.8;\n            double time_factor = time_factor_base + 1.1 * progress * progress;\n\n            double expected_alt_cost = 2.0 * min_d1;\n            double threshold = alpha_k * time_factor * risk_factor * expected_alt_cost;\n\n            if (l < threshold) {\n                take_edge = true;\n            }\n        }\n        \n        if (take_edge) {\n            std::cout << 1 << std::endl;\n            int old_root_u = dsu_main.leader(u);\n            int old_root_v = dsu_main.leader(v);\n            dsu_main.merge(u, v);\n            int new_root = dsu_main.leader(u);\n            if (new_root == old_root_u) {\n                component_members[old_root_u].insert(component_members[old_root_u].end(),\n                    std::make_move_iterator(component_members[old_root_v].begin()),\n                    std::make_move_iterator(component_members[old_root_v].end()));\n                component_members[old_root_v].clear();\n            } else {\n                component_members[old_root_v].insert(component_members[old_root_v].end(),\n                    std::make_move_iterator(component_members[old_root_u].begin()),\n                    std::make_move_iterator(component_members[old_root_u].end()));\n                component_members[old_root_u].clear();\n            }\n        } else {\n            std::cout << 0 << std::endl;\n        }\n    }\n\n    return 0;\n}","ahc008":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <queue>\n#include <map>\n#include <chrono>\n#include <tuple>\n#include <numeric>\n#include <cstring>\n\nusing namespace std;\n\n// --- Utilities ---\nstruct Point {\n    int r, c;\n\n    bool operator==(const Point& other) const { return r == other.r && c == other.c; }\n    bool operator!=(const Point& other) const { return !(*this == other); }\n    bool operator<(const Point& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n};\n\nnamespace std {\n    template <> struct hash<Point> {\n        size_t operator()(const Point& p) const { return hash<int>()(p.r * 31 + p.c); }\n    };\n}\n\nconst int H = 30, W = 30;\nconst int DR[] = {-1, 1, 0, 0};\nconst int DC[] = {0, 0, -1, 1};\nconst char MOVE_CH[] = {'U', 'D', 'L', 'R'};\nconst char BUILD_CH[] = {'u', 'd', 'l', 'r'};\n\nint N, M;\nvector<Point> pet_pos;\nvector<int> pet_type;\nvector<Point> human_pos;\nbool is_impassable[H][W];\n\nint dist(Point p1, Point p2) {\n    return abs(p1.r - p2.r) + abs(p1.c - p2.c);\n}\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < H && c >= 0 && c < W;\n}\n\n// --- Game State & Strategy ---\nenum StrategyPhase { ASSEMBLY, EXPANSION, SEALING, CONSOLIDATION };\nStrategyPhase current_strategy_phase;\nPoint rendezvous_point;\nint bunker_size = 0;\nvector<Point> bunker_walls;\n\nbool is_safe[H][W];\nvector<double> danger_map(H * W, 0.0);\nint current_turn = 0;\n\n\n// --- A* Pathfinder ---\nstruct Node {\n    Point p; int g; double h; double cost;\n    bool operator>(const Node& other) const { return cost > other.cost; }\n};\n\nvector<Point> find_path(Point start, Point end, const vector<Point>& temp_impassable) {\n    static int g_score[H][W];\n    static Point parent[H][W];\n    memset(g_score, -1, sizeof(g_score));\n\n    priority_queue<Node, vector<Node>, greater<Node>> pq;\n    \n    g_score[start.r][start.c] = 0;\n    pq.push({start, 0, (double)dist(start, end), (double)dist(start, end)});\n    bool found = false;\n    while (!pq.empty()) {\n        Node current = pq.top(); pq.pop();\n        if (current.p == end) { found = true; break; }\n        if (current.g > g_score[current.p.r][current.p.c]) continue;\n\n        for (int i = 0; i < 4; ++i) {\n            Point next_p = {current.p.r + DR[i], current.p.c + DC[i]};\n            if (!is_valid(next_p.r, next_p.c) || is_impassable[next_p.r][next_p.c]) continue;\n            bool is_temp_impassable = false;\n            for(const auto& obs : temp_impassable) if(obs == next_p) {is_temp_impassable = true; break;}\n            if(is_temp_impassable) continue;\n\n            int new_g = current.g + 1;\n            if (g_score[next_p.r][next_p.c] == -1 || new_g < g_score[next_p.r][next_p.c]) {\n                g_score[next_p.r][next_p.c] = new_g; \n                parent[next_p.r][next_p.c] = current.p;\n                double h_val = dist(next_p, end);\n                const double DANGER_WEIGHT = 50.0;\n                double cost = new_g + h_val + DANGER_WEIGHT * danger_map[next_p.r * W + next_p.c];\n                pq.push({next_p, new_g, h_val, cost});\n            }\n        }\n    }\n    if (!found) return {};\n    vector<Point> path; Point curr = end;\n    while (curr != start) { \n        path.push_back(curr); \n        curr = parent[curr.r][curr.c]; \n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nvoid initial_plan() {\n    double pet_com_r = 0, pet_com_c = 0;\n    for (const auto& p : pet_pos) { pet_com_r += p.r; pet_com_c += p.c; }\n    if (N > 0) { pet_com_r /= N; pet_com_c /= N; }\n    double human_com_r = 0, human_com_c = 0;\n    for (const auto& p : human_pos) { human_com_r += p.r; human_com_c += p.c; }\n    if (M > 0) { human_com_r /= M; human_com_c /= M; }\n    vector<Point> corners = {{0, 0}, {0, W - 1}, {H - 1, 0}, {H - 1, W - 1}};\n    double max_score = -1e9;\n    for (const auto& corner : corners) {\n        double d_pet = abs(corner.r - pet_com_r) + abs(corner.c - pet_com_c);\n        double d_human = abs(corner.r - human_com_r) + abs(corner.c - human_com_c);\n        double score = d_pet - 0.5 * d_human;\n        if (score > max_score) { max_score = score; rendezvous_point = corner; }\n    }\n\n    bunker_size = 0;\n    for (int s = 6; s >= 3; --s) {\n        int r_min = (rendezvous_point.r == 0) ? 0 : H - s;\n        int r_max = (rendezvous_point.r == 0) ? s - 1 : H - 1;\n        int c_min = (rendezvous_point.c == 0) ? 0 : W - s;\n        int c_max = (rendezvous_point.c == 0) ? s - 1 : W - 1;\n        bool pet_inside = false;\n        for (const auto& p : pet_pos) {\n            if (p.r >= r_min && p.r <= r_max && p.c >= c_min && p.c <= c_max) { pet_inside = true; break; }\n        }\n        if (!pet_inside) { bunker_size = s; break; }\n    }\n\n    if (bunker_size > 0) {\n        current_strategy_phase = ASSEMBLY;\n        int r_dir = (rendezvous_point.r == 0) ? 1 : -1; int c_dir = (rendezvous_point.c == 0) ? 1 : -1;\n        int wall_r = rendezvous_point.r + r_dir * bunker_size;\n        int wall_c = rendezvous_point.c + c_dir * bunker_size;\n        for(int i = 0; i <= bunker_size; ++i) {\n            Point p1 = {rendezvous_point.r + r_dir*i, wall_c};\n            Point p2 = {wall_r, rendezvous_point.c + c_dir*i};\n            if(is_valid(p1.r, p1.c)) bunker_walls.push_back(p1);\n            if(is_valid(p2.r, p2.c)) bunker_walls.push_back(p2);\n        }\n        sort(bunker_walls.begin(), bunker_walls.end());\n        bunker_walls.erase(unique(bunker_walls.begin(), bunker_walls.end()), bunker_walls.end());\n    } else {\n        current_strategy_phase = EXPANSION;\n    }\n}\n\nvoid update_danger_map() {\n    fill(danger_map.begin(), danger_map.end(), 0.0);\n    int pet_moves[] = {0, 1, 2, 3, 2, 2}; \n    for (int i = 0; i < N; ++i) {\n        int radius = pet_moves[pet_type[i]] + 2;\n        for (int r = 0; r < H; ++r) for (int c = 0; c < W; ++c) if (dist(pet_pos[i], {r, c}) <= radius) danger_map[r * W + c] += 1.0;\n    }\n}\n\nvoid calculate_reachable_area(Point start_node, const bool impassable_map[H][W], bool reachable_map[H][W]) {\n    fill(&reachable_map[0][0], &reachable_map[0][0] + H * W, false);\n    if (!is_valid(start_node.r, start_node.c) || impassable_map[start_node.r][start_node.c]) return;\n    queue<Point> q; q.push(start_node); reachable_map[start_node.r][start_node.c] = true;\n    while (!q.empty()) {\n        Point curr = q.front(); q.pop();\n        for (int i = 0; i < 4; ++i) {\n            Point next_p = {curr.r + DR[i], curr.c + DC[i]};\n            if (is_valid(next_p.r, next_p.c) && !impassable_map[next_p.r][next_p.c] && !reachable_map[next_p.r][next_p.c]) {\n                reachable_map[next_p.r][next_p.c] = true; q.push(next_p);\n            }\n        }\n    }\n}\n\nvoid determine_safe_zone() {\n    bool impassable_with_pets[H][W]; memcpy(impassable_with_pets, is_impassable, sizeof(is_impassable));\n    bool base_safe_zone[H][W]; calculate_reachable_area(rendezvous_point, is_impassable, base_safe_zone);\n    bool pet_inside = false;\n    if (current_turn > 10) {\n        for (const auto& p : pet_pos) if (base_safe_zone[p.r][p.c]) { impassable_with_pets[p.r][p.c] = true; pet_inside = true; }\n    }\n    if (pet_inside) {\n        Point anchor = {-1, -1}; int max_dist_to_pets = -1;\n        for (const auto& h : human_pos) if (base_safe_zone[h.r][h.c] && !impassable_with_pets[h.r][h.c]) {\n            int min_d = 1e9; for (const auto& p : pet_pos) min_d = min(min_d, dist(h, p));\n            if (min_d > max_dist_to_pets) { max_dist_to_pets = min_d; anchor = h; }\n        }\n        if (anchor.r == -1 && !impassable_with_pets[rendezvous_point.r][rendezvous_point.c]) anchor = rendezvous_point;\n        if (anchor.r != -1) calculate_reachable_area(anchor, impassable_with_pets, is_safe);\n        else fill(&is_safe[0][0], &is_safe[0][0] + H * W, false);\n    } else { memcpy(is_safe, base_safe_zone, sizeof(base_safe_zone)); }\n}\n\nvoid check_phase_transition() {\n    if (current_strategy_phase == ASSEMBLY) {\n        bool all_walls_built = true;\n        for(const auto& p : bunker_walls) if(!is_impassable[p.r][p.c]) { all_walls_built = false; break; }\n        if (all_walls_built || current_turn > 60) current_strategy_phase = EXPANSION;\n    }\n    if (current_turn >= 260 && current_strategy_phase == EXPANSION) current_strategy_phase = SEALING;\n    if (current_turn >= 290) current_strategy_phase = CONSOLIDATION;\n}\n\nstring solve() {\n    if (current_turn == 0) initial_plan();\n    check_phase_transition();\n    update_danger_map();\n    determine_safe_zone();\n    \n    vector<bool> can_build(H * W, true);\n    for(int r=0; r<H; ++r) for(int c=0; c<W; ++c) if (is_impassable[r][c]) can_build[r*W+c] = false;\n    for (const auto& p : human_pos) can_build[p.r*W+p.c] = false;\n    for (const auto& p : pet_pos) { can_build[p.r*W+p.c] = false; for (int i=0; i<4; ++i) { Point adj = {p.r+DR[i], p.c+DC[i]}; if (is_valid(adj.r, adj.c)) can_build[adj.r*W+adj.c] = false; }}\n\n    string actions_str(M, '.');\n    vector<Point> planned_walls;\n    vector<bool> human_has_action(M, false);\n\n    // --- Pass 1: Plan Builds ---\n    if (current_strategy_phase == ASSEMBLY || current_strategy_phase == EXPANSION || current_strategy_phase == SEALING) {\n        vector<Point> build_tasks;\n        if(current_strategy_phase == ASSEMBLY) {\n            for(const auto& p : bunker_walls) if(!is_impassable[p.r][p.c]) build_tasks.push_back(p);\n        } else {\n            for (int r=0; r<H; ++r) for (int c=0; c<W; ++c) if (!is_safe[r][c] && !is_impassable[r][c]) {\n                for (int i=0; i<4; ++i) { Point adj = {r+DR[i], c+DC[i]}; if (is_valid(adj.r, adj.c) && is_safe[adj.r][adj.c]) { build_tasks.push_back({r,c}); break; } }\n            }\n        }\n        \n        if (!build_tasks.empty()) {\n            using BuildCand = tuple<double, int, int>; vector<BuildCand> build_candidates;\n            for (int i = 0; i < M; ++i) {\n                for (size_t j = 0; j < build_tasks.size(); ++j) {\n                    Point task_pos = build_tasks[j];\n                    if (dist(human_pos[i], task_pos) == 1 && is_safe[human_pos[i].r][human_pos[i].c]) {\n                        int k = 0; for(int d=0; d<4; ++d) { Point adj = {task_pos.r+DR[d],task_pos.c+DC[d]}; if (!is_valid(adj.r,adj.c)||is_impassable[adj.r][adj.c]) k++; }\n                        double value = pow(1.0 + k, 2.0) * (5.0 + dist(task_pos, rendezvous_point)) / (1.0 + danger_map[task_pos.r*W+task_pos.c]);\n                        build_candidates.emplace_back(-value, i, j);\n                    }\n                }\n            }\n            sort(build_candidates.begin(), build_candidates.end());\n            vector<bool> task_taken(build_tasks.size(), false);\n            for (const auto& cand : build_candidates) {\n                int h_idx = get<1>(cand); int t_idx = get<2>(cand);\n                if (human_has_action[h_idx] || task_taken[t_idx]) continue;\n                Point task_pos = build_tasks[t_idx];\n                if (can_build[task_pos.r*W+task_pos.c]) {\n                    for (int d = 0; d < 4; ++d) {\n                        if (human_pos[h_idx].r + DR[d] == task_pos.r && human_pos[h_idx].c + DC[d] == task_pos.c) {\n                            actions_str[h_idx] = BUILD_CH[d]; planned_walls.push_back(task_pos);\n                            human_has_action[h_idx] = true; task_taken[t_idx] = true;\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // --- Pass 2: Plan Moves ---\n    for (int i = 0; i < M; ++i) {\n        if (human_has_action[i]) continue;\n        Point goal = rendezvous_point; bool has_goal = false;\n        \n        if (current_strategy_phase == ASSEMBLY) {\n            int r_min = (rendezvous_point.r == 0) ? 0 : H - bunker_size; int r_max = (rendezvous_point.r == 0) ? bunker_size - 1 : H - 1;\n            int c_min = (rendezvous_point.c == 0) ? 0 : W - bunker_size; int c_max = (rendezvous_point.c == 0) ? bunker_size - 1 : W - 1;\n            Point p = human_pos[i];\n            if (p.r < r_min || p.r > r_max || p.c < c_min || p.c > c_max) { has_goal = true; } // if outside, move to rendezvous\n        } else if (current_strategy_phase == EXPANSION || current_strategy_phase == SEALING) {\n            if(!is_safe[human_pos[i].r][human_pos[i].c]){\n                goal = rendezvous_point; has_goal = true;\n            } else {\n                vector<Point> build_tasks;\n                for (int r=0; r<H; ++r) for (int c=0; c<W; ++c) if (!is_safe[r][c] && !is_impassable[r][c]) {\n                    for (int d=0; d<4; ++d) { Point adj = {r+DR[d], c+DC[d]}; if (is_valid(adj.r, adj.c) && is_safe[adj.r][adj.c]) { build_tasks.push_back({r,c}); break; } }\n                }\n                double best_score = -1e9;\n                if (!build_tasks.empty()) {\n                    for(const auto& task_pos : build_tasks){\n                        int k = 0; for(int d=0; d<4; ++d) { Point adj = {task_pos.r+DR[d],task_pos.c+DC[d]}; if (!is_valid(adj.r,adj.c)||is_impassable[adj.r][adj.c]) k++; }\n                        double value = pow(1.0 + k, 2.0) * (5.0 + dist(task_pos, rendezvous_point)) / (1.0 + danger_map[task_pos.r*W+task_pos.c]);\n                        Point best_build_site = {-1,-1}; int min_dist = 1e9; for (int d=0; d<4; ++d) { Point site = {task_pos.r+DR[d], task_pos.c+DC[d]}; if (is_valid(site.r, site.c) && is_safe[site.r][site.c]) { int cur_d = dist(human_pos[i], site); if (cur_d < min_dist) { min_dist = cur_d; best_build_site = site;} } }\n                        if(best_build_site.r != -1) {\n                            double score = value / (1.0 + min_dist);\n                            if(score > best_score) { best_score = score; goal = best_build_site; has_goal = true;}\n                        }\n                    }\n                }\n            }\n        } else if(current_strategy_phase == CONSOLIDATION) {\n            double center_r=0, center_c=0; int count=0;\n            for (int r=0; r<H; ++r) for (int c=0; c<W; ++c) if (is_safe[r][c]) { center_r+=r; center_c+=c; count++; }\n            if (count > 0) { goal = {(int)round(center_r/count), (int)round(center_c/count)}; has_goal = true;}\n        }\n\n        if(has_goal && human_pos[i] != goal) {\n            vector<Point> path = find_path(human_pos[i], goal, planned_walls);\n            if (!path.empty()) {\n                Point next_pos = path[0];\n                for (int d = 0; d < 4; ++d) {\n                    if (human_pos[i].r + DR[d] == next_pos.r && human_pos[i].c + DC[d] == next_pos.c) {\n                        actions_str[i] = MOVE_CH[d];\n                        break;\n                    }\n                }\n            }\n        }\n    }\n    return actions_str;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false); cin.tie(NULL);\n    cin >> N;\n    pet_pos.resize(N); pet_type.resize(N);\n    for (int i=0; i<N; ++i) { cin >> pet_pos[i].r >> pet_pos[i].c >> pet_type[i]; pet_pos[i].r--; pet_pos[i].c--; }\n    cin >> M;\n    human_pos.resize(M);\n    for (int i=0; i<M; ++i) { cin >> human_pos[i].r >> human_pos[i].c; human_pos[i].r--; human_pos[i].c--; }\n    fill(&is_impassable[0][0], &is_impassable[0][0]+H*W, false);\n    for (int t=0; t<300; ++t) {\n        current_turn = t;\n        string actions = solve();\n        cout << actions << endl;\n        vector<Point> temp_walls;\n        for(int i=0; i<M; ++i) { char act = actions[i]; Point p = human_pos[i]; if (act == 'u') temp_walls.push_back({p.r-1, p.c}); else if (act == 'd') temp_walls.push_back({p.r+1, p.c}); else if (act == 'l') temp_walls.push_back({p.r, p.c-1}); else if (act == 'r') temp_walls.push_back({p.r, p.c+1}); }\n        for(int i=0; i<M; ++i) {\n            char act = actions[i]; Point& p = human_pos[i]; Point next_p = p;\n            if (act == 'U') next_p.r--; else if (act == 'D') next_p.r++; else if (act == 'L') next_p.c--; else if (act == 'R') next_p.c++;\n            bool blocked = false; for(const auto& w : temp_walls) if(next_p == w) blocked = true;\n            if (act >= 'A' && act <= 'Z' && !blocked) p = next_p;\n            else if (act >= 'a' && act <= 'z') { if (act == 'u') is_impassable[p.r-1][p.c] = true; else if (act == 'd') is_impassable[p.r+1][p.c] = true; else if (act == 'l') is_impassable[p.r][p.c-1] = true; else if (act == 'r') is_impassable[p.r][p.c+1] = true; }\n        }\n        for (int i=0; i<N; ++i) { string move_str; cin >> move_str; for (char move : move_str) { if (move == 'U') pet_pos[i].r--; else if (move == 'D') pet_pos[i].r++; else if (move == 'L') pet_pos[i].c--; else if (move == 'R') pet_pos[i].c++; } }\n    }\n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <array>\n#include <algorithm>\n#include <cmath>\n#include <utility>\n#include <functional>\n\nusing namespace std;\n\n// Using long double for better precision\nusing ld = long double;\n\nconstexpr int N = 20;\nconstexpr int MAX_TURNS = 200;\nconstexpr int BEAM_WIDTH = 250; // Increased beam width thanks to optimizations\nconstexpr int K_FOR_CENTER_OF_MASS = 10;\nconstexpr ld PROB_PRUNING_THRESH = 1e-30L;\nconstexpr ld TOTAL_PROB_THRESH = 1e-20L;\n\nstruct State {\n    int r, c;\n    bool operator==(const State& other) const {\n        return r == other.r && c == other.c;\n    }\n};\n\nstruct ProbEntry {\n    State s;\n    ld p;\n};\n\nState start_pos, target_pos;\nld forget_prob;\narray<array<bool, N - 1>, N> h_walls;\narray<array<bool, N>, N - 1> v_walls;\narray<array<int, N>, N> dist_to_target;\narray<array<array<State, 4>, N>, N> next_pos_cache;\n\nconst int DR[] = {-1, 1, 0, 0}; // U, D, L, R\nconst int DC[] = {0, 0, -1, 1};\nconst char DIRS[] = \"UDLR\";\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N;\n}\n\nState internal_move_state(State s, int dir_idx) {\n    int nr = s.r + DR[dir_idx];\n    int nc = s.c + DC[dir_idx];\n\n    if (!is_valid(nr, nc)) return s;\n    if (DR[dir_idx] == -1 && v_walls[s.r - 1][s.c]) return s;\n    if (DR[dir_idx] == 1 && v_walls[s.r][s.c]) return s;\n    if (DC[dir_idx] == -1 && h_walls[s.r][s.c - 1]) return s;\n    if (DC[dir_idx] == 1 && h_walls[s.r][s.c]) return s;\n    \n    return {nr, nc};\n}\n\nvoid precompute_moves() {\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            for (int i = 0; i < 4; ++i) {\n                next_pos_cache[r][c][i] = internal_move_state({r, c}, i);\n            }\n        }\n    }\n}\n\nState move_state(State s, int dir_idx) {\n    return next_pos_cache[s.r][s.c][dir_idx];\n}\n\nvoid bfs_from_target() {\n    for (auto& row : dist_to_target) row.fill(-1);\n    queue<State> q;\n    q.push(target_pos);\n    dist_to_target[target_pos.r][target_pos.c] = 0;\n    \n    while (!q.empty()) {\n        State u = q.front();\n        q.pop();\n        \n        for (int i = 0; i < 4; ++i) {\n            State predecessor = {u.r - DR[i], u.c - DC[i]};\n            if (!is_valid(predecessor.r, predecessor.c)) continue;\n            \n            State moved_from_predecessor = move_state(predecessor, i);\n            if (moved_from_predecessor.r == u.r && moved_from_predecessor.c == u.c) {\n                 if (dist_to_target[predecessor.r][predecessor.c] == -1) {\n                    dist_to_target[predecessor.r][predecessor.c] = dist_to_target[u.r][u.c] + 1;\n                    q.push(predecessor);\n                }\n            }\n        }\n    }\n}\n\nstruct Candidate {\n    string moves;\n    vector<ProbEntry> prob_dist;\n    ld accumulated_score;\n    ld heuristic_score;\n\n    void calculate_heuristic_score(int turn) {\n        ld future_score = 0;\n        for (const auto& entry : prob_dist) {\n            int d = dist_to_target[entry.s.r][entry.s.c];\n            if (d <= 0) continue;\n            ld expected_turns_to_reach = (ld)d / (1.0L - forget_prob);\n            if (turn + expected_turns_to_reach <= 400) {\n               future_score += entry.p * (401.0L - (turn + expected_turns_to_reach));\n            }\n        }\n        heuristic_score = accumulated_score + future_score;\n    }\n};\n\nstatic array<ld, N*N> next_prob_map;\nstatic vector<int> dirty_indices;\nstatic array<bool, N*N> is_dirty;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> start_pos.r >> start_pos.c >> target_pos.r >> target_pos.c;\n    double p_double;\n    cin >> p_double;\n    forget_prob = p_double;\n\n    for (int i = 0; i < N; ++i) {\n        string row; cin >> row;\n        for (int j = 0; j < N - 1; ++j) h_walls[i][j] = (row[j] == '1');\n    }\n    for (int i = 0; i < N - 1; ++i) {\n        string row; cin >> row;\n        for (int j = 0; j < N; ++j) v_walls[i][j] = (row[j] == '1');\n    }\n    \n    precompute_moves();\n    bfs_from_target();\n    dirty_indices.reserve(N * N);\n\n    vector<Candidate> beam;\n    {\n        Candidate initial_candidate;\n        initial_candidate.moves = \"\";\n        initial_candidate.prob_dist.push_back({start_pos, 1.0L});\n        initial_candidate.accumulated_score = 0.0L;\n        initial_candidate.calculate_heuristic_score(1);\n        beam.push_back(initial_candidate);\n    }\n    \n    for (int t = 1; t <= MAX_TURNS; ++t) {\n        vector<Candidate> next_candidates;\n        next_candidates.reserve(beam.size() * 4);\n\n        for (const auto& cand : beam) {\n            ld total_prob_mass = 0;\n            for (const auto& entry : cand.prob_dist) {\n                total_prob_mass += entry.p;\n            }\n            if(total_prob_mass < TOTAL_PROB_THRESH) {\n                next_candidates.push_back(cand);\n                continue;\n            }\n\n            // --- DYNAMIC MOVE ORDERING ---\n            vector<ProbEntry> current_probs = cand.prob_dist;\n            ld dr, dc;\n            if (current_probs.empty()) {\n                dr = target_pos.r - start_pos.r;\n                dc = target_pos.c - start_pos.c;\n            } else {\n                int k_actual = min((int)current_probs.size(), K_FOR_CENTER_OF_MASS);\n                partial_sort(current_probs.begin(), current_probs.begin() + k_actual, current_probs.end(),\n                             [](const ProbEntry& a, const ProbEntry& b) { return a.p > b.p; });\n\n                ld total_top_prob = 0, avg_r = 0, avg_c = 0;\n                for(int i = 0; i < k_actual; ++i) {\n                    total_top_prob += current_probs[i].p;\n                    avg_r += current_probs[i].p * current_probs[i].s.r;\n                    avg_c += current_probs[i].p * current_probs[i].s.c;\n                }\n                avg_r /= total_top_prob; avg_c /= total_top_prob;\n                dr = target_pos.r - avg_r; dc = target_pos.c - avg_c;\n            }\n            \n            vector<pair<ld, int>> move_scores;\n            move_scores.push_back({-dr, 0}); move_scores.push_back({dr, 1});\n            move_scores.push_back({-dc, 2}); move_scores.push_back({dc, 3});\n            sort(move_scores.rbegin(), move_scores.rend());\n            \n            array<int, 4> dynamic_dirs_order;\n            for(int i = 0; i < 4; ++i) dynamic_dirs_order[i] = move_scores[i].second;\n            // --- END DYNAMIC MOVE ORDERING ---\n\n            for (int dir_idx : dynamic_dirs_order) {\n                ld prob_reaching_this_turn = 0.0L;\n\n                for (const auto& entry : cand.prob_dist) {\n                    const State& current_pos = entry.s;\n                    const ld& current_p = entry.p;\n                    \n                    int current_idx = current_pos.r * N + current_pos.c;\n                    if (!is_dirty[current_idx]) {\n                        is_dirty[current_idx] = true;\n                        dirty_indices.push_back(current_idx);\n                    }\n                    next_prob_map[current_idx] += current_p * forget_prob;\n\n                    State next_pos = move_state(current_pos, dir_idx);\n                    if (next_pos == target_pos) {\n                        prob_reaching_this_turn += current_p * (1.0L - forget_prob);\n                    } else {\n                        int next_idx = next_pos.r * N + next_pos.c;\n                        if (!is_dirty[next_idx]) {\n                            is_dirty[next_idx] = true;\n                            dirty_indices.push_back(next_idx);\n                        }\n                        next_prob_map[next_idx] += current_p * (1.0L - forget_prob);\n                    }\n                }\n                \n                Candidate next_cand;\n                next_cand.moves = cand.moves + DIRS[dir_idx];\n                next_cand.prob_dist.reserve(dirty_indices.size());\n                for(int idx : dirty_indices) {\n                    if (next_prob_map[idx] > PROB_PRUNING_THRESH) {\n                        next_cand.prob_dist.push_back({{idx/N, idx%N}, next_prob_map[idx]});\n                    }\n                    // Cleanup for next iteration\n                    next_prob_map[idx] = 0.0L;\n                    is_dirty[idx] = false;\n                }\n                dirty_indices.clear();\n\n                next_cand.accumulated_score = cand.accumulated_score + prob_reaching_this_turn * (401 - t);\n                next_cand.calculate_heuristic_score(t + 1);\n                \n                next_candidates.push_back(move(next_cand));\n            }\n        }\n\n        sort(next_candidates.begin(), next_candidates.end(), [](const Candidate& a, const Candidate& b) {\n            return a.heuristic_score > b.heuristic_score;\n        });\n\n        if (next_candidates.size() > BEAM_WIDTH) {\n            next_candidates.resize(BEAM_WIDTH);\n        }\n        beam = move(next_candidates);\n    }\n\n    Candidate best_candidate;\n    ld max_score = -1.0;\n    for (const auto& cand : beam) {\n        if (cand.accumulated_score > max_score) {\n            max_score = cand.accumulated_score;\n            best_candidate = cand;\n        }\n    }\n\n    cout << best_candidate.moves << endl;\n\n    return 0;\n}","ahc010":"#include <iostream>\n#include <vector>\n#include <string>\n#include <array>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <cmath>\n#include <tuple>\n\n// --- Utilities ---\nclass Timer {\n    std::chrono::time_point<std::chrono::high_resolution_clock> start_time;\npublic:\n    Timer() {\n        start_time = std::chrono::high_resolution_clock::now();\n    }\n    double get_elapsed_sec() {\n        auto now = std::chrono::high_resolution_clock::now();\n        return std::chrono::duration<double>(now - start_time).count();\n    }\n};\n\nstruct Rng {\n    std::mt19937 mt;\n    Rng() : mt(std::chrono::high_resolution_clock::now().time_since_epoch().count()) {}\n    int get_int(int min, int max) {\n        std::uniform_int_distribution<int> dist(min, max);\n        return dist(mt);\n    }\n    double get_double(double min, double max) {\n        std::uniform_real_distribution<double> dist(min, max);\n        return dist(mt);\n    }\n};\n\n// --- Problem Constants & Globals ---\nconstexpr int N = 30;\nconstexpr int di[] = {0, -1, 0, 1}; // L, U, R, D\nconstexpr int dj[] = {-1, 0, 1, 0};\nconst int to[8][4] = {\n\t{1, 0, -1, -1}, {3, -1, -1, 0}, {-1, -1, 3, 2}, {-1, 2, 1, -1},\n\t{1, 0, 3, 2},   {3, 2, 1, 0},   {2, -1, 0, -1}, {-1, 3, -1, 1},\n};\nint t_rot[8][4];\nstd::array<std::array<int, N>, N> initial_tiles;\n\nvoid precompute_rotations() {\n    for (int i = 0; i < 8; ++i) t_rot[i][0] = i;\n    for (int r = 1; r < 4; ++r) {\n        for (int i = 0; i < 8; ++i) {\n            int prev_t = t_rot[i][r - 1];\n            int next_t;\n            if (0 <= prev_t && prev_t <= 3) next_t = (prev_t + 1) % 4;\n            else if (prev_t == 4) next_t = 5;\n            else if (prev_t == 5) next_t = 4;\n            else if (prev_t == 6) next_t = 7;\n            else next_t = 6;\n            t_rot[i][r] = next_t;\n        }\n    }\n}\n\n// --- Core Logic ---\nusing RotationsGrid = std::array<std::array<int, N>, N>;\n\nstruct ScoreInfo {\n    long long product_score = 0;\n    long long total_len_score = 0;\n};\n\nScoreInfo calculate_scores(const RotationsGrid& rotations) {\n    std::array<std::array<int, N>, N> tiles;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            tiles[i][j] = t_rot[initial_tiles[i][j]][rotations[i][j]];\n        }\n    }\n\n    bool visited_edge[N][N][4] = {};\n    std::vector<int> loop_lengths;\n    long long total_path_len_sum = 0;\n\n    for (int si = 0; si < N; ++si) {\n        for (int sj = 0; sj < N; ++sj) {\n            for (int sd = 0; sd < 4; ++sd) {\n                if (visited_edge[si][sj][sd]) continue;\n\n                int ci = si, cj = sj, cd = sd;\n                int length = 0;\n                std::vector<std::tuple<int, int, int>> path_history;\n                bool is_loop = false;\n\n                for(int k=0; k < N*N*2 + 5; ++k) {\n                    path_history.emplace_back(ci, cj, cd);\n                    \n                    int d_out = to[tiles[ci][cj]][cd];\n                    if (d_out == -1) break;\n\n                    int ni = ci + di[d_out];\n                    int nj = cj + dj[d_out];\n                    \n                    if (ni < 0 || ni >= N || nj < 0 || nj >= N) break;\n                    \n                    length++;\n                    ci = ni; cj = nj; cd = (d_out + 2) % 4;\n\n                    if (ci == si && cj == sj && cd == sd) {\n                        is_loop = true;\n                        break;\n                    }\n                    if (visited_edge[ci][cj][cd]) break;\n                }\n\n                if (length > 0) {\n                    total_path_len_sum += length;\n                }\n                \n                if (is_loop) {\n                    loop_lengths.push_back(length);\n                }\n                \n                for (const auto& [pi, pj, pd] : path_history) {\n                    visited_edge[pi][pj][pd] = true;\n                }\n            }\n        }\n    }\n\n    ScoreInfo info;\n    \n    long long loop_len_sum = 0;\n    for(int len : loop_lengths) {\n        loop_len_sum += len;\n    }\n    long long open_path_len_doubled = total_path_len_sum - loop_len_sum;\n    info.total_len_score = loop_len_sum + open_path_len_doubled / 2;\n\n    if (loop_lengths.size() >= 2) {\n        std::sort(loop_lengths.rbegin(), loop_lengths.rend());\n        info.product_score = static_cast<long long>(loop_lengths[0]) * loop_lengths[1];\n    }\n\n    return info;\n}\n\n\nvoid solve() {\n    Timer timer;\n    Rng rng;\n    \n    for (int i = 0; i < N; ++i) {\n        std::string row;\n        std::cin >> row;\n        for (int j = 0; j < N; ++j) {\n            initial_tiles[i][j] = row[j] - '0';\n        }\n    }\n    precompute_rotations();\n\n    RotationsGrid current_rotations;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            current_rotations[i][j] = rng.get_int(0, 3);\n        }\n    }\n\n    RotationsGrid best_rotations_ever = current_rotations;\n    ScoreInfo current_scores = calculate_scores(current_rotations);\n    long long best_prod_score_ever = current_scores.product_score;\n\n    const double time_limit = 1.95;\n    const double phase1_time_limit = time_limit * 0.50;\n\n    // --- Phase 1: Optimize for total path length ---\n    double T_start1 = 20, T_end1 = 0.5;\n    long long current_eval_score = current_scores.total_len_score;\n    \n    while (timer.get_elapsed_sec() < phase1_time_limit) {\n        double progress = timer.get_elapsed_sec() / phase1_time_limit;\n        double T = T_start1 * std::pow(T_end1 / T_start1, progress);\n        \n        RotationsGrid next_rotations = current_rotations;\n        if (rng.get_double(0.0, 1.0) < 0.2) { \n            int r = rng.get_int(0, N - 2); int c = rng.get_int(0, N - 2);\n            for(int i=0; i<2; ++i) for(int j=0; j<2; ++j) next_rotations[r+i][c+j] = rng.get_int(0,3);\n        } else {\n            int r = rng.get_int(0, N - 1); int c = rng.get_int(0, N - 1);\n            int old_rot = next_rotations[r][c];\n            int new_rot; do { new_rot = rng.get_int(0, 3); } while (new_rot == old_rot);\n            next_rotations[r][c] = new_rot;\n        }\n\n        ScoreInfo new_scores = calculate_scores(next_rotations);\n        long long new_eval_score = new_scores.total_len_score;\n        double delta = static_cast<double>(new_eval_score - current_eval_score);\n        \n        if (delta >= 0 || rng.get_double(0.0, 1.0) < std::exp(delta / T)) {\n            current_rotations = next_rotations;\n            current_eval_score = new_eval_score;\n            current_scores = new_scores;\n        }\n        \n        if (current_scores.product_score > best_prod_score_ever) {\n            best_prod_score_ever = current_scores.product_score;\n            best_rotations_ever = current_rotations;\n        }\n    }\n    \n    // --- Phase 2: Optimize for L1 * L2 ---\n    current_rotations = best_rotations_ever;\n    current_scores = calculate_scores(current_rotations);\n    current_eval_score = current_scores.product_score;\n    \n    double T_start2 = 5000, T_end2 = 10;\n    while (timer.get_elapsed_sec() < time_limit) {\n        double elapsed_in_phase2 = timer.get_elapsed_sec() - phase1_time_limit;\n        double phase2_duration = time_limit - phase1_time_limit;\n        double progress = elapsed_in_phase2 / phase2_duration;\n        double T = T_start2 * std::pow(T_end2 / T_start2, progress);\n\n        RotationsGrid next_rotations = current_rotations;\n        if (rng.get_double(0.0, 1.0) < 0.05) {\n            int r = rng.get_int(0, N - 2); int c = rng.get_int(0, N - 2);\n            for(int i=0; i<2; ++i) for(int j=0; j<2; ++j) next_rotations[r+i][c+j] = rng.get_int(0,3);\n        } else {\n            int r = rng.get_int(0, N - 1); int c = rng.get_int(0, N - 1);\n            int old_rot = next_rotations[r][c];\n            int new_rot; do { new_rot = rng.get_int(0, 3); } while (new_rot == old_rot);\n            next_rotations[r][c] = new_rot;\n        }\n        \n        ScoreInfo new_scores = calculate_scores(next_rotations);\n        long long new_eval_score = new_scores.product_score;\n        double delta = static_cast<double>(new_eval_score - current_eval_score);\n        \n        if (delta >= 0 || rng.get_double(0.0, 1.0) < std::exp(delta / T)) {\n            current_rotations = next_rotations;\n            current_eval_score = new_eval_score;\n            if (current_eval_score > best_prod_score_ever) {\n                best_prod_score_ever = current_eval_score;\n                best_rotations_ever = current_rotations;\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            std::cout << best_rotations_ever[i][j];\n        }\n    }\n    std::cout << std::endl;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc011":"#include <iostream>\n#include <vector>\n#include <string>\n#include <array>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <cmath>\n#include <map>\n#include <queue>\n#include <unordered_map>\n#include <functional>\n\n#include <atcoder/mincostflow>\n\nusing namespace std;\n\n// --- Timer ---\nusing namespace std::chrono;\nauto start_time = high_resolution_clock::now();\ndouble time_limit = 2.85; // More conservative time limit\n\nbool is_time_over() {\n    auto current_time = high_resolution_clock::now();\n    duration<double> elapsed = current_time - start_time;\n    return elapsed.count() > time_limit;\n}\n\n// --- Random Number Generator ---\nmt19937 rng(time(0));\n\n// --- Constants and Type Definitions ---\nconstexpr int MAX_N = 10;\nconstexpr int MAX_N2 = MAX_N * MAX_N;\n\nint N, T;\narray<int, 4> dr = {-1, 1, 0, 0}; // U, D, L, R\narray<int, 4> dc = {0, 0, -1, 1};\nstring move_chars = \"UDLR\";\narray<int, 4> opposite_move_idx = {1, 0, 3, 2}; // U->D, D->U, L->R, R->L\n\nstruct Board {\n    array<int, MAX_N2> grid;\n    int empty_pos = -1;\n    void find_empty() {\n        for (int i = 0; i < N * N; ++i) {\n            if (grid[i] == 0) {\n                empty_pos = i;\n                return;\n            }\n        }\n    }\n};\n\nint char_to_hex(char c) {\n    if (c >= '0' && c <= '9') return c - '0';\n    return c - 'a' + 10;\n}\n\nstruct DSU {\n    vector<int> parent;\n    vector<int> sz;\n    DSU(int n) {\n        parent.resize(n);\n        sz.resize(n);\n        for (int i = 0; i < n; i++) {\n            parent[i] = i;\n            sz[i] = 1;\n        }\n    }\n    int find(int i) {\n        if (parent[i] == i) return i;\n        return parent[i] = find(parent[i]);\n    }\n    void unite(int i, int j) {\n        int root_i = find(i);\n        int root_j = find(j);\n        if (root_i != root_j) {\n            if (sz[root_i] < sz[root_j]) swap(root_i, root_j);\n            parent[root_j] = root_i;\n            sz[root_i] += sz[root_j];\n        }\n    }\n};\n\n// --- Global State for Solver ---\nBoard initial_board;\narray<int, 16> initial_tile_counts{};\nvector<pair<int, int>> initial_pos_by_type[16];\narray<int, MAX_N2> best_target_grid;\nlong long best_dist_score = -1;\narray<int, MAX_N2> dest_of_tile_id;\nstring ida_solution;\nconst int IDA_FOUND = -1;\nconst int IDA_TIMEOUT = -2;\n\nvoid evaluate_target(const array<int, MAX_N2>& target_grid, long long& connectivity_score, long long& dist_score) {\n    DSU dsu(N * N);\n    int edges = 0;\n    connectivity_score = 0;\n\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int pos = r * N + c;\n            if (target_grid[pos] == 0) continue;\n            if (r + 1 < N && target_grid[(r+1)*N+c] != 0 && (target_grid[pos] & 8) && (target_grid[(r+1)*N+c] & 2)) {\n                if (dsu.find(pos) == dsu.find((r+1)*N+c)) connectivity_score -= 10000000;\n                else { dsu.unite(pos, (r+1)*N+c); edges++; }\n            }\n            if (c + 1 < N && target_grid[r*N+c+1] != 0 && (target_grid[pos] & 4) && (target_grid[r*N+c+1] & 1)) {\n                if (dsu.find(pos) == dsu.find(r*N+c+1)) connectivity_score -= 10000000;\n                else { dsu.unite(pos, r*N+c+1); edges++; }\n            }\n        }\n    }\n    \n    int non_empty_cells = N * N - 1;\n    int max_comp_size = 0;\n    for(int i = 0; i < N * N; ++i) {\n        if(target_grid[i] != 0 && dsu.parent[i] == i) max_comp_size = max(max_comp_size, dsu.sz[i]);\n    }\n    \n    connectivity_score += (long long)max_comp_size * 100000;\n    if (max_comp_size == non_empty_cells && edges == non_empty_cells - 1) connectivity_score += 100000000;\n\n    vector<int> target_pos_by_type[16];\n    for(int i=0; i<N*N; ++i) if(target_grid[i] != 0) target_pos_by_type[target_grid[i]].push_back(i);\n    \n    dist_score = 0;\n    for (int type = 1; type <= 15; ++type) {\n        if (initial_tile_counts[type] == 0) continue;\n        vector<pair<int, int>> s_coords, d_coords;\n        for (auto p : initial_pos_by_type[type]) s_coords.push_back(p);\n        for (auto pos : target_pos_by_type[type]) d_coords.push_back({pos / N, pos % N});\n        sort(s_coords.begin(), s_coords.end());\n        sort(d_coords.begin(), d_coords.end());\n        for (size_t i = 0; i < s_coords.size(); ++i) dist_score += abs(s_coords[i].first - d_coords[i].first) + abs(s_coords[i].second - d_coords[i].second);\n    }\n}\n\n\n// --- IDA* Solver ---\nint calculate_h(const array<uint8_t, MAX_N2>& board_ids) {\n    int h = 0;\n    for (int i = 0; i < N * N; ++i) {\n        if (board_ids[i] != 255) { // 255 represents empty\n            int tile_id = board_ids[i];\n            int dest_pos = dest_of_tile_id[tile_id];\n            h += abs(i / N - dest_pos / N) + abs(i % N - dest_pos % N);\n        }\n    }\n    return h;\n}\n\nint ida_dfs(array<uint8_t, MAX_N2>& board_ids, int empty_pos, int g, int f_limit, int last_move_idx, string& path) {\n    int h = calculate_h(board_ids);\n    int f = g + h;\n    if (f > f_limit) return f;\n    if (h == 0) {\n        ida_solution = path;\n        return IDA_FOUND;\n    }\n    if (is_time_over()) return IDA_TIMEOUT;\n\n    int r = empty_pos / N, c = empty_pos % N;\n    int next_min_f = 1e9;\n\n    for (int i = 0; i < 4; ++i) {\n        if (g > 0 && i == opposite_move_idx[last_move_idx]) continue;\n        int nr = r + dr[i], nc = c + dc[i];\n        if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n        \n        int next_empty_pos = nr * N + nc;\n        swap(board_ids[empty_pos], board_ids[next_empty_pos]);\n        path.push_back(move_chars[i]);\n\n        int res = ida_dfs(board_ids, next_empty_pos, g + 1, f_limit, i, path);\n        \n        swap(board_ids[empty_pos], board_ids[next_empty_pos]);\n        path.pop_back();\n\n        if (res == IDA_FOUND || res == IDA_TIMEOUT) return res;\n        next_min_f = min(next_min_f, res);\n    }\n    return next_min_f;\n}\n\nstring solve_puzzle_ida() {\n    array<uint8_t, MAX_N2> initial_board_ids; // maps pos -> tile_id\n    array<int, MAX_N2> initial_pos_of_id;   // maps tile_id -> initial_pos\n    int current_id = 0;\n    for(int i = 0; i < N * N; ++i) {\n        if (initial_board.grid[i] != 0) {\n            initial_board_ids[i] = current_id;\n            initial_pos_of_id[current_id] = i;\n            current_id++;\n        } else {\n            initial_board_ids[i] = 255; // empty\n        }\n    }\n\n    for (int type = 1; type <= 15; ++type) {\n        int count = initial_tile_counts[type];\n        if (count == 0) continue;\n        \n        vector<int> type_initial_ids;\n        for(int id = 0; id < N*N-1; ++id) {\n            if (initial_board.grid[initial_pos_of_id[id]] == type) {\n                type_initial_ids.push_back(id);\n            }\n        }\n\n        vector<int> target_pos_for_type;\n        for (int i = 0; i < N * N; ++i) if (best_target_grid[i] == type) target_pos_for_type.push_back(i);\n\n        atcoder::mcf_graph<int, int> graph(2 * count + 2);\n        int s = 2 * count, t = 2 * count + 1;\n\n        for (int i = 0; i < count; ++i) {\n            graph.add_edge(s, i, 1, 0);\n            graph.add_edge(i + count, t, 1, 0);\n            for (int j = 0; j < count; ++j) {\n                int start_pos = initial_pos_of_id[type_initial_ids[i]];\n                int target_pos = target_pos_for_type[j];\n                int dist = abs(start_pos / N - target_pos / N) + abs(start_pos % N - target_pos % N);\n                graph.add_edge(i, j + count, 1, dist);\n            }\n        }\n        graph.flow(s, t, count);\n        for (auto edge : graph.edges()) {\n            if (edge.from < count && edge.to >= count && edge.to < 2 * count && edge.flow > 0) {\n                dest_of_tile_id[type_initial_ids[edge.from]] = target_pos_for_type[edge.to - count];\n            }\n        }\n    }\n    \n    int f_limit = calculate_h(initial_board_ids);\n    string path = \"\";\n    while (f_limit <= T) {\n        if (is_time_over()) break;\n        int res = ida_dfs(initial_board_ids, initial_board.empty_pos, 0, f_limit, -1, path);\n        if (res == IDA_FOUND) return ida_solution;\n        if (res == IDA_TIMEOUT) break;\n        if (res > T) break;\n        f_limit = res;\n    }\n    \n    return \"\";\n}\n\n\nint main() {\n    ios_base::sync_with_stdio(false); cin.tie(NULL);\n    cin >> N >> T;\n    for (int i = 0; i < N; ++i) {\n        string row; cin >> row;\n        for (int j = 0; j < N; ++j) {\n            int type = char_to_hex(row[j]);\n            initial_board.grid[i * N + j] = type;\n            if (type != 0) { initial_tile_counts[type]++; initial_pos_by_type[type].push_back({i, j}); }\n        }\n    }\n    initial_board.find_empty();\n\n    double sa_time_allowed = time_limit * 0.90;\n    auto sa_start_time = high_resolution_clock::now();\n\n    array<int, MAX_N2> current_grid;\n    vector<int> tiles;\n    for (int type = 1; type <= 15; ++type) for (int i = 0; i < initial_tile_counts[type]; ++i) tiles.push_back(type);\n    shuffle(tiles.begin(), tiles.end(), rng);\n    int tile_idx = 0;\n    for(int i=0; i<N*N; ++i) current_grid[i] = (i == N*N-1) ? 0 : tiles[tile_idx++];\n\n    long long current_conn_score=0, current_dist_score=0;\n    evaluate_target(current_grid, current_conn_score, current_dist_score);\n    long long best_conn_score = -1e18;\n    double start_temp = 5000, end_temp = 0.1;\n    \n    while(true) {\n        auto now = high_resolution_clock::now();\n        duration<double> elapsed = now - sa_start_time;\n        if(elapsed.count() > sa_time_allowed) break;\n        double time_progress = elapsed.count() / sa_time_allowed;\n        double temp = start_temp * pow(end_temp / start_temp, time_progress);\n        \n        for (int k=0; k<200; ++k) {\n            int p1 = rng() % (N * N), p2 = rng() % (N * N);\n            if (p1 == p2 || current_grid[p1] == 0 || current_grid[p2] == 0) continue;\n            swap(current_grid[p1], current_grid[p2]);\n            long long new_conn_score=0, new_dist_score=0;\n            evaluate_target(current_grid, new_conn_score, new_dist_score);\n            long long current_score = current_conn_score - current_dist_score * (N > 8 ? 3 : 2);\n            long long new_score = new_conn_score - new_dist_score * (N > 8 ? 3 : 2);\n\n            if (new_score > current_score || (temp > 1e-9 && uniform_real_distribution<>(0.0, 1.0)(rng) < exp((new_score - current_score) / temp))) {\n                current_conn_score = new_conn_score; current_dist_score = new_dist_score;\n                if (current_conn_score > best_conn_score || (current_conn_score == best_conn_score && current_dist_score < best_dist_score)) {\n                    best_conn_score = current_conn_score; best_dist_score = current_dist_score; best_target_grid = current_grid;\n                }\n            } else { swap(current_grid[p1], current_grid[p2]); }\n        }\n    }\n    \n    if (best_conn_score < 100000000) { cout << \"\" << endl; return 0; }\n    cout << solve_puzzle_ida() << endl;\n\n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <map>\n#include <unordered_map>\n\n// --- Utilities ---\nstruct XorShift {\n    unsigned int x, y, z, w;\n\n    XorShift() {\n        std::random_device rd;\n        x = rd();\n        y = rd();\n        z = rd();\n        w = rd();\n    }\n\n    unsigned int next() {\n        unsigned int t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));\n    }\n\n    double next_double() {\n        return next() / 4294967295.0;\n    }\n\n    int next_int(int max_val) { // [0, max_val-1]\n        return next() % max_val;\n    }\n};\n\nXorShift rnd;\nauto start_time = std::chrono::high_resolution_clock::now();\ndouble TIME_LIMIT = 2.95;\n\ndouble get_time() {\n    auto now = std::chrono::high_resolution_clock::now();\n    return std::chrono::duration_cast<std::chrono::duration<double>>(now - start_time).count();\n}\n\n// --- Data Structures ---\nconst long long INF_COORD = 1000000000;\nconst double PI = acos(-1.0L);\n\nstruct Point {\n    long long x, y;\n};\n\nstruct Line {\n    long double a, b, c; // ax+by+c=0\n};\n\nstruct LinePolar {\n    double theta, rho; // rho = x*cos(theta) + y*sin(theta)\n};\n\n// --- Problem Data ---\nint N, K;\nstd::vector<int> target_a;\nstd::vector<Point> strawberries;\nstd::vector<std::vector<int>> clusters;\n\n// --- Hashing for Score Calculation Speedup ---\nconst long long HASH_P1 = 31, HASH_M1 = 1e9 + 7;\nconst long long HASH_P2 = 37, HASH_M2 = 1e9 + 9;\nstd::vector<long long> p1_pows(101), p2_pows(101);\n\nvoid precompute_hash_powers() {\n    p1_pows[0] = 1; p2_pows[0] = 1;\n    for(int i = 1; i <= K; ++i) {\n        p1_pows[i] = (p1_pows[i-1] * HASH_P1) % HASH_M1;\n        p2_pows[i] = (p2_pows[i-1] * HASH_P2) % HASH_M2;\n    }\n}\n\nstruct SignatureHash {\n    long long h1, h2;\n    bool operator==(const SignatureHash& other) const {\n        return h1 == other.h1 && h2 == other.h2;\n    }\n};\nstruct SignatureHasher {\n    std::size_t operator()(const SignatureHash& s) const {\n        return s.h1 ^ (s.h2 << 1);\n    }\n};\n\n// --- Geometry ---\nLine points_to_line(Point p1, Point p2) {\n    long double a = (long double)p1.y - p2.y;\n    long double b = (long double)p2.x - p1.x;\n    long double c = -a * p1.x - b * p1.y;\n    return {a, b, c};\n}\n\nLine perturb_line(Line l, double amount) {\n    l.c += amount;\n    return l;\n}\n\nint get_side(const Line& l, const Point& p) {\n    long double val = l.a * p.x + l.b * p.y + l.c;\n    if (std::abs(val) < 1e-9) return 0;\n    return val > 0 ? 1 : -1;\n}\n\nLine to_cartesian(LinePolar lp) {\n    return {std::cos((long double)lp.theta), std::sin((long double)lp.theta), (long double)-lp.rho};\n}\n\nLinePolar to_polar(Line l) {\n    if (std::abs(l.a) < 1e-12 && std::abs(l.b) < 1e-12) return {0,0};\n    long double norm = std::sqrt(l.a * l.a + l.b * l.b);\n    long double a_ = l.a / norm;\n    long double b_ = l.b / norm;\n    long double c_ = l.c / norm;\n    \n    double rho = -c_;\n    double theta = std::atan2((double)b_, (double)a_);\n\n    if (theta < 0) theta += 2 * PI;\n    theta = fmod(theta, 2*PI);\n    if (theta >= PI) {\n        theta -= PI;\n        rho = -rho;\n    }\n    return {(double)theta, (double)rho};\n}\n\n// --- Candidate Generation ---\nPoint get_centroid(const std::vector<int>& strawberry_indices) {\n    if (strawberry_indices.empty()) return {0, 0};\n    long long sum_x = 0, sum_y = 0;\n    for (int idx : strawberry_indices) {\n        sum_x += strawberries[idx].x;\n        sum_y += strawberries[idx].y;\n    }\n    return {sum_x / (long long)strawberry_indices.size(), sum_y / (long long)strawberry_indices.size()};\n}\n\nLine gen_candidate_p2p() {\n    int c1_idx = rnd.next_int(clusters.size());\n    int c2_idx = rnd.next_int(clusters.size());\n    if (clusters.size() > 1 && c1_idx == c2_idx) {\n        c2_idx = (c1_idx + 1) % clusters.size();\n    }\n    \n    if (clusters.empty() || clusters[c1_idx].empty() || clusters[c2_idx].empty()) {\n        Point p1 = {(long long)rnd.next_int(20001) - 10000, (long long)rnd.next_int(20001) - 10000};\n        Point p2 = {(long long)rnd.next_int(20001) - 10000, (long long)rnd.next_int(20001) - 10000};\n        if (p1.x == p2.x && p1.y == p2.y) p2.x++;\n        return points_to_line(p1, p2);\n    }\n    \n    int s1_idx = clusters[c1_idx][rnd.next_int(clusters[c1_idx].size())];\n    int s2_idx = clusters[c2_idx][rnd.next_int(clusters[c2_idx].size())];\n    Line l = points_to_line(strawberries[s1_idx], strawberries[s2_idx]);\n    return perturb_line(l, (rnd.next_double() * 2 - 1) * 0.1);\n}\n\nLine gen_candidate_centroid() {\n    if (clusters.size() < 2) return gen_candidate_p2p();\n    int c1_idx = rnd.next_int(clusters.size());\n    int c2_idx = rnd.next_int(clusters.size());\n    if (c1_idx == c2_idx) c2_idx = (c1_idx + 1) % clusters.size();\n\n    Point centroid1 = get_centroid(clusters[c1_idx]);\n    Point centroid2 = get_centroid(clusters[c2_idx]);\n    \n    if (centroid1.x == centroid2.x && centroid1.y == centroid2.y) return gen_candidate_p2p();\n\n    Point mid_point = {(centroid1.x + centroid2.x) / 2, (centroid1.y + centroid2.y) / 2};\n    Point p_on_perp = {mid_point.x - (centroid2.y - centroid1.y), mid_point.y + (centroid2.x - centroid1.x)};\n\n    Line l = points_to_line(mid_point, p_on_perp);\n    double angle = (rnd.next_double() * 2 - 1) * PI / 12.0;\n    long double cosa = cos(angle), sina = sin(angle);\n    long double new_a = l.a * cosa - l.b * sina;\n    long double new_b = l.a * sina + l.b * cosa;\n    long double new_c = -new_a * mid_point.x - new_b * mid_point.y;\n    return {new_a, new_b, new_c};\n}\n\nLine generate_candidate_line() {\n    if (clusters.size() < 2 || rnd.next_double() < 0.01) { // 1% chance of a random line\n        Point p1 = {(long long)rnd.next_int(20001) - 10000, (long long)rnd.next_int(20001) - 10000};\n        Point p2 = {(long long)rnd.next_int(20001) - 10000, (long long)rnd.next_int(20001) - 10000};\n        if (p1.x == p2.x && p1.y == p2.y) p2.x++;\n        return points_to_line(p1, p2);\n    }\n    if (rnd.next_double() < 0.5) return gen_candidate_p2p();\n    else return gen_candidate_centroid();\n}\n\n// --- Clustering ---\nvoid perform_clustering() {\n    std::vector<int> target_sizes;\n    for (int d = 1; d <= 10; ++d) {\n        for (int i = 0; i < target_a[d]; ++i) target_sizes.push_back(d);\n    }\n    std::shuffle(target_sizes.begin(), target_sizes.end(), std::mt19937(rnd.next()));\n\n    std::vector<bool> assigned(N, false);\n    int assigned_count = 0;\n\n    for (int d : target_sizes) {\n        if (assigned_count + d > N) continue;\n\n        int seed_idx = -1;\n        int start_node = rnd.next_int(N);\n        for (int i = 0; i < N; ++i) {\n            int current_node = (start_node + i) % N;\n            if (!assigned[current_node]) { seed_idx = current_node; break; }\n        }\n        if (seed_idx == -1) break;\n\n        std::vector<std::pair<long long, int>> dists;\n        for (int i = 0; i < N; ++i) {\n            if (!assigned[i]) {\n                long long dx = strawberries[seed_idx].x - strawberries[i].x;\n                long long dy = strawberries[seed_idx].y - strawberries[i].y;\n                dists.push_back({dx * dx + dy * dy, i});\n            }\n        }\n        \n        if (dists.size() > (size_t)d) std::nth_element(dists.begin(), dists.begin() + d, dists.end());\n\n        std::vector<int> new_cluster;\n        for (int i = 0; i < std::min((int)dists.size(), d); ++i) {\n            new_cluster.push_back(dists[i].second);\n            assigned[dists[i].second] = true;\n        }\n        clusters.push_back(new_cluster);\n        assigned_count += d;\n    }\n}\n\n// --- Score Calculation ---\nint calculate_score_val(const std::vector<Line>& lines) {\n    if (lines.empty()) return 0;\n    \n    std::unordered_map<SignatureHash, int, SignatureHasher> piece_counts;\n    for (int i = 0; i < N; ++i) {\n        long long h1 = 0, h2 = 0;\n        bool on_line = false;\n        for (size_t k = 0; k < lines.size(); ++k) {\n            int side = get_side(lines[k], strawberries[i]);\n            if (side == 0) { on_line = true; break; }\n            int val = (side + 1); // map {-1, 1} to {0, 2}\n            h1 = (h1 + val * p1_pows[k]) % HASH_M1;\n            h2 = (h2 + val * p2_pows[k]) % HASH_M2;\n        }\n        if (!on_line) piece_counts[{h1, h2}]++;\n    }\n\n    std::vector<int> b(11, 0);\n    for (const auto& pair : piece_counts) {\n        if (pair.second >= 1 && pair.second <= 10) b[pair.second]++;\n    }\n\n    int score = 0;\n    for (int d = 1; d <= 10; ++d) score += std::min(target_a[d], b[d]);\n    return score;\n}\n\n// --- Fast Greedy Construction ---\nstruct GreedyState {\n    using Partition = std::unordered_map<SignatureHash, std::vector<int>, SignatureHasher>;\n\n    Partition partition;\n    std::vector<int> b_dist;\n    int k;\n\n    GreedyState() : b_dist(11, 0), k(0) {\n        std::vector<int> initial_indices(N);\n        std::iota(initial_indices.begin(), initial_indices.end(), 0);\n        partition[{0, 0}] = initial_indices;\n        if (N >= 1 && N <= 10) b_dist[N] = 1;\n    }\n\n    int get_score_from_b(const std::vector<int>& b) const {\n        int score = 0;\n        for (int d = 1; d <= 10; ++d) score += std::min(target_a[d], b[d]);\n        return score;\n    }\n\n    int calculate_score_with_new_line(const Line& new_line) const {\n        std::vector<int> next_b_dist = b_dist;\n        for (auto const& [sig, strawberry_indices] : partition) {\n            int old_count = strawberry_indices.size();\n            if (old_count >= 1 && old_count <= 10) next_b_dist[old_count]--;\n            \n            int count1 = 0, count2 = 0;\n            for (int idx : strawberry_indices) {\n                int side = get_side(new_line, strawberries[idx]);\n                if (side == 1) count1++;\n                else if (side == -1) count2++;\n            }\n            if (count1 >= 1 && count1 <= 10) next_b_dist[count1]++;\n            if (count2 >= 1 && count2 <= 10) next_b_dist[count2]++;\n        }\n        return get_score_from_b(next_b_dist);\n    }\n    \n    void add_line(const Line& new_line) {\n        auto old_partition = partition;\n        partition.clear();\n        b_dist.assign(11, 0);\n\n        for (auto const& [old_sig, strawberry_indices] : old_partition) {\n            std::vector<int> group1, group2;\n            for (int idx : strawberry_indices) {\n                int side = get_side(new_line, strawberries[idx]);\n                if (side == 1) group1.push_back(idx);\n                else if (side == -1) group2.push_back(idx);\n            }\n            if (!group1.empty()) {\n                int val = 2; // side=1 -> val=2\n                long long h1 = (old_sig.h1 + val * p1_pows[k]) % HASH_M1;\n                long long h2 = (old_sig.h2 + val * p2_pows[k]) % HASH_M2;\n                partition[{h1,h2}] = group1;\n                if (group1.size() <= 10) b_dist[group1.size()]++;\n            }\n            if (!group2.empty()) {\n                int val = 0; // side=-1 -> val=0\n                long long h1 = (old_sig.h1 + val * p1_pows[k]) % HASH_M1;\n                long long h2 = (old_sig.h2 + val * p2_pows[k]) % HASH_M2;\n                partition[{h1,h2}] = group2;\n                if (group2.size() <= 10) b_dist[group2.size()]++;\n            }\n        }\n        k++;\n    }\n};\n\n// --- Main ---\nvoid output_solution(const std::vector<Line>& lines) {\n    std::cout << lines.size() << std::endl;\n    for (const auto& l : lines) {\n        long long p1x, p1y, p2x, p2y;\n        if (std::abs(l.b) > 1e-9 && (std::abs(l.a / l.b) < 1)) {\n            p1x = -INF_COORD; p1y = std::round(- (l.c + l.a * p1x) / l.b);\n            p2x = INF_COORD; p2y = std::round(- (l.c + l.a * p2x) / l.b);\n        } else if (std::abs(l.a) > 1e-9) {\n            p1y = -INF_COORD; p1x = std::round(- (l.c + l.b * p1y) / l.a);\n            p2y = INF_COORD; p2x = std::round(- (l.c + l.b * p2y) / l.a);\n        } else { \n            p1x = 0; p1y = 0; p2x = 1; p2y = 1;\n        }\n        std::cout << p1x << \" \" << p1y << \" \" << p2x << \" \" << p2y << std::endl;\n    }\n}\n\nvoid solve() {\n    std::cin >> N >> K;\n    target_a.resize(11);\n    for (int d = 1; d <= 10; ++d) std::cin >> target_a[d];\n    strawberries.resize(N);\n    for (int i = 0; i < N; ++i) std::cin >> strawberries[i].x >> strawberries[i].y;\n    precompute_hash_powers();\n    \n    perform_clustering();\n    \n    // Partial Greedy Construction\n    std::vector<Line> current_lines;\n    GreedyState state;\n    const int K_greedy = 35;\n    const int T_SEARCH = 40;\n\n    for (int k_iter = 0; k_iter < K_greedy; ++k_iter) {\n        Line best_line = {};\n        int best_score = -1;\n        for (int i = 0; i < T_SEARCH; ++i) {\n            Line candidate_line = generate_candidate_line();\n            int score = state.calculate_score_with_new_line(candidate_line);\n            if (score > best_score) {\n                best_score = score;\n                best_line = candidate_line;\n            }\n        }\n        if (best_score != -1) {\n            current_lines.push_back(best_line);\n            state.add_line(best_line);\n        } else break;\n    }\n    \n    // Seed remaining lines\n    while (current_lines.size() < (size_t)K) {\n        current_lines.push_back(generate_candidate_line());\n    }\n    \n    // Simulated Annealing\n    std::vector<LinePolar> polar_lines;\n    polar_lines.reserve(current_lines.size());\n    for(const auto& l : current_lines) polar_lines.push_back(to_polar(l));\n    \n    int current_score = calculate_score_val(current_lines);\n    std::vector<Line> best_lines = current_lines;\n    int best_score = current_score;\n\n    double T_start = 10.0, T_end = 0.01;\n    double time_start_sa = get_time(), time_end_sa = TIME_LIMIT;\n    const double P_REPLACE = 0.1;\n\n    while(true) {\n        double current_time = get_time();\n        if (current_time >= time_end_sa) break;\n\n        double progress = (current_time - time_start_sa) / (time_end_sa - time_start_sa + 1e-9);\n        double T = T_start * std::pow(T_end / T_start, progress);\n\n        if (polar_lines.empty()) break;\n        int line_idx = rnd.next_int(polar_lines.size());\n        \n        std::vector<Line> new_lines = current_lines;\n        \n        if (rnd.next_double() < P_REPLACE) {\n            new_lines[line_idx] = generate_candidate_line();\n        } else {\n            LinePolar new_polar = polar_lines[line_idx];\n            double move_range = (1.0 - progress) * 0.5;\n            new_polar.theta += (rnd.next_double() * 2 - 1) * PI * move_range;\n            new_polar.rho += (rnd.next_double() * 2 - 1) * 10000 * move_range;\n\n            if (new_polar.theta < 0) new_polar.theta += 2*PI;\n            new_polar.theta = fmod(new_polar.theta, 2*PI);\n            if (new_polar.theta >= PI) {\n                new_polar.theta -= PI; new_polar.rho *= -1;\n            }\n            new_lines[line_idx] = to_cartesian(new_polar);\n        }\n        \n        int new_score = calculate_score_val(new_lines);\n        double delta = new_score - current_score;\n\n        if (delta > 0 || std::exp(delta / T) > rnd.next_double()) {\n            current_score = new_score;\n            current_lines = new_lines;\n            polar_lines[line_idx] = to_polar(current_lines[line_idx]);\n            if (new_score > best_score) {\n                best_score = new_score;\n                best_lines = new_lines;\n            }\n        }\n    }\n    output_solution(best_lines);\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <tuple>\n#include <chrono>\n#include <map>\n#include <queue>\n#include <set>\n\nusing namespace std;\n\n// Timer\nauto start_time = chrono::steady_clock::now();\ndouble time_limit = 4.9;\n\nbool is_time_over() {\n    auto now = chrono::steady_clock::now();\n    double elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count() / 1000.0;\n    return elapsed > time_limit;\n}\n\nint N;\nlong long M_initial;\nlong long C;\n\nstruct Point {\n    int x, y;\n\n    bool operator==(const Point& other) const { return x == other.x && y == other.y; }\n    bool operator!=(const Point& other) const { return !(*this == other); }\n    bool operator<(const Point& other) const { if (x != other.x) return x < other.x; return y < other.y; }\n    Point operator+(const Point& other) const { return {x + other.x, y + other.y}; }\n    Point operator-(const Point& other) const { return {x - other.x, y - other.y}; }\n};\n\nlong long get_weight(const Point& p) {\n    long long dx = p.x - C;\n    long long dy = p.y - C;\n    return dx * dx + dy * dy + 1;\n}\n\nlong long dot_product(const Point& a, const Point& b) {\n    return (long long)a.x * b.x + (long long)a.y * b.y;\n}\n\nstruct Candidate {\n    long long weight;\n    Point p_new, p_adj1, p_corner, p_adj2;\n    bool operator<(const Candidate& other) const { return weight < other.weight; }\n};\n\nbool has_dot[62][62];\nvector<Point> dots;\nvector<tuple<Point, Point, Point, Point>> solution_moves;\npriority_queue<Candidate> pq;\nmap<int, set<pair<int, int>>> H_segs, V_segs, D1_segs, D2_segs;\n\nbool is_in_bounds(const Point& p) { return p.x >= 0 && p.x < N && p.y >= 0 && p.y < N; }\n\nbool check_perimeter_clean(const Point& p_new, const Point& p_adj1, const Point& p_corner, const Point& p_adj2) {\n    auto check_segment = [&](const Point& a, const Point& b) {\n        int dx = b.x - a.x, dy = b.y - a.y;\n        int common_divisor = std::gcd(abs(dx), abs(dy));\n        if (common_divisor <= 1) return true;\n        int step_x = dx / common_divisor, step_y = dy / common_divisor;\n        for (int i = 1; i < common_divisor; ++i) {\n            if (has_dot[a.x + i * step_x][a.y + i * step_y]) return false;\n        }\n        return true;\n    };\n    return check_segment(p_corner, p_adj1) && check_segment(p_adj1, p_new) && check_segment(p_new, p_adj2) && check_segment(p_adj2, p_corner);\n}\n\nbool check_segment_overlap(map<int, set<pair<int, int>>>& seg_map, int line_idx, int c1, int c2) {\n    if (c1 == c2) return false;\n    int min_c = min(c1, c2), max_c = max(c1, c2);\n    if (seg_map.find(line_idx) == seg_map.end()) return false;\n    const auto& intervals = seg_map.at(line_idx);\n    auto it = intervals.lower_bound({min_c, 0});\n    if (it != intervals.begin()) {\n        auto prev_it = prev(it);\n        if (max(min_c, prev_it->first) < min(max_c, prev_it->second)) return true;\n    }\n    if (it != intervals.end()) {\n        if (max(min_c, it->first) < min(max_c, it->second)) return true;\n    }\n    return false;\n}\n\nvoid add_segment(map<int, set<pair<int, int>>>& seg_map, int line_idx, int c1, int c2) {\n    if (c1 == c2) return;\n    seg_map[line_idx].insert({min(c1, c2), max(c1, c2)});\n}\n\nbool is_valid_side_vector(const Point& v) {\n    if (v.x == 0 && v.y == 0) return false;\n    return (v.x == 0 || v.y == 0) || (abs(v.x) == abs(v.y));\n}\n\nvoid find_and_push_candidates(const Point& p_adj1, const Point& p_corner, const Point& p_adj2) {\n    Point p_new = p_adj1 + p_adj2 - p_corner;\n    if (is_in_bounds(p_new) && !has_dot[p_new.x][p_new.y] && check_perimeter_clean(p_new, p_adj1, p_corner, p_adj2)) {\n        pq.push({get_weight(p_new), p_new, p_adj1, p_corner, p_adj2});\n    }\n}\n\nvoid find_new_candidates_slow(const Point& p_added) {\n    size_t old_dots_count = dots.size() - 1;\n    // Case 1: p_added is the corner\n    for (size_t i = 0; i < old_dots_count; ++i) {\n        for (size_t j = i + 1; j < old_dots_count; ++j) {\n            const Point& p_i = dots[i];\n            const Point& p_j = dots[j];\n            if (dot_product(p_i - p_added, p_j - p_added) == 0) {\n                if (is_valid_side_vector(p_i - p_added)) {\n                    find_and_push_candidates(p_i, p_added, p_j);\n                }\n            }\n        }\n    }\n    // Case 2: an existing dot p_i is the corner, p_added is adjacent\n    for (size_t i = 0; i < old_dots_count; ++i) { // p_i is corner\n        const Point& p_i = dots[i];\n        for (size_t j = 0; j < old_dots_count; ++j) { // p_j is the other adjacent\n            if (i == j) continue;\n            const Point& p_j = dots[j];\n            if (dot_product(p_added - p_i, p_j - p_i) == 0) {\n                 if (is_valid_side_vector(p_added - p_i)) {\n                    find_and_push_candidates(p_added, p_i, p_j);\n                 }\n            }\n        }\n    }\n}\n\nvoid find_initial_candidates_slow() {\n    if (dots.size() > 400) return; // Safety break for large M\n    for (size_t i = 0; i < dots.size(); ++i) {\n        for (size_t j = i + 1; j < dots.size(); ++j) {\n            for (size_t k = j + 1; k < dots.size(); ++k) {\n                Point p_i = dots[i], p_j = dots[j], p_k = dots[k];\n                if (dot_product(p_j - p_i, p_k - p_i) == 0) {\n                    if (is_valid_side_vector(p_j - p_i)) find_and_push_candidates(p_j, p_i, p_k);\n                }\n                if (dot_product(p_i - p_j, p_k - p_j) == 0) {\n                    if (is_valid_side_vector(p_i - p_j)) find_and_push_candidates(p_i, p_j, p_k);\n                }\n                if (dot_product(p_i - p_k, p_j - p_k) == 0) {\n                    if (is_valid_side_vector(p_i - p_k)) find_and_push_candidates(p_i, p_k, p_j);\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false); cin.tie(NULL);\n    cin >> N >> M_initial;\n    C = (N - 1) / 2;\n    for (int i = 0; i < M_initial; ++i) {\n        int x, y; cin >> x >> y;\n        dots.push_back({x, y});\n        has_dot[x][y] = true;\n    }\n    \n    find_initial_candidates_slow();\n\n    while (!pq.empty() && !is_time_over()) {\n        Candidate c = pq.top(); pq.pop();\n\n        if (has_dot[c.p_new.x][c.p_new.y]) continue;\n        \n        Point p_new = c.p_new, p_corner = c.p_corner, p_adj1 = c.p_adj1, p_adj2 = c.p_adj2;\n        if (!check_perimeter_clean(p_new, p_adj1, p_corner, p_adj2)) continue;\n\n        auto check_s = [&](const Point& u, const Point& v) {\n            if (u.y == v.y) return !check_segment_overlap(H_segs, u.y, u.x, v.x);\n            if (u.x == v.x) return !check_segment_overlap(V_segs, u.x, u.y, v.y);\n            if (u.x + u.y == v.x + v.y) return !check_segment_overlap(D1_segs, u.x + u.y, u.x, v.x);\n            return !check_segment_overlap(D2_segs, u.x - u.y, u.x, v.x);\n        };\n        if (!check_s(p_corner, p_adj1) || !check_s(p_adj1, p_new) || !check_s(p_new, p_adj2) || !check_s(p_adj2, p_corner)) continue;\n\n        auto add_s = [&](const Point& u, const Point& v){\n            if (u.y == v.y) add_segment(H_segs, u.y, u.x, v.x);\n            else if (u.x == v.x) add_segment(V_segs, u.x, u.y, v.y);\n            else if (u.x + u.y == v.x + v.y) add_segment(D1_segs, u.x + u.y, u.x, v.x);\n            else add_segment(D2_segs, u.x - u.y, u.x, v.x);\n        };\n        add_s(p_corner, p_adj1); add_s(p_adj1, p_new); add_s(p_new, p_adj2); add_s(p_adj2, p_corner);\n\n        solution_moves.emplace_back(p_new, p_adj1, p_corner, p_adj2);\n        dots.push_back(p_new);\n        has_dot[p_new.x][p_new.y] = true;\n        \n        find_new_candidates_slow(p_new);\n    }\n\n    cout << solution_moves.size() << endl;\n    for (const auto& move : solution_moves) {\n        cout << get<0>(move).x << \" \" << get<0>(move).y << \" \" << get<1>(move).x << \" \" << get<1>(move).y << \" \" << get<2>(move).x << \" \" << get<2>(move).y << \" \" << get<3>(move).x << \" \" << get<3>(move).y << endl;\n    }\n\n    return 0;\n}","ahc015":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <algorithm>\n#include <map>\n#include <cmath>\n\nconst int GRID_SIZE = 10;\n\n// Represents the state of the 10x10 grid.\nstruct Grid {\n    std::vector<std::vector<int>> board;\n\n    Grid() : board(GRID_SIZE, std::vector<int>(GRID_SIZE, 0)) {}\n\n    // Places a candy of a given flavor at the p-th empty cell (1-indexed).\n    void place(int p, int flavor) {\n        int empty_count = 0;\n        for (int i = 0; i < GRID_SIZE; ++i) {\n            for (int j = 0; j < GRID_SIZE; ++j) {\n                if (board[i][j] == 0) {\n                    empty_count++;\n                    if (empty_count == p) {\n                        board[i][j] = flavor;\n                        return;\n                    }\n                }\n            }\n        }\n    }\n};\n\n// Simulates a tilt operation on the grid and returns the new grid state.\nGrid simulate_tilt(const Grid& current_grid, char dir) {\n    Grid next_grid; // Initializes to an empty board.\n    \n    if (dir == 'F') { // Move Up\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            int current_row = 0;\n            for (int i = 0; i < GRID_SIZE; ++i) {\n                if (current_grid.board[i][j] != 0) {\n                    next_grid.board[current_row++][j] = current_grid.board[i][j];\n                }\n            }\n        }\n    } else if (dir == 'B') { // Move Down\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            int current_row = GRID_SIZE - 1;\n            for (int i = GRID_SIZE - 1; i >= 0; --i) {\n                if (current_grid.board[i][j] != 0) {\n                    next_grid.board[current_row--][j] = current_grid.board[i][j];\n                }\n            }\n        }\n    } else if (dir == 'L') { // Move Left\n        for (int i = 0; i < GRID_SIZE; ++i) {\n            int current_col = 0;\n            for (int j = 0; j < GRID_SIZE; ++j) {\n                if (current_grid.board[i][j] != 0) {\n                    next_grid.board[i][current_col++] = current_grid.board[i][j];\n                }\n            }\n        }\n    } else if (dir == 'R') { // Move Right\n        for (int i = 0; i < GRID_SIZE; ++i) {\n            int current_col = GRID_SIZE - 1;\n            for (int j = GRID_SIZE - 1; j >= 0; --j) {\n                if (current_grid.board[i][j] != 0) {\n                    next_grid.board[i][current_col--] = current_grid.board[i][j];\n                }\n            }\n        }\n    }\n    return next_grid;\n}\n\n// Calculates the sum of squares of connected component sizes using BFS.\nlong long calculate_conn_score(const Grid& grid) {\n    long long total_score = 0;\n    std::vector<std::vector<bool>> visited(GRID_SIZE, std::vector<bool>(GRID_SIZE, false));\n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            if (grid.board[i][j] != 0 && !visited[i][j]) {\n                int flavor = grid.board[i][j];\n                long long component_size = 0;\n                std::vector<std::pair<int, int>> q;\n                q.push_back({i, j});\n                visited[i][j] = true;\n                \n                size_t head = 0;\n                while(head < q.size()){\n                    auto [r, c] = q[head++];\n                    component_size++;\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 < GRID_SIZE && nc >= 0 && nc < GRID_SIZE &&\n                            !visited[nr][nc] && grid.board[nr][nc] == flavor) {\n                            visited[nr][nc] = true;\n                            q.push_back({nr, nc});\n                        }\n                    }\n                }\n                total_score += component_size * component_size;\n            }\n        }\n    }\n    return total_score;\n}\n\n// Global map from flavor to its target side.\nstd::map<int, int> target_side_map; // 0: Top, 1: Left, 3: Bottom\n\n// Calculates positioning score (negative sum of squared distances to target sides).\nlong long calculate_position_score(const Grid& grid) {\n    long long total_sq_dist = 0;\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            if (grid.board[i][j] != 0) {\n                int flavor = grid.board[i][j];\n                int target_side = target_side_map.at(flavor);\n                long long dist = 0;\n                if (target_side == 0) { // Top\n                    dist = i;\n                } else if (target_side == 1) { // Left\n                    dist = j;\n                } else { // Bottom (target_side == 3)\n                    dist = (GRID_SIZE - 1 - i);\n                }\n                total_sq_dist += dist * dist;\n            }\n        }\n    }\n    return -total_sq_dist;\n}\n\n// Calculates a penalty for adjacent (orthogonal and diagonal) different-flavor candies.\nlong long calculate_adj_penalty_score(const Grid& grid) {\n    long long penalty = 0;\n    for (int r = 0; r < GRID_SIZE; ++r) {\n        for (int c = 0; c < GRID_SIZE; ++c) {\n            if (grid.board[r][c] == 0) continue;\n            int current_flavor = grid.board[r][c];\n            \n            // Check neighbors to the right, down, and bottom-diagonals to avoid double counting.\n            if (c + 1 < GRID_SIZE && grid.board[r][c+1] != 0 && grid.board[r][c+1] != current_flavor) {\n                penalty--;\n            }\n            if (r + 1 < GRID_SIZE) {\n                if (grid.board[r+1][c] != 0 && grid.board[r+1][c] != current_flavor) {\n                    penalty--;\n                }\n                if (c + 1 < GRID_SIZE && grid.board[r+1][c+1] != 0 && grid.board[r+1][c+1] != current_flavor) {\n                    penalty--;\n                }\n                if (c - 1 >= 0 && grid.board[r+1][c-1] != 0 && grid.board[r+1][c-1] != current_flavor) {\n                    penalty--;\n                }\n            }\n        }\n    }\n    return penalty;\n}\n\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    std::vector<int> f(100);\n    std::map<int, int> flavor_counts;\n    for (int i = 0; i < 100; ++i) {\n        std::cin >> f[i];\n        flavor_counts[f[i]]++;\n    }\n    \n    std::vector<std::pair<int, int>> sorted_flavors;\n    for (int i = 1; i <= 3; ++i) {\n        sorted_flavors.push_back({flavor_counts.count(i) ? flavor_counts[i] : 0, i});\n    }\n    std::sort(sorted_flavors.rbegin(), sorted_flavors.rend());\n\n    // Target assignment: Top, Left, Bottom\n    // 0: Top, 1: Left, 3: Bottom\n    std::vector<int> target_sides = {0, 1, 3}; \n    for (size_t i = 0; i < 3; ++i) {\n        target_side_map[sorted_flavors[i].second] = target_sides[i];\n    }\n\n    Grid current_grid;\n\n    for (int t = 1; t <= 100; ++t) {\n        int p;\n        std::cin >> p;\n        current_grid.place(p, f[t - 1]);\n\n        if (t == 100) {\n            break;\n        }\n\n        char best_dir = 'F';\n        double best_score = -1e18;\n\n        const char dirs[] = {'F', 'B', 'L', 'R'};\n        for (char dir : dirs) {\n            Grid next_grid = simulate_tilt(current_grid, dir);\n            \n            long long conn_score = calculate_conn_score(next_grid);\n            long long position_score = calculate_position_score(next_grid);\n            long long adj_penalty_score = calculate_adj_penalty_score(next_grid);\n\n            double t_double = static_cast<double>(t);\n            double w_conn = t_double * t_double;\n            double w_pos = 0.5 * (101.0 - t_double) * (101.0 - t_double);\n            double w_adj = 8.0 * t_double * t_double;\n            \n            double current_total_score = w_conn * conn_score + w_pos * position_score + w_adj * adj_penalty_score;\n            \n            if (current_total_score > best_score) {\n                best_score = current_total_score;\n                best_dir = dir;\n            }\n        }\n        \n        std::cout << best_dir << std::endl;\n        current_grid = simulate_tilt(current_grid, best_dir);\n    }\n\n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <set>\n#include <random>\n\n// Globals\nint M;\ndouble EPS;\nint N;\nstd::vector<int> clique_sizes;\nstd::vector<std::vector<bool>> H_adj;\nstd::mt19937 rng(5489);\n\n// --- Helper Functions ---\n\nstd::string clique_graph_to_string(int n, int clique_size) {\n    std::string s(n * (n - 1) / 2, '0');\n    int k = 0;\n    for (int i = 0; i < n; ++i) {\n        for (int j = i + 1; j < n; ++j) {\n            if (i < clique_size && j < clique_size) {\n                s[k] = '1';\n            }\n            k++;\n        }\n    }\n    return s;\n}\n\ndouble binary_entropy(double p) {\n    if (p <= 0.0 || p >= 1.0) return 0.0;\n    return -p * std::log2(p) - (1.0 - p) * std::log2(1.0 - p);\n}\n\n// O(N^2) degeneracy ordering heuristic. Returns vertices from core to periphery.\nstd::vector<int> get_peeling_order(int n, const std::vector<int>& initial_degrees) {\n    std::vector<int> degrees = initial_degrees;\n    std::vector<bool> removed(n, false);\n    std::vector<int> order(n);\n    for (int i = 0; i < n; ++i) {\n        int min_deg_val = n + 1;\n        int u = -1;\n        for (int j = 0; j < n; ++j) {\n            if (!removed[j] && degrees[j] < min_deg_val) {\n                min_deg_val = degrees[j];\n                u = j;\n            }\n        }\n        order[i] = u;\n        removed[u] = true;\n        for (int v = 0; v < n; ++v) {\n            if (H_adj[u][v]) {\n                degrees[v]--;\n            }\n        }\n    }\n    std::reverse(order.begin(), order.end());\n    return order;\n}\n\n// --- Main Logic ---\n\nvoid determine_N() {\n    double alpha = 1.8 + 20.0 * EPS * EPS;\n    double capacity = std::max(0.01, 1.0 - binary_entropy(EPS));\n    double bits_needed = std::log2(M) * alpha;\n    double edges_needed = bits_needed / capacity;\n    double n_theory = (1.0 + std::sqrt(std::max(0.0, 1.0 + 8.0 * edges_needed))) / 2.0;\n    \n    N = static_cast<int>(lround(n_theory));\n    N = std::max(N, M);\n    N = std::min(100, std::max(4, N));\n}\n\nvoid generate_base_graphs() {\n    std::set<int> st_clique_sizes;\n    if (M <= 1) {\n        st_clique_sizes.insert(0);\n    } else {\n        for (int i = 0; i < M; ++i) {\n            // Spacing clique sizes so that the edge counts are more linearly spaced.\n            st_clique_sizes.insert(lround(N * sqrt((double)i / (M - 1.0))));\n        }\n    }\n    \n    if (st_clique_sizes.count(1)) st_clique_sizes.erase(1);\n    \n    for (int i = 0; st_clique_sizes.size() < (size_t)M && i <= N; ++i) {\n        if (i == 1) continue;\n        st_clique_sizes.insert(i);\n    }\n    \n    clique_sizes.assign(st_clique_sizes.begin(), st_clique_sizes.end());\n    \n    std::cout << N << std::endl;\n    for (int k = 0; k < M; ++k) {\n        std::cout << clique_graph_to_string(N, clique_sizes[k]) << std::endl;\n    }\n}\n\nvoid solve() {\n    determine_N();\n    generate_base_graphs();\n    std::cout.flush();\n\n    H_adj.resize(N, std::vector<bool>(N));\n\n    for (int q = 0; q < 100; ++q) {\n        std::string H_str;\n        std::cin >> H_str;\n\n        int H_edges = 0;\n        int k_str_idx = 0;\n        std::vector<int> initial_degrees(N, 0);\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) {\n                H_adj[i][j] = H_adj[j][i] = (H_str[k_str_idx] == '1');\n                if (H_adj[i][j]) {\n                    H_edges++;\n                    initial_degrees[i]++;\n                    initial_degrees[j]++;\n                }\n                k_str_idx++;\n            }\n        }\n        \n        std::vector<int> initial_guess_order = get_peeling_order(N, initial_degrees);\n\n        int best_idx = -1;\n        double min_flips = 1e18;\n\n        for (int i = 0; i < M; ++i) {\n            int C = clique_sizes[i];\n            \n            if (C <= 1) {\n                double flips = H_edges;\n                if (flips < min_flips) {\n                    min_flips = flips;\n                    best_idx = i;\n                }\n                continue;\n            }\n\n            std::vector<int> S_nodes(C);\n            std::vector<int> pos_in_S(N, -1);\n            for (int j = 0; j < C; ++j) {\n                int node = initial_guess_order[j];\n                S_nodes[j] = node;\n                pos_in_S[node] = j;\n            }\n\n            std::vector<int> d_S(N, 0);\n            for(int u = 0; u < N; ++u) {\n                for(int v_node : S_nodes) {\n                    if (H_adj[u][v_node]) d_S[u]++;\n                }\n            }\n            \n            long long current_edges = 0;\n            for(int u_node : S_nodes) current_edges += d_S[u_node];\n            current_edges /= 2;\n            long long best_edges = current_edges;\n            \n            const int MAX_ITERS = 150;\n            double start_temp = 2.0, end_temp = 0.01;\n            std::uniform_real_distribution<> dist(0.0, 1.0);\n            \n            for (int iter = 0; iter < MAX_ITERS; ++iter) {\n                double temp = start_temp * pow(end_temp / start_temp, (double)iter / (MAX_ITERS -1));\n\n                int u_to_swap = -1, min_d_in = N + 1;\n                for (int u_node : S_nodes) {\n                    if (d_S[u_node] < min_d_in) {\n                        min_d_in = d_S[u_node];\n                        u_to_swap = u_node;\n                    }\n                }\n                \n                int v_to_swap = -1, max_d_out = -1;\n                for (int v = 0; v < N; ++v) {\n                    if (pos_in_S[v] == -1) {\n                        if (d_S[v] > max_d_out) {\n                            max_d_out = d_S[v];\n                            v_to_swap = v;\n                        }\n                    }\n                }\n\n                if (u_to_swap == -1 || v_to_swap == -1) break;\n                \n                int gain = max_d_out - min_d_in - (H_adj[u_to_swap][v_to_swap] ? 1 : 0);\n\n                if (gain > 0 || dist(rng) < exp((double)gain / temp)) {\n                    current_edges += gain;\n                    \n                    int u_idx = pos_in_S[u_to_swap];\n                    S_nodes[u_idx] = v_to_swap;\n                    pos_in_S[u_to_swap] = -1;\n                    pos_in_S[v_to_swap] = u_idx;\n\n                    for(int w = 0; w < N; ++w) {\n                        if(H_adj[w][u_to_swap]) d_S[w]--;\n                        if(H_adj[w][v_to_swap]) d_S[w]++;\n                    }\n                    if (current_edges > best_edges) {\n                        best_edges = current_edges;\n                    }\n                }\n            }\n            \n            long long E_star = best_edges;\n            long long E_clique = (long long)C * (C - 1) / 2;\n            double estimated_flips = (double)(E_clique - E_star) + (H_edges - E_star);\n\n            if (estimated_flips < min_flips) {\n                min_flips = estimated_flips;\n                best_idx = i;\n            }\n        }\n        \n        if (best_idx == -1) best_idx = 0;\n        std::cout << best_idx << std::endl;\n        std::cout.flush();\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    std::cin >> M >> EPS;\n    solve();\n    return 0;\n}","ahc017":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <iomanip>\n#include <functional>\n#include <queue>\n#include <tuple>\n\nusing namespace std;\n\n// Constants and Typedefs\nconst long long INF = 1e18;\n\n// Structs\nstruct Edge {\n    int id;\n    int u, v, w;\n};\n\nstruct Point {\n    int x, y;\n};\n\n// Utilities\nauto start_time = chrono::high_resolution_clock::now();\ndouble get_time() {\n    auto now = chrono::high_resolution_clock::now();\n    return chrono::duration_cast<chrono::duration<double>>(now - start_time).count();\n}\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// Bridge Finder for detecting 2-edge-cuts\nnamespace BridgeFinder {\n    vector<int> tin, low;\n    int timer;\n    vector<bool> visited;\n    const vector<vector<tuple<int, int, int>>>* adj_ptr;\n    vector<pair<int, int>> critical_pairs_buffer;\n    int current_ignored_edge;\n\n    void dfs(int u, int p_edge_id) {\n        visited[u] = true;\n        tin[u] = low[u] = timer++;\n        for (const auto& edge_tuple : (*adj_ptr)[u]) {\n            int v = get<0>(edge_tuple);\n            int edge_id = get<2>(edge_tuple);\n\n            if (edge_id == p_edge_id || edge_id == current_ignored_edge) continue;\n\n            if (visited[v]) {\n                low[u] = min(low[u], tin[v]);\n            } else {\n                dfs(v, edge_id);\n                low[u] = min(low[u], low[v]);\n                if (low[v] > tin[u]) {\n                    critical_pairs_buffer.emplace_back(current_ignored_edge, edge_id);\n                }\n            }\n        }\n    }\n\n    void find_bridges_in_subgraph(int ignored_edge, int N) {\n        current_ignored_edge = ignored_edge;\n        timer = 0;\n        visited.assign(N, false);\n        tin.assign(N, -1);\n        low.assign(N, -1);\n        for (int i = 0; i < N; ++i) {\n            if (!visited[i]) {\n                dfs(i, -1);\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // --- Input Reading ---\n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n\n    vector<Edge> edges(M);\n    vector<vector<tuple<int, int, int>>> adj(N);\n    for (int i = 0; i < M; ++i) {\n        edges[i].id = i;\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\n        edges[i].u--; \n        edges[i].v--;\n        adj[edges[i].u].emplace_back(edges[i].v, edges[i].w, i);\n        adj[edges[i].v].emplace_back(edges[i].u, edges[i].w, i);\n    }\n\n    vector<Point> coords(N);\n    for (int i = 0; i < N; ++i) cin >> coords[i].x >> coords[i].y;\n    \n    // --- Phase 1: Precomputation and Heuristics (Time Budget: ~2.8s) ---\n    const double PRECOMP_DEADLINE = 2.8;\n\n    // 1a. Path Centrality\n    vector<long long> edge_path_counts(M, 0);\n    int SAMPLES = 50;\n    vector<int> sample_nodes(N);\n    iota(sample_nodes.begin(), sample_nodes.end(), 0);\n    shuffle(sample_nodes.begin(), sample_nodes.end(), rng);\n    for (int i = 0; i < min((int)sample_nodes.size(), SAMPLES); ++i) {\n        int start_node = sample_nodes[i];\n        vector<long long> dist(N, INF); vector<int> parent_edge(N, -1); dist[start_node] = 0;\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<>> pq; pq.push({0, start_node});\n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop(); if (d > dist[u]) continue;\n            for (const auto& edge_tuple : adj[u]) {\n                auto [v, w, edge_id] = edge_tuple;\n                if (dist[u] != INF && dist[u] + w < dist[v]) {\n                    dist[v] = dist[u] + w; parent_edge[v] = edge_id; pq.push({dist[v], v});\n                }\n            }\n        }\n        vector<vector<int>> tree_adj(N);\n        for(int j=0; j<N; ++j) if (parent_edge[j] != -1) {int u = (edges[parent_edge[j]].u == j) ? edges[parent_edge[j]].v : edges[parent_edge[j]].u; tree_adj[u].push_back(j);}\n        vector<int> subtree_size(N, 0); function<void(int)> dfs_size = [&](int u) {subtree_size[u] = 1; for(int v : tree_adj[u]) {dfs_size(v); subtree_size[u] += subtree_size[v];}}; dfs_size(start_node);\n        for(int j=0; j<N; ++j) if(parent_edge[j] != -1) edge_path_counts[parent_edge[j]] += (long long)subtree_size[j] * (N - subtree_size[j]);\n    }\n\n    // 1b. Edge Importance Score\n    vector<double> edge_importance(M);\n    for(int i = 0; i < M; ++i) {\n        edge_importance[i] = (double)edges[i].w * edge_path_counts[i];\n    }\n    vector<int> sorted_by_importance(M);\n    iota(sorted_by_importance.begin(), sorted_by_importance.end(), 0);\n    sort(sorted_by_importance.begin(), sorted_by_importance.end(), [&](int a, int b){\n        return edge_importance[a] > edge_importance[b];\n    });\n\n    // 1c. Maximal-Effort Structural Analysis\n    BridgeFinder::adj_ptr = &adj;\n    vector<pair<int, int>> critical_pairs;\n    for (int edge_to_ignore : sorted_by_importance) {\n        if (get_time() > PRECOMP_DEADLINE) break;\n        BridgeFinder::find_bridges_in_subgraph(edge_to_ignore, N);\n        critical_pairs.insert(critical_pairs.end(), BridgeFinder::critical_pairs_buffer.begin(), BridgeFinder::critical_pairs_buffer.end());\n        BridgeFinder::critical_pairs_buffer.clear();\n    }\n    for(auto& p : critical_pairs) if (p.first > p.second) swap(p.first, p.second);\n    sort(critical_pairs.begin(), critical_pairs.end());\n    critical_pairs.erase(unique(critical_pairs.begin(), critical_pairs.end()), critical_pairs.end());\n    \n    // 1d. Interaction Matrix\n    vector<vector<float>> interactions(M, vector<float>(M));\n    vector<pair<double, double>> midpoints(M);\n    for(int i=0; i<M; ++i) midpoints[i] = {(coords[edges[i].u].x + coords[edges[i].v].x)/2.0, (coords[edges[i].u].y + coords[edges[i].v].y)/2.0};\n    const float ADJ_PENALTY = 50.0f;\n    const float CRITICAL_PENALTY = 5000.0f;\n    for(int i=0; i<M; ++i) {\n        for(int j=i+1; j<M; ++j) {\n            double dx = midpoints[i].first - midpoints[j].first;\n            double dy = midpoints[i].second - midpoints[j].second;\n            float val = 10000.0f / (dx*dx + dy*dy + 100.0f);\n            if (edges[i].u == edges[j].u || edges[i].u == edges[j].v || edges[i].v == edges[j].u || edges[i].v == edges[j].v) {\n                val += ADJ_PENALTY;\n            }\n            interactions[i][j] = interactions[j][i] = val;\n        }\n    }\n    for(const auto& p : critical_pairs) {\n        interactions[p.first][p.second] += CRITICAL_PENALTY;\n        interactions[p.second][p.first] += CRITICAL_PENALTY;\n    }\n\n    // --- Phase 2: Soft-Constraint Greedy Initial Solution ---\n    vector<vector<int>> days(D);\n    vector<int> edge_to_day(M);\n    for (int edge_idx : sorted_by_importance) {\n        int best_day = -1; float min_cost_increase = 1e18;\n        for (int d = 0; d < D; ++d) {\n            if (days[d].size() >= K) continue;\n            \n            float cost_increase = 0;\n            for (int other_edge_idx : days[d]) {\n                cost_increase += interactions[edge_idx][other_edge_idx];\n            }\n\n            if (cost_increase < min_cost_increase) {\n                min_cost_increase = cost_increase; best_day = d;\n            } else if (abs(cost_increase - min_cost_increase) < 1e-6) {\n                if (best_day == -1 || days[d].size() < days[best_day].size()) best_day = d;\n            }\n        }\n        if (best_day == -1) { // Fallback if all days are full\n            for(int d=0; d<D; ++d) { if (days[d].size() < K) { best_day = d; break; } }\n            if (best_day == -1) best_day = 0;\n        }\n        days[best_day].push_back(edge_idx); edge_to_day[edge_idx] = best_day;\n    }\n    \n    // --- Phase 3: Simulated Annealing Optimization ---\n    double end_temp = 0.1;\n    long long iter_count = 0;\n    const double TIME_LIMIT = 5.95;\n\n    // Temperature Calibration\n    double total_delta = 0; int bad_move_count = 0;\n    for(int i=0; i<1000; ++i) {\n        int e_idx = uniform_int_distribution<>(0, M - 1)(rng);\n        int d1 = edge_to_day[e_idx]; int d2 = uniform_int_distribution<>(0, D - 1)(rng);\n        if(d1 == d2 || days[d2].size() >= K) continue;\n        float cost_d1_old = 0; for(int other_e : days[d1]) if(other_e != e_idx) cost_d1_old += interactions[e_idx][other_e];\n        float cost_d2_new = 0; for(int other_e : days[d2]) cost_d2_new += interactions[e_idx][other_e];\n        double delta = cost_d2_new - cost_d1_old;\n        if(delta > 0) { total_delta += delta; bad_move_count++; }\n    }\n    double avg_bad_delta = (bad_move_count > 0) ? total_delta / bad_move_count : 50.0;\n    double start_temp = -avg_bad_delta / log(0.8);\n    start_temp = max(50.0, min(1000.0, start_temp));\n\n    double temp = start_temp;\n    double precompute_time = get_time();\n\n    while (true) {\n        iter_count++;\n        if ((iter_count & 127) == 0) {\n            double elapsed = get_time();\n            if (elapsed > TIME_LIMIT) break;\n            double sa_progress = max(0.0, elapsed - precompute_time) / (TIME_LIMIT - precompute_time);\n            if (sa_progress >= 1.0) break;\n            temp = start_temp * pow(end_temp / start_temp, sa_progress);\n        }\n\n        int move_type = uniform_int_distribution<>(0, 99)(rng);\n\n        if (move_type < 40) { // Random Move\n            int e_idx = uniform_int_distribution<>(0, M - 1)(rng);\n            int d1 = edge_to_day[e_idx]; int d2 = uniform_int_distribution<>(0, D - 1)(rng);\n            if (d1 == d2 || days[d2].size() >= K) continue;\n            \n            float cost_d1_old = 0; for(int other_e : days[d1]) if(other_e != e_idx) cost_d1_old += interactions[e_idx][other_e];\n            float cost_d2_new = 0; for(int other_e : days[d2]) cost_d2_new += interactions[e_idx][other_e];\n            double delta = cost_d2_new - cost_d1_old;\n\n            if (delta < 0 || (temp > 1e-9 && uniform_real_distribution<>(0.0, 1.0)(rng) < exp(-delta / temp))) {\n                auto& d1_edges = days[d1]; d1_edges.erase(remove(d1_edges.begin(), d1_edges.end(), e_idx), d1_edges.end());\n                days[d2].push_back(e_idx); edge_to_day[e_idx] = d2;\n            }\n        } else if (move_type < 80) { // Random Swap\n            int e1_idx = uniform_int_distribution<>(0, M - 1)(rng);\n            int e2_idx = uniform_int_distribution<>(0, M - 1)(rng);\n            if (e1_idx == e2_idx) continue;\n            int d1 = edge_to_day[e1_idx], d2 = edge_to_day[e2_idx];\n            if (d1 == d2) continue;\n\n            float cost1_in_d1 = 0, cost2_in_d2 = 0, cost1_in_d2 = 0, cost2_in_d1 = 0;\n            for(int e : days[d1]) if (e != e1_idx) { cost1_in_d1 += interactions[e1_idx][e]; cost2_in_d1 += interactions[e2_idx][e]; }\n            for(int e : days[d2]) if (e != e2_idx) { cost2_in_d2 += interactions[e2_idx][e]; cost1_in_d2 += interactions[e1_idx][e]; }\n            double delta = (cost2_in_d1 + cost1_in_d2) - (cost1_in_d1 + cost2_in_d2);\n            \n            if (delta < 0 || (temp > 1e-9 && uniform_real_distribution<>(0.0, 1.0)(rng) < exp(-delta / temp))) {\n                auto& d1_edges = days[d1]; auto& d2_edges = days[d2];\n                *find(d1_edges.begin(), d1_edges.end(), e1_idx) = e2_idx;\n                *find(d2_edges.begin(), d2_edges.end(), e2_idx) = e1_idx;\n                edge_to_day[e1_idx] = d2; edge_to_day[e2_idx] = d1;\n            }\n        } else { // Best Move\n            int e_idx = uniform_int_distribution<>(0, M - 1)(rng);\n            int d1 = edge_to_day[e_idx];\n            int d_best = -1;\n            double min_delta = 1e18;\n\n            float cost_d1_old = 0; for(int other_e : days[d1]) if(other_e != e_idx) cost_d1_old += interactions[e_idx][other_e];\n\n            for(int d2=0; d2<D; ++d2){\n                if(d1 == d2 || days[d2].size() >= K) continue;\n                float cost_d2_new = 0; for(int other_e : days[d2]) cost_d2_new += interactions[e_idx][other_e];\n                double current_delta = cost_d2_new - cost_d1_old;\n                if(current_delta < min_delta){\n                    min_delta = current_delta;\n                    d_best = d2;\n                }\n            }\n\n            if(d_best != -1){\n                 if (min_delta < 0 || (temp > 1e-9 && uniform_real_distribution<>(0.0, 1.0)(rng) < exp(-min_delta / temp))) {\n                    auto& d1_edges = days[d1]; d1_edges.erase(remove(d1_edges.begin(), d1_edges.end(), e_idx), d1_edges.end());\n                    days[d_best].push_back(e_idx); edge_to_day[e_idx] = d_best;\n                }\n            }\n        }\n    }\n\n    // --- Output ---\n    vector<int> result(M);\n    for (int i = 0; i < M; ++i) {\n        result[edges[i].id] = edge_to_day[i] + 1;\n    }\n    for (int i = 0; i < M; ++i) {\n        cout << result[i] << (i == M - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n\n    return 0;\n}","ahc019":"#include <iostream>\n#include <vector>\n#include <string>\n#include <tuple>\n#include <numeric>\n#include <algorithm>\n#include <set>\n#include <map>\n#include <chrono>\n#include <cmath>\n\nusing namespace std;\n\nint D;\nchrono::high_resolution_clock::time_point T_START;\n\nstruct Point3D {\n    int x, y, z;\n    bool operator<(const Point3D& other) const {\n        if (x != other.x) return x < other.x;\n        if (y != other.y) return y < other.y;\n        return z < other.z;\n    }\n    bool operator==(const Point3D& other) const {\n        return x == other.x && y == other.y && z == other.z;\n    }\n};\n\nPoint3D operator+(const Point3D& a, const Point3D& b) { return {a.x + b.x, a.y + b.y, a.z + b.z}; }\nPoint3D operator-(const Point3D& a, const Point3D& b) { return {a.x - b.x, a.y - b.y, a.z - b.z}; }\n\nusing Shape = vector<Point3D>;\n\nconst vector<vector<int>> ROTS = {\n    {1,0,0,0,1,0,0,0,1}, {1,0,0,0,0,-1,0,1,0}, {1,0,0,0,-1,0,0,0,-1}, {1,0,0,0,0,1,0,-1,0},\n    {-1,0,0,0,-1,0,0,0,1}, {-1,0,0,0,0,1,0,1,0}, {-1,0,0,0,1,0,0,0,-1}, {-1,0,0,0,0,-1,0,-1,0},\n    {0,1,0,1,0,0,0,0,-1}, {0,1,0,0,0,1,1,0,0}, {0,1,0,-1,0,0,0,0,1}, {0,1,0,0,0,-1,-1,0,0},\n    {0,-1,0,-1,0,0,0,0,-1}, {0,-1,0,0,0,-1,1,0,0}, {0,-1,0,1,0,0,0,0,1}, {0,-1,0,0,0,1,-1,0,0},\n    {0,0,1,0,1,0,-1,0,0}, {0,0,1,1,0,0,0,1,0}, {0,0,1,0,-1,0,1,0,0}, {0,0,1,-1,0,0,0,-1,0},\n    {0,0,-1,0,-1,0,-1,0,0}, {0,0,-1,-1,0,0,0,1,0}, {0,0,-1,0,1,0,1,0,0}, {0,0,-1,1,0,0,0,-1,0}\n};\n\nPoint3D rotate(const Point3D& p, const vector<int>& R) {\n    return {R[0]*p.x+R[1]*p.y+R[2]*p.z, R[3]*p.x+R[4]*p.y+R[5]*p.z, R[6]*p.x+R[7]*p.y+R[8]*p.z};\n}\n\nShape normalize_shape(Shape s) {\n    if (s.empty()) return {};\n    Point3D min_p = s[0];\n    for (size_t i = 1; i < s.size(); ++i) {\n        min_p.x = min(min_p.x, s[i].x); min_p.y = min(min_p.y, s[i].y); min_p.z = min(min_p.z, s[i].z);\n    }\n    for (auto& p : s) { p = p - min_p; }\n    sort(s.begin(), s.end());\n    return s;\n}\n\nShape get_canonical_shape(const Shape& s) {\n    if (s.empty()) return {};\n    Shape canonical = normalize_shape(s);\n    for (const auto& R : ROTS) {\n        Shape rotated_s;\n        for (const auto& p : s) { rotated_s.push_back(rotate(p, R)); }\n        Shape normalized_rotated = normalize_shape(rotated_s);\n        if (normalized_rotated < canonical) { canonical = normalized_rotated; }\n    }\n    return canonical;\n}\n\nstruct ProtoBlock { Shape points; int id = 0; };\nstruct PlacedBlock { Shape points; int original_idx; int id = 0; };\n\nstruct Solution {\n    long long score = -1;\n    int n = 0;\n    vector<vector<vector<int>>> b1;\n    vector<vector<vector<int>>> b2;\n    bool is_valid() const { return score != -1; }\n};\n\nbool time_limit_exceeded(int limit_ms) {\n    auto now = chrono::high_resolution_clock::now();\n    auto dur = chrono::duration_cast<chrono::milliseconds>(now - T_START).count();\n    return dur > limit_ms;\n}\n\nauto is_valid_coord = [](int x, int y, int z) { return x >= 0 && x < D && y >= 0 && y < D && z >= 0 && z < D; };\n\nSolution solve(const vector<string>& f_start_in, const vector<string>& r_start_in,\n               const vector<string>& f_target_in, const vector<string>& r_target_in, int time_limit_ms)\n{\n    vector<vector<vector<bool>>> C_start(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    vector<vector<vector<bool>>> C_target(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    vector<vector<vector<bool>>> C_common(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    for (int x=0; x<D; ++x) for (int y=0; y<D; ++y) for (int z=0; z<D; ++z) {\n        if (f_start_in[z][x] == '1' && r_start_in[z][y] == '1') C_start[x][y][z] = true;\n        if (f_target_in[z][x] == '1' && r_target_in[z][y] == '1') C_target[x][y][z] = true;\n        if (C_start[x][y][z] && C_target[x][y][z]) C_common[x][y][z] = true;\n    }\n\n    vector<ProtoBlock> common_blocks;\n    vector<vector<vector<bool>>> visited_common = C_common;\n    for (int x=0; x<D; ++x) for (int y=0; y<D; ++y) for (int z=0; z<D; ++z) {\n        if (visited_common[x][y][z]) {\n            Shape pts; vector<Point3D> q; q.push_back({x,y,z});\n            visited_common[x][y][z] = false; size_t head=0;\n            while(head < q.size()) {\n                Point3D curr = q[head++]; pts.push_back(curr);\n                int dx[]={-1,1,0,0,0,0}, dy[]={0,0,-1,1,0,0}, dz[]={0,0,0,0,-1,1};\n                for (int i=0; i<6; ++i) {\n                    Point3D next = {curr.x+dx[i], curr.y+dy[i], curr.z+dz[i]};\n                    if (is_valid_coord(next.x, next.y, next.z) && visited_common[next.x][next.y][next.z]) {\n                        visited_common[next.x][next.y][next.z] = false; q.push_back(next);\n                    }\n                }\n            }\n            common_blocks.push_back({pts, 0});\n        }\n    }\n    \n    vector<bool> f_start_req_met(D*D, false), r_start_req_met(D*D, false);\n    for (const auto& block : common_blocks) for (const auto& p : block.points) {\n        f_start_req_met[p.z*D+p.x] = true; r_start_req_met[p.z*D+p.y] = true;\n    }\n    \n    vector<ProtoBlock> start_fillers;\n    vector<Point3D> start_rem_cells;\n    for (int x=0; x<D; ++x) for(int y=0; y<D; ++y) for (int z=0; z<D; ++z) {\n        if (C_start[x][y][z] && !C_common[x][y][z]) start_rem_cells.push_back({x,y,z});\n    }\n\n    vector<Point3D> filler_cells;\n    while(!start_rem_cells.empty()) {\n        int best_score = -1; vector<int> best_indices;\n        for(size_t i=0; i<start_rem_cells.size(); ++i){\n            const auto& p = start_rem_cells[i];\n            int score = (!f_start_req_met[p.z*D+p.x]) + (!r_start_req_met[p.z*D+p.y]);\n            if(score > best_score) { best_score = score; best_indices.clear(); best_indices.push_back((int)i); }\n            else if(score == best_score) { best_indices.push_back((int)i); }\n        }\n        if(best_score <= 0) break;\n        \n        size_t chosen_rem_idx = best_indices[0];\n        if (best_score > 0 && best_indices.size() > 1 && !filler_cells.empty()){\n            Point3D last_p = filler_cells.back();\n            int min_dist = 1e9;\n            for(int idx : best_indices){\n                const auto& p = start_rem_cells[idx];\n                int dist = abs(p.x - last_p.x) + abs(p.y - last_p.y) + abs(p.z - last_p.z);\n                if(dist < min_dist){\n                    min_dist = dist;\n                    chosen_rem_idx = idx;\n                }\n            }\n        }\n\n        Point3D p = start_rem_cells[chosen_rem_idx];\n        filler_cells.push_back(p);\n        f_start_req_met[p.z*D+p.x] = true; r_start_req_met[p.z*D+p.y] = true;\n        swap(start_rem_cells[chosen_rem_idx], start_rem_cells.back()); start_rem_cells.pop_back();\n    }\n    \n    vector<vector<vector<bool>>> filler_grid(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    for(const auto& p : filler_cells) filler_grid[p.x][p.y][p.z] = true;\n    for(const auto& p_start : filler_cells) {\n        if (filler_grid[p_start.x][p_start.y][p_start.z]) {\n            Shape pts; vector<Point3D> q; q.push_back(p_start);\n            filler_grid[p_start.x][p_start.y][p_start.z] = false; size_t head=0;\n            while(head<q.size()){\n                Point3D curr = q[head++]; pts.push_back(curr);\n                int dx[]={-1,1,0,0,0,0}, dy[]={0,0,-1,1,0,0}, dz[]={0,0,0,0,-1,1};\n                for(int i=0; i<6; ++i) {\n                    Point3D next = {curr.x+dx[i], curr.y+dy[i], curr.z+dz[i]};\n                    if(is_valid_coord(next.x, next.y, next.z) && filler_grid[next.x][next.y][next.z]) {\n                        filler_grid[next.x][next.y][next.z] = false; q.push_back(next);\n                    }\n                }\n            }\n            start_fillers.push_back({pts, 0});\n        }\n    }\n    \n    vector<PlacedBlock> placed_common_blocks;\n    vector<vector<vector<bool>>> target_occupied(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    vector<bool> f_target_req_met(D*D, false), r_target_req_met(D*D, false);\n    vector<bool> common_block_placed(common_blocks.size(), false);\n    \n    vector<pair<int, const ProtoBlock*>> sorted_common_blocks;\n    for(size_t i = 0; i < common_blocks.size(); ++i) sorted_common_blocks.push_back({(int)i, &common_blocks[i]});\n    sort(sorted_common_blocks.begin(), sorted_common_blocks.end(), [](const auto&a, const auto&b){\n        return a.second->points.size() > b.second->points.size();\n    });\n\n    for (const auto& [idx, block_ptr] : sorted_common_blocks) {\n        if (time_limit_exceeded(time_limit_ms - 200)) break;\n        Shape s_rel = normalize_shape(block_ptr->points);\n        int best_block_score = -1; Shape best_block_placed_shape;\n        for (const auto& R : ROTS) {\n            Shape s_rot; for(const auto& p : s_rel) s_rot.push_back(rotate(p, R));\n            Point3D min_p_rot = s_rot[0];\n            for(size_t j=1; j<s_rot.size(); ++j) { min_p_rot.x=min(min_p_rot.x,s_rot[j].x); min_p_rot.y=min(min_p_rot.y,s_rot[j].y); min_p_rot.z=min(min_p_rot.z,s_rot[j].z); }\n            for (int x=0; x<D; ++x) for(int y=0; y<D; ++y) for(int z=0; z<D; ++z) {\n                Point3D trans = {x - min_p_rot.x, y - min_p_rot.y, z - min_p_rot.z};\n                bool possible = true; Shape placed_shape;\n                set<pair<int,int>> f_covered, r_covered;\n                for (const auto& p_rot : s_rot) {\n                    Point3D p_final = p_rot + trans;\n                    if (!is_valid_coord(p_final.x, p_final.y, p_final.z) || !C_target[p_final.x][p_final.y][p_final.z] || target_occupied[p_final.x][p_final.y][p_final.z]) {\n                        possible = false; break;\n                    }\n                    placed_shape.push_back(p_final);\n                    if (!f_target_req_met[p_final.z*D+p_final.x]) f_covered.insert({p_final.z, p_final.x});\n                    if (!r_target_req_met[p_final.z*D+p_final.y]) r_covered.insert({p_final.z, p_final.y});\n                }\n                if (possible) {\n                    int current_score = f_covered.size() + r_covered.size();\n                    if (current_score > best_block_score) {\n                        best_block_score = current_score; best_block_placed_shape = placed_shape;\n                    }\n                }\n            }\n        }\n        if(best_block_score >= 0){\n            placed_common_blocks.push_back({best_block_placed_shape, idx, 0});\n            common_block_placed[idx] = true;\n            for (const auto& p : best_block_placed_shape) {\n                target_occupied[p.x][p.y][p.z] = true;\n                f_target_req_met[p.z*D+p.x] = true; r_target_req_met[p.z*D+p.y] = true;\n            }\n        }\n    }\n    \n    vector<ProtoBlock> target_fillers;\n    vector<Point3D> target_rem_cells;\n    for (int x=0; x<D; ++x) for (int y=0; y<D; ++y) for (int z=0; z<D; ++z) {\n        if (C_target[x][y][z] && !target_occupied[x][y][z]) target_rem_cells.push_back({x,y,z});\n    }\n    vector<Point3D> t_filler_cells;\n    while(!target_rem_cells.empty()) {\n        int best_score = -1; vector<int> best_indices;\n        for(size_t i=0; i<target_rem_cells.size(); ++i){\n            const auto& p = target_rem_cells[i];\n            int score = (!f_target_req_met[p.z*D+p.x]) + (!r_target_req_met[p.z*D+p.y]);\n            if(score > best_score) { best_score = score; best_indices.clear(); best_indices.push_back((int)i); }\n            else if(score == best_score) { best_indices.push_back((int)i); }\n        }\n        if(best_score <= 0) break;\n        \n        size_t chosen_rem_idx = best_indices[0];\n        if (best_score > 0 && best_indices.size() > 1 && !t_filler_cells.empty()){\n            Point3D last_p = t_filler_cells.back();\n            int min_dist = 1e9;\n            for(int idx : best_indices){\n                const auto& p = target_rem_cells[idx];\n                int dist = abs(p.x - last_p.x) + abs(p.y - last_p.y) + abs(p.z - last_p.z);\n                if(dist < min_dist){\n                    min_dist = dist;\n                    chosen_rem_idx = idx;\n                }\n            }\n        }\n\n        Point3D p = target_rem_cells[chosen_rem_idx];\n        t_filler_cells.push_back(p);\n        f_target_req_met[p.z*D+p.x] = true; r_target_req_met[p.z*D+p.y] = true;\n        swap(target_rem_cells[chosen_rem_idx], target_rem_cells.back()); target_rem_cells.pop_back();\n    }\n    \n    vector<vector<vector<bool>>> t_filler_grid(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    for(const auto& p : t_filler_cells) t_filler_grid[p.x][p.y][p.z] = true;\n    for(const auto& p_start : t_filler_cells) {\n        if (t_filler_grid[p_start.x][p_start.y][p_start.z]) {\n            Shape pts; vector<Point3D> q; q.push_back(p_start);\n            t_filler_grid[p_start.x][p_start.y][p_start.z] = false; size_t head=0;\n            while(head<q.size()){\n                Point3D curr = q[head++]; pts.push_back(curr);\n                int dx[]={-1,1,0,0,0,0}, dy[]={0,0,-1,1,0,0}, dz[]={0,0,0,0,-1,1};\n                for(int i=0; i<6; ++i) {\n                    Point3D next = {curr.x+dx[i], curr.y+dy[i], curr.z+dz[i]};\n                    if(is_valid_coord(next.x, next.y, next.z) && t_filler_grid[next.x][next.y][next.z]) {\n                        t_filler_grid[next.x][next.y][next.z] = false; q.push_back(next);\n                    }\n                }\n            }\n            target_fillers.push_back({pts, 0});\n        }\n    }\n\n    int next_id = 1;\n    for (size_t i=0; i<common_blocks.size(); ++i) {\n        if (common_block_placed[i]) {\n            common_blocks[i].id = next_id++;\n        }\n    }\n    for (auto& pb : placed_common_blocks) {\n        pb.id = common_blocks[pb.original_idx].id;\n    }\n    \n    vector<ProtoBlock*> unplaced_common_ptrs;\n    for(size_t i=0; i<common_blocks.size(); ++i) if(!common_block_placed[i]) unplaced_common_ptrs.push_back(&common_blocks[i]);\n    vector<ProtoBlock*> start_fillers_ptrs; for(auto&b: start_fillers) start_fillers_ptrs.push_back(&b);\n    vector<ProtoBlock*> target_fillers_ptrs; for(auto&b: target_fillers) target_fillers_ptrs.push_back(&b);\n\n    vector<ProtoBlock*> start_specific_ptrs = unplaced_common_ptrs;\n    start_specific_ptrs.insert(start_specific_ptrs.end(), start_fillers_ptrs.begin(), start_fillers_ptrs.end());\n    \n    map<Shape, vector<ProtoBlock*>> start_by_canon, target_by_canon;\n    set<Shape> all_rem_canons;\n    for(auto ptr : start_specific_ptrs) {\n        if (ptr->points.empty()) continue;\n        Shape canon = get_canonical_shape(normalize_shape(ptr->points));\n        start_by_canon[canon].push_back(ptr); all_rem_canons.insert(canon);\n    }\n    for(auto ptr : target_fillers_ptrs) {\n        if (ptr->points.empty()) continue;\n        Shape canon = get_canonical_shape(normalize_shape(ptr->points));\n        target_by_canon[canon].push_back(ptr); all_rem_canons.insert(canon);\n    }\n\n    long long r_start_vol = 0, r_target_vol = 0; double inv_v_sum = 0;\n    for (const auto& b : placed_common_blocks) inv_v_sum += 1.0 / b.points.size();\n\n    for (const auto& canon : all_rem_canons) {\n        auto it1 = start_by_canon.find(canon); auto it2 = target_by_canon.find(canon);\n        vector<ProtoBlock*> v1 = (it1 == start_by_canon.end()) ? vector<ProtoBlock*>() : it1->second;\n        vector<ProtoBlock*> v2 = (it2 == target_by_canon.end()) ? vector<ProtoBlock*>() : it2->second;\n        size_t matches = min(v1.size(), v2.size());\n        for (size_t i = 0; i < matches; ++i) {\n            int id = next_id++; v1[i]->id = id; v2[i]->id = id;\n            inv_v_sum += 1.0 / v1[i]->points.size();\n        }\n        for (size_t i = matches; i < v1.size(); ++i) {\n            v1[i]->id = next_id++; r_target_vol += v1[i]->points.size();\n        }\n        for (size_t i = matches; i < v2.size(); ++i) {\n            v2[i]->id = next_id++; r_start_vol += v2[i]->points.size();\n        }\n    }\n    \n    Solution res;\n    res.score = round(1e9 * (r_start_vol + r_target_vol + inv_v_sum));\n    res.n = next_id - 1;\n    res.b1.assign(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    res.b2.assign(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    \n    for (const auto& block : common_blocks) for (const auto& p : block.points) res.b1[p.x][p.y][p.z] = block.id;\n    for (const auto& block : start_fillers) for (const auto& p : block.points) res.b1[p.x][p.y][p.z] = block.id;\n    for (const auto& block : placed_common_blocks) for (const auto& p : block.points) res.b2[p.x][p.y][p.z] = block.id;\n    for (const auto& block : target_fillers) for (const auto& p : block.points) res.b2[p.x][p.y][p.z] = block.id;\n    return res;\n}\n\nint main() {\n    T_START = chrono::high_resolution_clock::now();\n    ios_base::sync_with_stdio(false); cin.tie(NULL);\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    Solution res1 = solve(f1, r1, f2, r2, 2900);\n    Solution res2_swapped;\n    if (!time_limit_exceeded(5800)) {\n       res2_swapped = solve(f2, r2, f1, r1, 5800);\n    }\n\n    Solution best_res = res1;\n    if (res2_swapped.is_valid()) {\n        Solution res2 = {res2_swapped.score, res2_swapped.n, res2_swapped.b2, res2_swapped.b1};\n        if (!best_res.is_valid() || res2.score < best_res.score) {\n            best_res = res2;\n        }\n    }\n\n    if (!best_res.is_valid() || best_res.n == 0) {\n         cout << 0 << endl;\n         for(int i=0; i<D*D*D; ++i) cout << \"0\" << (i==D*D*D-1 ? \"\" : \" \");\n         cout << endl;\n         for(int i=0; i<D*D*D; ++i) cout << \"0\" << (i==D*D*D-1 ? \"\" : \" \");\n         cout << endl;\n         return 0;\n    }\n\n    cout << best_res.n << endl;\n    for(int x=0; x<D; ++x) for(int y=0; y<D; ++y) for(int z=0; z<D; ++z) cout << best_res.b1[x][y][z] << (x==D-1&&y==D-1&&z==D-1?\"\":\" \");\n    cout << endl;\n    for(int x=0; x<D; ++x) for(int y=0; y<D; ++y) for(int z=0; z<D; ++z) cout << best_res.b2[x][y][z] << (x==D-1&&y==D-1&&z==D-1?\"\":\" \");\n    cout << endl;\n\n    return 0;\n}","ahc020":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <queue>\n\nusing namespace std;\n\nconst long long INF = 1e18;\n\nstruct Point {\n    long long x, y;\n};\n\nstruct Edge {\n    int u, v;\n    long long w;\n    int id;\n};\n\nstruct GraphEdge {\n    int to;\n    long long weight;\n    int id;\n};\n\nlong long distSq(const Point& p1, const Point& p2) {\n    return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y);\n}\n\n// Global timer\nchrono::steady_clock::time_point start_time;\n\nbool is_time_up(double time_limit) {\n    auto now = chrono::steady_clock::now();\n    double elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n    return elapsed > time_limit;\n}\n\n// --- Precomputed data ---\nint N, M, K;\nvector<Point> stations;\nvector<Point> residents;\nvector<Edge> edges;\nvector<vector<GraphEdge>> adj;\nvector<vector<long long>> dist_G;\nvector<vector<int>> parent_G;\nvector<vector<pair<long long, int>>> dists_to_resident;\n\n// --- Randomness ---\nmt19937 rng;\n\nlong long integer_ceil_sqrt(long long n) {\n    if (n < 0) return 0;\n    if (n == 0) return 0;\n    long long root = sqrtl((long double)n);\n    while (root * root > n) {\n        root--;\n    }\n    while ((root + 1) * (root + 1) <= n) {\n        root++;\n    }\n    if (root * root < n) {\n        return root + 1;\n    }\n    return root;\n}\n\nlong long calculate_connection_cost(const vector<int>& V_list) {\n    if (V_list.size() <= 1) return 0;\n\n    long long cost = 0;\n    vector<long long> min_cost(N + 1, INF);\n    vector<bool> in_mst(N + 1, false);\n\n    min_cost[V_list[0]] = 0;\n    \n    for (size_t i = 0; i < V_list.size(); ++i) {\n        int u = -1;\n        for (int station_id : V_list) {\n            if (!in_mst[station_id] && (u == -1 || min_cost[station_id] < min_cost[u])) {\n                u = station_id;\n            }\n        }\n\n        if (u == -1) break;\n        in_mst[u] = true;\n        cost += min_cost[u];\n\n        for (int v : V_list) {\n            if (!in_mst[v]) {\n                min_cost[v] = min(min_cost[v], dist_G[u - 1][v - 1]);\n            }\n        }\n    }\n    return cost;\n}\n\nbool check_coverage(const vector<bool>& active) {\n    for (int k = 0; k < K; ++k) {\n        bool covered = false;\n        for (const auto& p : dists_to_resident[k]) {\n            if (active[p.second]) {\n                covered = true;\n                break;\n            }\n        }\n        if (!covered) return false;\n    }\n    return true;\n}\n\nlong long calculate_total_cost(const vector<bool>& active, vector<long long>& required_power_sq_out, vector<int>& max_power_resident_out) {\n    vector<int> V_list;\n    for (int i = 1; i <= N; ++i) {\n        if (active[i]) V_list.push_back(i);\n    }\n    if (V_list.empty() || !active[1]) {\n        return INF;\n    }\n\n    long long connection_cost = calculate_connection_cost(V_list);\n\n    long long power_cost = 0;\n    required_power_sq_out.assign(N + 1, 0);\n    max_power_resident_out.assign(N + 1, -1);\n\n    for (int k = 0; k < K; ++k) {\n        for (const auto& p : dists_to_resident[k]) {\n            int station_id = p.second;\n            if (active[station_id]) {\n                if (p.first > required_power_sq_out[station_id]) {\n                    required_power_sq_out[station_id] = p.first;\n                    max_power_resident_out[station_id] = k;\n                }\n                break;\n            }\n        }\n    }\n\n    for (int i = 1; i <= N; ++i) {\n        if (required_power_sq_out[i] > 0) {\n            long long p = integer_ceil_sqrt(required_power_sq_out[i]);\n            if (p > 5000) return INF;\n            power_cost += p * p;\n        }\n    }\n    \n    return connection_cost + power_cost;\n}\n\nlong long calculate_total_cost(const vector<bool>& active) {\n    vector<long long> dummy_p;\n    vector<int> dummy_k;\n    return calculate_total_cost(active, dummy_p, dummy_k);\n}\n\nvoid solve() {\n    start_time = chrono::steady_clock::now();\n    \n    cin >> N >> M >> K;\n    stations.resize(N);\n    for (int i = 0; i < N; ++i) cin >> stations[i].x >> stations[i].y;\n    edges.resize(M);\n    adj.resize(N + 1);\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\n        edges[i].id = i + 1;\n        adj[edges[i].u].push_back({edges[i].v, edges[i].w, edges[i].id});\n        adj[edges[i].v].push_back({edges[i].u, edges[i].w, edges[i].id});\n    }\n    residents.resize(K);\n    for (int i = 0; i < K; ++i) cin >> residents[i].x >> residents[i].y;\n\n    // Precomputation\n    dist_G.assign(N, vector<long long>(N, INF));\n    parent_G.assign(N, vector<int>(N, -1));\n\n    for (int i = 0; i < N; ++i) {\n        dist_G[i][i] = 0;\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n        pq.push({0, i + 1});\n\n        vector<long long> d(N + 1, INF);\n        vector<int> p(N + 1, -1);\n        d[i + 1] = 0;\n\n        while (!pq.empty()) {\n            auto [cost, u] = pq.top();\n            pq.pop();\n\n            if (cost > d[u]) continue;\n\n            for (const auto& edge : adj[u]) {\n                int v = edge.to;\n                if (d[u] + edge.weight < d[v]) {\n                    d[v] = d[u] + edge.weight;\n                    p[v] = u;\n                    pq.push({d[v], v});\n                }\n            }\n        }\n        for (int j = 0; j < N; ++j) {\n            dist_G[i][j] = d[j + 1];\n            parent_G[i][j] = p[j + 1];\n        }\n    }\n    \n    dists_to_resident.resize(K);\n    for (int k = 0; k < K; ++k) {\n        for (int i = 0; i < N; ++i) {\n            dists_to_resident[k].push_back({distSq(residents[k], stations[i]), i + 1});\n        }\n        sort(dists_to_resident[k].begin(), dists_to_resident[k].end());\n    }\n\n    // --- Robust Initial Solution with Fixup Loop ---\n    vector<bool> current_V(N + 1, false);\n    current_V[1] = true;\n    for (int iter = 0; iter < N + 5; ++iter) {\n        while (true) {\n            int uncovered_k = -1;\n            for (int k = 0; k < K; ++k) {\n                bool covered = false;\n                for (const auto& p : dists_to_resident[k]) if (current_V[p.second]) { covered = true; break; }\n                if (!covered) { uncovered_k = k; break; }\n            }\n            if (uncovered_k == -1) break;\n            for (const auto& p : dists_to_resident[uncovered_k]) if (p.first <= 5000LL * 5000LL) { if (!current_V[p.second]) { current_V[p.second] = true; break; } }\n        }\n        vector<long long> req_p_sq; vector<int> max_p_res;\n        calculate_total_cost(current_V, req_p_sq, max_p_res);\n        int problematic_station = -1;\n        for (int i = 1; i <= N; ++i) if (req_p_sq[i] > 5000LL * 5000LL) { problematic_station = i; break; }\n        if (problematic_station == -1) break;\n        int problematic_resident = max_p_res[problematic_station];\n        for (const auto& p : dists_to_resident[problematic_resident]) if (p.first <= 5000LL * 5000LL) { if (!current_V[p.second]) { current_V[p.second] = true; break; } }\n    }\n    \n    // --- Greedy Refinement ---\n    bool changed = true;\n    while(changed) {\n        changed = false;\n        vector<int> active_nodes; for(int i=2; i<=N; ++i) if(current_V[i]) active_nodes.push_back(i);\n        shuffle(active_nodes.begin(), active_nodes.end(), rng);\n        long long base_cost = calculate_total_cost(current_V);\n        for(int v : active_nodes) {\n            current_V[v] = false;\n            if (check_coverage(current_V)) {\n                long long new_cost = calculate_total_cost(current_V);\n                if (new_cost != INF && new_cost < base_cost) { base_cost = new_cost; changed = true; } else { current_V[v] = true; }\n            } else { current_V[v] = true; }\n        }\n    }\n\n    vector<bool> best_V = current_V;\n    vector<long long> current_req_p_sq; vector<int> current_max_power_resident;\n    long long current_cost = calculate_total_cost(current_V, current_req_p_sq, current_max_power_resident);\n    long long best_cost = current_cost;\n\n    // --- Simulated Annealing ---\n    double time_limit = 1980;\n    double T_start = best_cost > 0 ? best_cost / 10.0 : 1000.0;\n    double T_end = 1.0;\n    \n    uniform_int_distribution<> dist_N(1, N);\n    uniform_real_distribution<> dist_real(0.0, 1.0);\n\n    while (!is_time_up(time_limit)) {\n        double elapsed = chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count();\n        double progress = elapsed / time_limit;\n        if (progress > 1.0) progress = 1.0;\n        double T = T_start * pow(T_end / T_start, progress);\n\n        vector<bool> next_V = current_V;\n        double move_type = dist_real(rng);\n\n        if (move_type < 0.4) { // ADD\n            bool guided_add = dist_real(rng) < 0.5; bool success = false;\n            if (guided_add) {\n                int s_max = -1; long long max_p_sq = -1;\n                for (int i=1; i<=N; ++i) if (current_V[i] && current_req_p_sq[i] > max_p_sq) { max_p_sq = current_req_p_sq[i]; s_max = i; }\n                if (s_max != -1) {\n                    int k_far = current_max_power_resident[s_max];\n                    if (k_far != -1) for(const auto& p : dists_to_resident[k_far]) if(!current_V[p.second]) { next_V[p.second] = true; success = true; break; }\n                }\n            }\n            if(!success) { int u; int attempts=0; do { u = dist_N(rng); attempts++; } while(next_V[u] && attempts < 2*N); if(!next_V[u]) next_V[u] = true; else continue; }\n        } else if (move_type < 0.8) { // REMOVE\n            bool guided_remove = dist_real(rng) < 0.5; bool success = false;\n            if (guided_remove) {\n                vector<pair<long long, int>> candidates;\n                for(int i = 2; i <= N; ++i) if (current_V[i]) candidates.push_back({current_req_p_sq[i], i});\n                if (!candidates.empty()) {\n                    sort(candidates.begin(), candidates.end());\n                    int num_to_pick = max(1, (int)candidates.size() / 5);\n                    uniform_int_distribution<> dist_cand(0, num_to_pick - 1);\n                    int v_to_remove = candidates[dist_cand(rng)].second;\n                    next_V[v_to_remove] = false; success = true;\n                }\n            }\n            if (!success) { vector<int> active_nodes; for(int i=2; i<=N; ++i) if(next_V[i]) active_nodes.push_back(i); if (active_nodes.empty()) continue; uniform_int_distribution<> dist_rem(0, active_nodes.size() - 1); next_V[active_nodes[dist_rem(rng)]] = false; }\n            if (!check_coverage(next_V)) continue;\n        } else { // SWAP\n            vector<int> active_nodes; for(int i=2; i<=N; ++i) if(next_V[i]) active_nodes.push_back(i); if (active_nodes.empty()) continue;\n            uniform_int_distribution<> dist_rem(0, active_nodes.size() - 1); int v = active_nodes[dist_rem(rng)];\n            int u; int attempts_u = 0; do { u = dist_N(rng); attempts_u++; } while(next_V[u] && attempts_u < 2*N); if(next_V[u]) continue;\n            next_V[v] = false; next_V[u] = true;\n            if (!check_coverage(next_V)) continue;\n        }\n        \n        vector<long long> next_req_p_sq; vector<int> next_max_power_resident;\n        long long next_cost = calculate_total_cost(next_V, next_req_p_sq, next_max_power_resident);\n        if(next_cost == INF) continue;\n\n        long long delta = next_cost - current_cost;\n        if (delta < 0 || (T > 0 && dist_real(rng) < exp(-(double)delta / T))) {\n            current_V = next_V;\n            current_cost = next_cost;\n            current_req_p_sq = next_req_p_sq;\n            current_max_power_resident = next_max_power_resident;\n            if (current_cost < best_cost) {\n                best_cost = current_cost;\n                best_V = current_V;\n            }\n        }\n    }\n\n    // --- Output ---\n    vector<long long> P(N + 1, 0);\n    vector<long long> required_power_sq(N + 1, 0); vector<int> dummy_k;\n    calculate_total_cost(best_V, required_power_sq, dummy_k);\n    for (int i = 1; i <= N; ++i) {\n        if (best_V[i] && required_power_sq[i] > 0) P[i] = integer_ceil_sqrt(required_power_sq[i]);\n    }\n\n    vector<bool> B(M + 1, false);\n    vector<int> V_list; for (int i = 1; i <= N; ++i) if (best_V[i]) V_list.push_back(i);\n    if (V_list.size() > 1) {\n        vector<long long> min_cost(N + 1, INF); vector<int> edge_from(N + 1, -1); vector<bool> in_mst(N + 1, false);\n        min_cost[V_list[0]] = 0;\n        for (size_t i = 0; i < V_list.size(); ++i) {\n            int u = -1;\n            for (int sid : V_list) if (!in_mst[sid] && (u == -1 || min_cost[sid] < min_cost[u])) u = sid;\n            if (u == -1) break;\n            in_mst[u] = true;\n            if (edge_from[u] != -1) {\n                int v = edge_from[u], start_node_idx = v-1, curr_node_idx = u-1;\n                while(curr_node_idx != start_node_idx) {\n                    int prev_node = parent_G[start_node_idx][curr_node_idx];\n                    if (prev_node == -1) break;\n                    for(const auto& edge : adj[curr_node_idx+1]) if (edge.to == prev_node) { B[edge.id] = true; break; }\n                    curr_node_idx = prev_node-1;\n                }\n            }\n            for (int v_idx : V_list) if (!in_mst[v_idx] && dist_G[u-1][v_idx-1] < min_cost[v_idx]) { min_cost[v_idx] = dist_G[u-1][v_idx-1]; edge_from[v_idx] = u; }\n        }\n    }\n\n    for (int i = 1; i <= N; ++i) cout << P[i] << (i == N ? \"\" : \" \"); cout << endl;\n    for (int i = 1; i <= M; ++i) cout << B[i] << (i == M ? \"\" : \" \"); cout << endl;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    unsigned int seed = chrono::high_resolution_clock::now().time_since_epoch().count();\n    rng.seed(seed);\n    solve();\n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <tuple>\n\nconst int N = 30;\nconst int TOTAL_BALLS = N * (N + 1) / 2;\nconst int MAX_OPS = 10000;\n\nstd::vector<std::vector<int>> b;\nstd::vector<std::pair<int, int>> pos;\nstd::vector<std::tuple<int, int, int, int>> ops;\n\nvoid do_swap(int r1, int c1, int r2, int c2) {\n    if (ops.size() >= MAX_OPS) return;\n\n    int val1 = b[r1][c1];\n    int val2 = b[r2][c2];\n\n    std::swap(b[r1][c1], b[r2][c2]);\n    std::swap(pos[val1], pos[val2]);\n    \n    ops.emplace_back(r1, c1, r2, c2);\n}\n\n// Moves small values up as far as they can go.\nvoid small_up_climb_pass() {\n    for (int v = 0; v < TOTAL_BALLS; ++v) {\n        while (ops.size() < MAX_OPS) {\n            auto [r, c] = pos[v];\n            if (r == 0) break;\n\n            bool has_p_left = (c > 0);\n            bool has_p_right = (c < r);\n\n            int p_left_val = -1, p_right_val = -1;\n            if (has_p_left) p_left_val = b[r - 1][c - 1];\n            if (has_p_right) p_right_val = b[r - 1][c];\n            \n            bool swap_left = has_p_left && v < p_left_val;\n            bool swap_right = has_p_right && v < p_right_val;\n\n            if (!swap_left && !swap_right) break;\n\n            if (swap_left && swap_right) {\n                if (p_left_val > p_right_val) {\n                    do_swap(r, c, r - 1, c - 1);\n                } else {\n                    do_swap(r, c, r - 1, c);\n                }\n            } else if (swap_left) {\n                do_swap(r, c, r - 1, c - 1);\n            } else { // swap_right\n                do_swap(r, c, r - 1, c);\n            }\n        }\n    }\n}\n\n// Moves large values down as far as they can go.\nvoid large_down_sink_pass() {\n    for (int v = TOTAL_BALLS - 1; v >= 0; --v) {\n        while (ops.size() < MAX_OPS) {\n            auto [r, c] = pos[v];\n            if (r == N - 1) break;\n            \n            int child_left_val = b[r + 1][c];\n            int child_right_val = b[r + 1][c + 1];\n\n            bool swap_left = v > child_left_val;\n            bool swap_right = v > child_right_val;\n\n            if (!swap_left && !swap_right) break;\n\n            if (swap_left && swap_right) {\n                if (child_left_val < child_right_val) {\n                    do_swap(r, c, r + 1, c);\n                } else {\n                    do_swap(r, c, r + 1, c + 1);\n                }\n            } else if (swap_left) {\n                do_swap(r, c, r + 1, c);\n            } else { // swap_right\n                do_swap(r, c, r + 1, c + 1);\n            }\n        }\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    b.resize(N);\n    pos.resize(TOTAL_BALLS);\n    for (int i = 0; i < N; ++i) {\n        b[i].resize(i + 1);\n        for (int j = 0; j <= i; ++j) {\n            std::cin >> b[i][j];\n            pos[b[i][j]] = {i, j};\n        }\n    }\n\n    int iter = 0;\n    while(ops.size() < MAX_OPS) {\n        size_t ops_before_iter = ops.size();\n        \n        if (iter % 2 == 0) {\n            small_up_climb_pass();\n            if (ops.size() >= MAX_OPS) break;\n            large_down_sink_pass();\n        } else {\n            large_down_sink_pass();\n            if (ops.size() >= MAX_OPS) break;\n            small_up_climb_pass();\n        }\n\n        if (ops.size() == ops_before_iter) break;\n        iter++;\n    }\n\n    std::cout << ops.size() << \"\\n\";\n    for (const auto& op : ops) {\n        std::cout << std::get<0>(op) << \" \" << std::get<1>(op) << \" \" << std::get<2>(op) << \" \" << std::get<3>(op) << \"\\n\";\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n#include <map>\n#include <tuple>\n#include <set>\n#include <cassert>\n\nusing namespace std;\n\n// Constants and global state\nconst int D_CONST = 9;\nconst int ENTRANCE_R = 0;\nconst int ENTRANCE_C = (D_CONST - 1) / 2;\nconst int DR[] = {-1, 1, 0, 0};\nconst int DC[] = {0, 0, -1, 1};\n\nint D_input, N;\nint C; // Total number of containers\nvector<vector<int>> grid; // Grid state: -3=Empty, -2=Entrance, -1=Obstacle, >=0=Container ID\nmap<int, pair<int, int>> container_locs; // Maps container ID to its location\n\n// Candidate struct for dynamic placement decision\nstruct Candidate {\n    int r, c;\n    int dist;\n    int dynamic_block_count;\n};\n\n// Utility to check if coordinates are within the grid\nbool is_valid(int r, int c) {\n    return r >= 0 && r < D_CONST && c >= 0 && c < D_CONST;\n}\n\n// Phase 1: Just read inputs and set up the initial grid\nvoid precompute() {\n    C = D_CONST * D_CONST - 1 - N;\n    grid.assign(D_CONST, vector<int>(D_CONST, -3));\n    grid[ENTRANCE_R][ENTRANCE_C] = -2;\n    \n    for (int i = 0; i < N; ++i) {\n        int r, c;\n        cin >> r >> c;\n        grid[r][c] = -1;\n    }\n}\n\n// Phase 2: Place containers using the Power-Law Proportional strategy\nvoid solve_placement() {\n    for (int d = 0; d < C; ++d) {\n        int t_d;\n        cin >> t_d;\n\n        // 1. Find all currently reachable empty squares and their distances.\n        vector<pair<int, int>> reachable_empty_squares;\n        vector<vector<int>> dist_grid(D_CONST, vector<int>(D_CONST, -1));\n        queue<pair<int, int>> q;\n        \n        q.push({ENTRANCE_R, ENTRANCE_C});\n        dist_grid[ENTRANCE_R][ENTRANCE_C] = 0;\n\n        queue<pair<int, int>> q_bfs = q;\n        while(!q_bfs.empty()){\n            auto [r, c] = q_bfs.front();\n            q_bfs.pop();\n            if(grid[r][c] == -3) {\n                reachable_empty_squares.push_back({r, c});\n            }\n            for(int i = 0; i < 4; ++i){\n                int nr = r + DR[i];\n                int nc = c + DC[i];\n                if(is_valid(nr, nc) && dist_grid[nr][nc] == -1 && (grid[nr][nc] == -3 || grid[nr][nc] == -2)) {\n                    dist_grid[nr][nc] = dist_grid[r][c] + 1;\n                    q_bfs.push({nr, nc});\n                }\n            }\n        }\n        \n        assert(!reachable_empty_squares.empty());\n\n        // 2. Evaluate each reachable empty square as a candidate.\n        vector<Candidate> candidates;\n        for (const auto& square : reachable_empty_squares) {\n            int r = square.first, c = square.second;\n            grid[r][c] = -1; // Temporarily block\n            \n            vector<vector<char>> visited_after(D_CONST, vector<char>(D_CONST, 0));\n            queue<pair<int, int>> q_check;\n            if(grid[ENTRANCE_R][ENTRANCE_C] != -1) {\n                q_check.push({ENTRANCE_R, ENTRANCE_C});\n                visited_after[ENTRANCE_R][ENTRANCE_C] = 1;\n            }\n            while(!q_check.empty()){\n                auto [curr_r, curr_c] = q_check.front(); q_check.pop();\n                for(int i = 0; i < 4; ++i){\n                    int nr = curr_r + DR[i]; int nc = curr_c + DC[i];\n                    if(is_valid(nr, nc) && !visited_after[nr][nc] && (grid[nr][nc] == -3 || grid[nr][nc] == -2)){\n                        visited_after[nr][nc] = 1; q_check.push({nr, nc});\n                    }\n                }\n            }\n            int reachable_count_after = 0;\n            for(const auto& other_square : reachable_empty_squares) {\n                if (square != other_square && visited_after[other_square.first][other_square.second]) {\n                    reachable_count_after++;\n                }\n            }\n            int dynamic_block_count = (int)(reachable_empty_squares.size() - 1) - reachable_count_after;\n            \n            grid[r][c] = -3; // Restore\n            candidates.push_back({r, c, dist_grid[r][c], dynamic_block_count});\n        }\n        \n        // 3. Select the best candidate using the Power-Law Proportional strategy.\n        vector<Candidate> safe_candidates, bottleneck_candidates;\n        for(const auto& cand : candidates) {\n            if(cand.dynamic_block_count == 0) safe_candidates.push_back(cand);\n            else bottleneck_candidates.push_back(cand);\n        }\n        \n        Candidate best_cand;\n        if (!safe_candidates.empty()) {\n            // Use the proven best sorting method: distance, then scanline.\n            sort(safe_candidates.begin(), safe_candidates.end(), [](const Candidate& a, const Candidate& b){\n                if (a.dist != b.dist) return a.dist < b.dist;\n                if (a.r != b.r) return a.r < b.r;\n                return a.c < b.c;\n            });\n            \n            // Apply the power-law adjustment to the proportional mapping.\n            double percentile = (C > 1) ? (double)t_d / (C - 1.0) : 0.0;\n            double adjusted_percentile = pow(percentile, 0.75);\n            int target_idx = round(adjusted_percentile * (safe_candidates.size() - 1));\n            \n            best_cand = safe_candidates[target_idx];\n\n        } else { // Fallback: use bottleneck with least damage.\n            assert(!bottleneck_candidates.empty());\n            sort(bottleneck_candidates.begin(), bottleneck_candidates.end(), [](const Candidate& a, const Candidate& b){\n                if (a.dynamic_block_count != b.dynamic_block_count) return a.dynamic_block_count < b.dynamic_block_count;\n                if (a.dist != b.dist) return a.dist > b.dist;\n                if (a.r != b.r) return a.r > b.r;\n                return a.c > b.c;\n            });\n            best_cand = bottleneck_candidates[0];\n        }\n\n        grid[best_cand.r][best_cand.c] = t_d;\n        container_locs[t_d] = {best_cand.r, best_cand.c};\n        cout << best_cand.r << \" \" << best_cand.c << endl;\n    }\n}\n\n// Phase 3: Retrieve all containers in a greedy fashion\nvoid solve_retrieval() {\n    for (int k = 0; k < C; ++k) {\n        set<int> accessible_containers;\n        queue<pair<int, int>> q;\n        vector<vector<char>> visited_empty(D_CONST, vector<char>(D_CONST, 0));\n\n        q.push({ENTRANCE_R, ENTRANCE_C});\n        visited_empty[ENTRANCE_R][ENTRANCE_C] = 1;\n\n        while(!q.empty()){\n            auto [r, c] = q.front(); q.pop();\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + DR[i]; int nc = c + DC[i];\n                if (!is_valid(nr, nc)) continue;\n                if (grid[nr][nc] >= 0) {\n                    accessible_containers.insert(grid[nr][nc]);\n                } else if ((grid[nr][nc] == -3 || grid[nr][nc] == -2) && !visited_empty[nr][nc]) {\n                    visited_empty[nr][nc] = 1; q.push({nr, nc});\n                }\n            }\n        }\n        \n        if (accessible_containers.empty()) break;\n        int min_t = *accessible_containers.begin();\n        auto [qr, qc] = container_locs[min_t];\n        cout << qr << \" \" << qc << endl;\n        grid[qr][qc] = -3;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    cin >> D_input >> N;\n    precompute();\n    solve_placement();\n    solve_retrieval();\n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <set>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <queue>\n#include <tuple>\n\n// Constants\nconstexpr int N = 50;\nconstexpr int M = 100;\n\n// Randomness\nstruct Xoroshiro128 {\n    uint64_t s[2];\n\n    Xoroshiro128() {\n        std::random_device rd;\n        s[0] = ((uint64_t)rd() << 32) | rd();\n        s[1] = ((uint64_t)rd() << 32) | rd();\n    }\n\n    static inline uint64_t rotl(const uint64_t x, int k) {\n        return (x << k) | (x >> (64 - k));\n    }\n\n    uint64_t next() {\n        const uint64_t s0 = s[0];\n        uint64_t s1 = s[1];\n        const uint64_t result = s0 + s1;\n\n        s1 ^= s0;\n        s[0] = rotl(s0, 24) ^ s1 ^ (s1 << 16);\n        s[1] = rotl(s1, 37);\n\n        return result;\n    }\n\n    double next_double() {\n        return (double)(next() >> 11) * (1.0 / (1LL << 53));\n    }\n};\n\nXoroshiro128 rng;\n\n// Timer\nclass Timer {\npublic:\n    Timer() : start_time(std::chrono::high_resolution_clock::now()) {}\n\n    double get_elapsed_sec() {\n        auto now = std::chrono::high_resolution_clock::now();\n        return std::chrono::duration_cast<std::chrono::duration<double>>(now - start_time).count();\n    }\nprivate:\n    std::chrono::time_point<std::chrono::high_resolution_clock> start_time;\n};\n\n// Data structures\nstruct Point {\n    int r, c;\n};\n\nstruct Vec2d {\n    double x, y;\n};\n\n// Globals for problem data\nstd::vector<std::vector<bool>> adj;\nstd::vector<std::vector<int>> initial_grid;\n\nvoid read_input() {\n    int n_dummy, m_dummy;\n    std::cin >> n_dummy >> m_dummy;\n    initial_grid.assign(N, std::vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            std::cin >> initial_grid[i][j];\n        }\n    }\n}\n\nvoid build_adj() {\n    adj.assign(M + 1, std::vector<bool>(M + 1, false));\n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            if (r == 0 || r == N - 1 || c == 0 || c == N - 1) {\n                adj[initial_grid[r][c]][0] = adj[0][initial_grid[r][c]] = true;\n            }\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + dr[i];\n                int nc = c + dc[i];\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                    int c1 = initial_grid[r][c];\n                    int c2 = initial_grid[nr][nc];\n                    if (c1 != c2) {\n                        adj[c1][c2] = adj[c2][c1] = true;\n                    }\n                }\n            }\n        }\n    }\n}\n\nstruct Solution {\n    std::vector<std::vector<int>> grid;\n    int score;\n\n    Solution() : grid(N, std::vector<int>(N, 0)), score(0) {}\n\n    void calculate_score() {\n        int empty_count = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (grid[i][j] == 0) {\n                    empty_count++;\n                }\n            }\n        }\n        score = empty_count + 1;\n    }\n\n    void print() {\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                std::cout << grid[i][j] << (j == N - 1 ? \"\" : \" \");\n            }\n            std::cout << std::endl;\n        }\n    }\n};\n\nclass Solver {\npublic:\n    Solver(const Timer& timer) : timer(timer) {}\n\n    Solution solve() {\n        Solution best_solution;\n        best_solution.score = -1;\n\n        while(timer.get_elapsed_sec() < 1.95) {\n            Solution current_solution = generate_solution();\n            if (current_solution.score > best_solution.score) {\n                best_solution = current_solution;\n            }\n        }\n        return best_solution;\n    }\n\nprivate:\n    const Timer& timer;\n    std::vector<std::vector<int>> grid;\n    std::vector<Point> seed_pos;\n\n    Solution generate_solution() {\n        std::vector<Vec2d> positions = force_directed_layout();\n        grid.assign(N, std::vector<int>(N, 0));\n        seed_pos.assign(M + 1, {-1, -1});\n        place_seeds(positions);\n        connect_regions();\n        \n        Solution sol;\n        sol.grid = grid;\n        sol.calculate_score();\n        return sol;\n    }\n\n    std::vector<Vec2d> force_directed_layout() {\n        std::vector<Vec2d> pos(M + 1);\n        for (int i = 1; i <= M; ++i) {\n            pos[i] = {rng.next_double() * N, rng.next_double() * N};\n        }\n\n        double temp = N / 4.0;\n        const int iterations = 150;\n        const double k_attr = 0.1, k_rep = 150.0;\n        const double border_rep = 200.0;\n\n        for (int iter = 0; iter < iterations; ++iter) {\n            if (timer.get_elapsed_sec() > 1.95) break;\n\n            std::vector<Vec2d> forces(M + 1, {0.0, 0.0});\n            for (int i = 1; i <= M; ++i) {\n                for (int j = i + 1; j <= M; ++j) {\n                    Vec2d diff = {pos[j].x - pos[i].x, pos[j].y - pos[i].y};\n                    double dist_sq = diff.x * diff.x + diff.y * diff.y + 1e-6;\n                    double dist = std::sqrt(dist_sq);\n                    \n                    if (adj[i][j]) {\n                        double f = k_attr * (dist - N/10.0);\n                        forces[i].x += f * diff.x / dist;\n                        forces[i].y += f * diff.y / dist;\n                        forces[j].x -= f * diff.x / dist;\n                        forces[j].y -= f * diff.y / dist;\n                    } else {\n                        double f = k_rep / dist_sq;\n                        forces[i].x -= f * diff.x / dist;\n                        forces[i].y -= f * diff.y / dist;\n                        forces[j].x += f * diff.x / dist;\n                        forces[j].y += f * diff.y / dist;\n                    }\n                }\n            }\n\n            for (int i = 1; i <= M; ++i) {\n                 if (!adj[i][0]) {\n                    forces[i].x += border_rep / (pos[i].x * pos[i].x + 1e-6);\n                    forces[i].y += border_rep / (pos[i].y * pos[i].y + 1e-6);\n                    forces[i].x -= border_rep / ((N-1 - pos[i].x) * (N-1 - pos[i].x) + 1e-6);\n                    forces[i].y -= border_rep / ((N-1 - pos[i].y) * (N-1 - pos[i].y) + 1e-6);\n                }\n            }\n\n            for (int i = 1; i <= M; ++i) {\n                double force_mag = std::sqrt(forces[i].x * forces[i].x + forces[i].y * forces[i].y) + 1e-6;\n                pos[i].x += temp * forces[i].x / force_mag;\n                pos[i].y += temp * forces[i].y / force_mag;\n                pos[i].x = std::max(1.0, std::min((double)N - 2, pos[i].x));\n                pos[i].y = std::max(1.0, std::min((double)N - 2, pos[i].y));\n            }\n            temp *= 0.98;\n        }\n        return pos;\n    }\n\n    void place_seeds(const std::vector<Vec2d>& pos) {\n        std::vector<int> p(M);\n        std::iota(p.begin(), p.end(), 1);\n        auto mt = std::mt19937(rng.next());\n        std::shuffle(p.begin(), p.end(), mt);\n\n        for (int color : p) {\n            int target_r = std::round(pos[color].y);\n            int target_c = std::round(pos[color].x);\n\n            int best_r = -1, best_c = -1;\n            for (int d = 0; d < N; ++d) {\n                for(int i = -d; i <= d; ++i) {\n                    int j = d - std::abs(i);\n                    int r_offsets[] = {i, i};\n                    int c_offsets[] = {j, -j};\n                    for (int k = 0; k < 2; ++k) {\n                        int r = target_r + r_offsets[k];\n                        int c = target_c + c_offsets[k];\n                        if (r < 0 || r >= N || c < 0 || c >= N) continue;\n                        if (is_valid_placement(color, r, c)) {\n                            best_r = r; best_c = c; goto found_pos;\n                        }\n                    }\n                }\n            }\n            found_pos:;\n            if (best_r != -1) {\n                grid[best_r][best_c] = color;\n                seed_pos[color] = {best_r, best_c};\n            }\n        }\n    }\n\n    bool is_valid_placement(int color, int r, int c) {\n        if (grid[r][c] != 0) return false;\n        if (!adj[color][0] && (r == 0 || r == N - 1 || c == 0 || c == N - 1)) return false;\n        \n        int dr[] = {-1, 1, 0, 0};\n        int dc[] = {0, 0, -1, 1};\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i], nc = c + dc[i];\n            if (nr >= 0 && nr < N && nc >= 0 && nc < N && grid[nr][nc] != 0) {\n                if (!adj[color][grid[nr][nc]]) return false;\n            }\n        }\n        return true;\n    }\n\n    void connect_regions() {\n        std::vector<std::pair<int, int>> reqs;\n        for (int i = 1; i <= M; ++i) for (int j = i + 1; j <= M; ++j) if (adj[i][j]) reqs.push_back({i, j});\n        auto mt = std::mt19937(rng.next());\n        std::shuffle(reqs.begin(), reqs.end(), mt);\n        \n        std::vector<std::vector<bool>> satisfied_adj(M + 1, std::vector<bool>(M + 1, false));\n\n        for (const auto& p : reqs) {\n            if (timer.get_elapsed_sec() > 1.95) break;\n            \n            bool is_adj = false;\n            int c1 = p.first, c2 = p.second;\n            if(seed_pos[c1].r == -1 || seed_pos[c2].r == -1) continue;\n            for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) {\n                if(grid[r][c]==c1) {\n                    int dr[]={-1,1,0,0}, dc[]={0,0,-1,1};\n                    for(int i=0;i<4;++i) {\n                        int nr=r+dr[i], nc=c+dc[i];\n                        if(nr>=0 && nr<N && nc>=0 && nc<N && grid[nr][nc]==c2) { is_adj=true; goto end_check; }\n                    }\n                }\n            }\n            end_check:;\n\n            if (!is_adj) connect_pair(p.first, p.second);\n        }\n        \n        for (int i = 1; i <= M; ++i) {\n            if (timer.get_elapsed_sec() > 1.95) break;\n            if (adj[i][0]) {\n                 bool is_adj_to_0 = false;\n                 for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) {\n                    if (grid[r][c] == i && (r==0 || r==N-1 || c==0 || c==N-1)) {\n                        is_adj_to_0 = true; break;\n                    }\n                 }\n                 if(!is_adj_to_0) connect_to_border(i);\n            }\n        }\n    }\n\n    void connect_pair(int c1, int c2) {\n        using State = std::tuple<int, int, int>;\n        std::priority_queue<State, std::vector<State>, std::greater<State>> pq;\n        std::vector<std::vector<int>> dist(N, std::vector<int>(N, 1e9));\n        std::vector<std::vector<Point>> parent(N, std::vector<Point>(N, {-1, -1}));\n\n        for (int r = 0; r < N; ++r) for (int c = 0; c < N; ++c) {\n            if (grid[r][c] == c1) { pq.emplace(0, r, c); dist[r][c] = 0; }\n        }\n\n        const int PENALTY = N*N;\n        int dr[] = {-1, 1, 0, 0}; int dc[] = {0, 0, -1, 1};\n        Point end_pos = {-1, -1};\n\n        while (!pq.empty()) {\n            auto [d, r, c] = pq.top(); pq.pop();\n            if (d > dist[r][c]) continue;\n\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + dr[i], nc = c + dc[i];\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N && grid[nr][nc] == c2) {\n                    end_pos = {r, c}; goto path_found;\n                }\n            }\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + dr[i], nc = c + dc[i];\n                if (nr < 0 || nr >= N || nc < 0 || nc >= N || (grid[nr][nc] != 0 && grid[nr][nc] != c1)) continue;\n                int cost = 1, penalty = 0;\n                for (int j = 0; j < 4; ++j) {\n                    int nnr = nr + dr[j], nnc = nc + dc[j];\n                    if (nnr < 0 || nnr >= N || nnc < 0 || nnc >= N) continue;\n                    int neighbor_color = grid[nnr][nnc];\n                    if (neighbor_color != 0 && neighbor_color != c1 && !adj[c1][neighbor_color]) penalty += PENALTY;\n                }\n                if (dist[nr][nc] > d + cost + penalty) {\n                    dist[nr][nc] = d + cost + penalty; parent[nr][nc] = {r, c}; pq.emplace(dist[nr][nc], nr, nc);\n                }\n            }\n        }\n    path_found:\n        if (end_pos.r != -1) {\n            Point curr = end_pos;\n            while (grid[curr.r][curr.c] == 0) {\n                grid[curr.r][curr.c] = c1; curr = parent[curr.r][curr.c];\n            }\n        }\n    }\n\n    void connect_to_border(int c1) {\n        if (seed_pos[c1].r == -1) return;\n        using State = std::tuple<int, int, int>;\n        std::priority_queue<State, std::vector<State>, std::greater<State>> pq;\n        std::vector<std::vector<int>> dist(N, std::vector<int>(N, 1e9));\n        std::vector<std::vector<Point>> parent(N, std::vector<Point>(N, {-1, -1}));\n\n        for (int r = 0; r < N; ++r) for (int c = 0; c < N; ++c) {\n            if (grid[r][c] == c1) { pq.emplace(0, r, c); dist[r][c] = 0; }\n        }\n        \n        const int PENALTY = N*N;\n        int dr[] = {-1, 1, 0, 0}; int dc[] = {0, 0, -1, 1};\n        Point end_pos = {-1, -1};\n\n        while (!pq.empty()) {\n            auto [d, r, c] = pq.top(); pq.pop();\n            if (d > dist[r][c]) continue;\n            if (r == 0 || r == N - 1 || c == 0 || c == N - 1) { end_pos = {r, c}; break; }\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + dr[i], nc = c + dc[i];\n                if (nr < 0 || nr >= N || nc < 0 || nc >= N || (grid[nr][nc] != 0 && grid[nr][nc] != c1)) continue;\n                int cost = 1, penalty = 0;\n                for (int j = 0; j < 4; ++j) {\n                    int nnr = nr + dr[j], nnc = nc + dc[j];\n                    if (nnr < 0 || nnr >= N || nnc < 0 || nnc >= N) continue;\n                    int neighbor_color = grid[nnr][nnc];\n                    if (neighbor_color != 0 && neighbor_color != c1 && !adj[c1][neighbor_color]) penalty += PENALTY;\n                }\n                if (!adj[c1][0] && (nr==0 || nr==N-1 || nc==0 || nc==N-1)) penalty += PENALTY;\n                if (dist[nr][nc] > d + cost + penalty) {\n                    dist[nr][nc] = d + cost + penalty; parent[nr][nc] = {r, c}; pq.emplace(dist[nr][nc], nr, nc);\n                }\n            }\n        }\n        if (end_pos.r != -1) {\n            Point curr = end_pos;\n            while (grid[curr.r][curr.c] == 0) {\n                grid[curr.r][curr.c] = c1; curr = parent[curr.r][curr.c];\n            }\n        }\n    }\n};\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    Timer timer;\n\n    read_input();\n    build_adj();\n\n    Solver solver(timer);\n    Solution best_solution = solver.solve();\n    \n    best_solution.print();\n\n    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n\n// --- Utilities ---\nstruct Timer {\n    std::chrono::high_resolution_clock::time_point start_time;\n    Timer() {\n        start_time = std::chrono::high_resolution_clock::now();\n    }\n    long long get_elapsed_ms() const {\n        auto now = std::chrono::high_resolution_clock::now();\n        return std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time).count();\n    }\n};\n\nstd::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// --- Problem specific globals ---\nint N, D, Q;\nconst int NUM_PARTICLES = 2500;\nstd::vector<std::vector<long long>> particles;\ndouble W_CAP;\n\n// --- Query interaction ---\nchar query(const std::vector<int>& L, const std::vector<int>& R) {\n    if (L.empty() || R.empty()) {\n        return '=';\n    }\n    std::cout << L.size() << \" \" << R.size();\n    for (int x : L) std::cout << \" \" << x;\n    for (int x : R) std::cout << \" \" << x;\n    std::cout << std::endl;\n    char res;\n    std::cin >> res;\n    return res;\n}\n\n// --- Particle management ---\nvoid generate_particles() {\n    particles.clear();\n    std::uniform_real_distribution<double> unif(0.0, 1.0);\n    const double lambda = 1e-5;\n\n    particles.reserve(NUM_PARTICLES);\n    for (int i = 0; i < NUM_PARTICLES; ++i) {\n        std::vector<long long> weights(N);\n        for (int j = 0; j < N; ++j) {\n            double w_prime;\n            do {\n                double u = std::max(1e-9, unif(rng)); // Avoid log(0)\n                w_prime = -log(u) / lambda;\n            } while (w_prime > W_CAP);\n            weights[j] = std::max(1LL, (long long)round(w_prime));\n        }\n        particles.push_back(weights);\n    }\n}\n\nvoid filter_particles(const std::vector<int>& L, const std::vector<int>& R, char result) {\n    std::vector<std::vector<long long>> next_particles;\n    next_particles.reserve(particles.size());\n    for (const auto& p : particles) {\n        long long sum_L = 0, sum_R = 0;\n        for (int i : L) sum_L += p[i];\n        for (int i : R) sum_R += p[i];\n        \n        bool consistent = false;\n        if (result == '<' && sum_L < sum_R) consistent = true;\n        else if (result == '>' && sum_L > sum_R) consistent = true;\n        else if (result == '=' && sum_L == sum_R) consistent = true;\n        \n        if (consistent) {\n            next_particles.push_back(p);\n        }\n    }\n    if (!next_particles.empty()) {\n        particles = std::move(next_particles);\n    }\n}\n\nstd::vector<double> get_estimated_weights() {\n    std::vector<double> avg_weights(N, 0.0);\n    if (particles.empty()) {\n        for(int i=0; i<N; ++i) avg_weights[i] = 1.0;\n        return avg_weights;\n    }\n    int p_count = particles.size();\n    for (int i = 0; i < N; ++i) {\n        double total = 0;\n        for (const auto& p : particles) {\n            total += p[i];\n        }\n        avg_weights[i] = total / p_count;\n    }\n    return avg_weights;\n}\n\n// --- Main logic ---\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    Timer timer;\n\n    std::cin >> N >> D >> Q;\n    W_CAP = 1e5 * N / D;\n\n    generate_particles();\n\n    int queries_made = 0;\n\n    // Phase 1: Sorting queries\n    int num_sort_queries = Q * 2 / 5;\n    \n    std::vector<std::pair<int, int>> pairs;\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            pairs.push_back({i, j});\n        }\n    }\n    std::shuffle(pairs.begin(), pairs.end(), rng);\n\n    for (int i = 0; i < num_sort_queries && i < (int)pairs.size() && queries_made < Q; ++i) {\n        auto [u, v] = pairs[i];\n        char res = query({u}, {v});\n        filter_particles({u}, {v}, res);\n        queries_made++;\n    }\n\n    // Phase 2: Hybrid magnitude queries\n    int magnitude_queries_count = 0;\n    int one_vs_many_cycle = 0;\n    while (queries_made < Q) {\n        auto estimated_weights = get_estimated_weights();\n        std::vector<int> p(N);\n        std::iota(p.begin(), p.end(), 0);\n        std::sort(p.begin(), p.end(), [&](int i, int j) {\n            return estimated_weights[i] < estimated_weights[j];\n        });\n\n        if (magnitude_queries_count % 4 == 0 && N > 1) {\n            // Query type: Balanced groups of all items\n            std::vector<int> L, R;\n            double sum_L = 0, sum_R = 0;\n            for (int i = N - 1; i >= 0; --i) {\n                int item_idx = p[i];\n                if (sum_L <= sum_R) {\n                    L.push_back(item_idx);\n                    sum_L += estimated_weights[item_idx];\n                } else {\n                    R.push_back(item_idx);\n                    sum_R += estimated_weights[item_idx];\n                }\n            }\n            char res = query(L, R);\n            filter_particles(L, R, res);\n        } else {\n            // Query type: Cycling \"One vs. Many\"\n            int k_idx = (N - 1) - (one_vs_many_cycle % (std::max(1, N - 1)));\n            int item_k = p[k_idx];\n\n            std::vector<double> prefix_sum_w(k_idx, 0.0);\n            if (k_idx > 0) {\n                prefix_sum_w[0] = estimated_weights[p[0]];\n                for (int i = 1; i < k_idx; ++i) {\n                    prefix_sum_w[i] = prefix_sum_w[i-1] + estimated_weights[p[i]];\n                }\n            }\n            \n            auto it = std::upper_bound(prefix_sum_w.begin(), prefix_sum_w.end(), estimated_weights[item_k]);\n            int j_idx = std::distance(prefix_sum_w.begin(), it);\n            if (j_idx > 0 && j_idx < k_idx) {\n                if (std::abs(prefix_sum_w[j_idx] - estimated_weights[item_k]) > std::abs(prefix_sum_w[j_idx-1] - estimated_weights[item_k])) {\n                    j_idx--;\n                }\n            }\n            j_idx = std::max(0, std::min(k_idx - 1, j_idx));\n            \n            std::vector<int> L = {item_k};\n            std::vector<int> R;\n            for (int i = 0; i <= j_idx; ++i) {\n                R.push_back(p[i]);\n            }\n            \n            if (!R.empty()) {\n                char res = query(L, R);\n                filter_particles(L, R, res);\n            } else if (N > 1) {\n                char res = query({item_k}, {p[k_idx == 0 ? 1 : 0]});\n                filter_particles({item_k}, {p[k_idx == 0 ? 1 : 0]}, res);\n            }\n            one_vs_many_cycle++;\n        }\n        queries_made++;\n        magnitude_queries_count++;\n    }\n\n    // Partitioning phase\n    auto final_weights = get_estimated_weights();\n    std::vector<long long> scaled_weights(N);\n    double scale_factor = 10000.0;\n    for(int i=0; i<N; ++i) {\n        scaled_weights[i] = std::max(1LL, (long long)round(final_weights[i] * scale_factor));\n    }\n\n    // Initial solution using LPT greedy algorithm\n    std::vector<int> p_part(N);\n    std::iota(p_part.begin(), p_part.end(), 0);\n    std::sort(p_part.begin(), p_part.end(), [&](int i, int j) {\n        return scaled_weights[i] > scaled_weights[j];\n    });\n\n    std::vector<int> assignment(N);\n    using int128 = __int128_t;\n    std::vector<int128> set_sums(D, 0);\n    \n    for (int item_idx : p_part) {\n        if (D > 0) {\n            auto min_it = std::min_element(set_sums.begin(), set_sums.end());\n            int best_set = std::distance(set_sums.begin(), min_it);\n            assignment[item_idx] = best_set;\n            set_sums[best_set] += scaled_weights[item_idx];\n        }\n    }\n    \n    // Simulated Annealing\n    std::vector<int128> current_set_sums = set_sums;\n    std::vector<int> current_assignment = assignment;\n    \n    int128 current_score = 0;\n    for(auto s : current_set_sums) current_score += s*s;\n\n    auto best_assignment = current_assignment;\n    int128 best_score = current_score;\n\n    long double start_temp = 1.0;\n    if (N > 0 && D > 1) {\n        long double total_worsening_delta = 0;\n        int worsening_moves = 0;\n        for (int i = 0; i < 100; ++i) {\n            int item_idx = rng() % N;\n            int d1 = current_assignment[item_idx];\n            int d2;\n            do { d2 = rng() % D; } while (d1 == d2);\n            \n            int128 w = scaled_weights[item_idx];\n            int128 s1 = current_set_sums[d1];\n            int128 s2 = current_set_sums[d2];\n            int128 delta = (s1-w)*(s1-w) + (s2+w)*(s2+w) - s1*s1 - s2*s2;\n            if (delta > 0) {\n                total_worsening_delta += (long double)delta;\n                worsening_moves++;\n            }\n        }\n        if (worsening_moves > 0) {\n            long double avg_worsening_delta = total_worsening_delta / worsening_moves;\n            long double initial_accept_prob = 0.5;\n            start_temp = -avg_worsening_delta / log(initial_accept_prob);\n        }\n    }\n\n    long long time_limit = 1950;\n    \n    while(D > 1) {\n        long long elapsed_ms = timer.get_elapsed_ms();\n        if (elapsed_ms >= time_limit) break;\n\n        long double elapsed_ratio = (long double)elapsed_ms / time_limit;\n        long double temp = start_temp * (1.0 - elapsed_ratio);\n        if (temp < 1e-9) temp = 1e-9;\n        \n        if (rng() % 4 != 0) { // Move (75% total)\n            int item_idx = -1;\n            int d1 = -1;\n\n            if (rng() % 2 == 0) { // Targeted Move (37.5%)\n                auto max_it = std::max_element(current_set_sums.begin(), current_set_sums.end());\n                d1 = std::distance(current_set_sums.begin(), max_it);\n                \n                std::vector<int> candidates;\n                candidates.reserve(N);\n                for(int i=0; i<N; ++i) { if(current_assignment[i] == d1) candidates.push_back(i); }\n                if(candidates.empty()) continue;\n                item_idx = candidates[rng() % candidates.size()];\n            } else { // Simple Move (37.5%)\n                item_idx = rng() % N;\n                d1 = current_assignment[item_idx];\n            }\n            \n            int d2;\n            do { d2 = rng() % D; } while (d1 == d2);\n\n            int128 w = scaled_weights[item_idx];\n            int128 s1 = current_set_sums[d1];\n            int128 s2 = current_set_sums[d2];\n            int128 new_score = current_score - s1*s1 - s2*s2 + (s1 - w)*(s1 - w) + (s2 + w)*(s2 + w);\n            \n            if (new_score < current_score || std::uniform_real_distribution<long double>(0,1)(rng) < expl((long double)(current_score - new_score) / temp)) {\n                current_assignment[item_idx] = d2;\n                current_set_sums[d1] -= w;\n                current_set_sums[d2] += w;\n                current_score = new_score;\n                if (current_score < best_score) {\n                    best_score = current_score;\n                    best_assignment = current_assignment;\n                }\n            }\n        } else { // Swap (25%)\n            if (N < 2) continue;\n            int item1_idx = rng() % N;\n            int item2_idx;\n            do { item2_idx = rng() % N; } while (item1_idx == item2_idx);\n\n            int d1 = current_assignment[item1_idx];\n            int d2 = current_assignment[item2_idx];\n            if (d1 == d2) continue;\n\n            int128 w1 = scaled_weights[item1_idx];\n            int128 w2 = scaled_weights[item2_idx];\n            int128 s1 = current_set_sums[d1];\n            int128 s2 = current_set_sums[d2];\n            int128 new_score = current_score - s1*s1 - s2*s2 + (s1 - w1 + w2)*(s1 - w1 + w2) + (s2 - w2 + w1)*(s2 - w2 + w1);\n\n            if (new_score < current_score || std::uniform_real_distribution<long double>(0,1)(rng) < expl((long double)(current_score - new_score) / temp)) {\n                std::swap(current_assignment[item1_idx], current_assignment[item2_idx]);\n                current_set_sums[d1] = s1 - w1 + w2;\n                current_set_sums[d2] = s2 - w2 + w1;\n                current_score = new_score;\n                if (current_score < best_score) {\n                    best_score = current_score;\n                    best_assignment = current_assignment;\n                }\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        std::cout << best_assignment[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    std::cout << std::endl;\n\n    return 0;\n}","ahc026":"#include <iostream>\n#include <vector>\n#include <array>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <cmath>\n\nusing namespace std;\n\n// Constants for the problem\nconst int N = 200;\nconst int M = 10;\nconst double TIME_LIMIT_MS = 1950.0;\n\n// Beam width parameters, pushed to a very high limit.\nconst int INITIAL_BEAM_WIDTH = 1200;\nconst int FINAL_BEAM_WIDTH = 120;\n\n// Used to scale the primary heuristic so the tie-breaker doesn't interfere.\nconst double PRIMARY_HEURISTIC_SCALE = N + 1;\n\nstruct State {\n    array<vector<int>, M> stacks;\n    array<pair<int, int>, N + 1> box_pos; // {stack_idx, height_from_bottom}\n    long long cost = 0;\n    double eval_score = 0.0;\n    \n    // History tracing to avoid copying large vectors, enabling a wider beam.\n    int parent_idx = -1;\n    char num_ops = 0;\n    pair<int, int> op1{0,0}, op2{0,0};\n\n    State() {\n        for(int i=0; i<=N; ++i) box_pos[i] = {-1, -1};\n    }\n    \n    // The final heuristic combines the pure A* score with a minor tie-breaker.\n    void evaluate(int v_start) {\n        // h1: Heuristic for future unblocking cost (primary heuristic).\n        double h1 = 0;\n        for (int v = v_start; v <= N; ++v) {\n            if (box_pos[v].first != -1) {\n                int stack_idx = box_pos[v].first;\n                int height = box_pos[v].second;\n                int boxes_on_top = stacks[stack_idx].size() - height - 1;\n                if (boxes_on_top > 0) {\n                    h1 += boxes_on_top + 1;\n                }\n            }\n        }\n        \n        // h_inv: Penalty for adjacent inversions (serves as a tie-breaker).\n        double h_inv = 0;\n        for (int i = 0; i < M; ++i) {\n            for (size_t j = 0; j + 1 < stacks[i].size(); ++j) {\n                if (stacks[i][j] > stacks[i][j + 1]) {\n                    h_inv += 1.0;\n                }\n            }\n        }\n\n        eval_score = (cost + h1) * PRIMARY_HEURISTIC_SCALE + h_inv;\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    auto start_time = chrono::high_resolution_clock::now();\n\n    int n_in, m_in;\n    cin >> n_in >> m_in;\n\n    State initial_state;\n    for (int i = 0; i < M; ++i) {\n        initial_state.stacks[i].resize(N / M);\n        for (int j = 0; j < N / M; ++j) {\n            int b;\n            cin >> b;\n            initial_state.stacks[i][j] = b;\n            initial_state.box_pos[b] = {i, j};\n        }\n    }\n\n    vector<vector<State>> beam_history;\n    beam_history.reserve(N + 1);\n    beam_history.push_back({initial_state});\n\n    for (int v_to_carry = 1; v_to_carry <= N; ++v_to_carry) {\n        double elapsed_ms = chrono::duration<double, milli>(chrono::high_resolution_clock::now() - start_time).count();\n        \n        int current_beam_width;\n        if (elapsed_ms >= TIME_LIMIT_MS) {\n            current_beam_width = 1;\n        } else {\n            double time_ratio = elapsed_ms / TIME_LIMIT_MS;\n            // Quadratic decay keeps the beam wider for longer.\n            double decay_factor = time_ratio * time_ratio;\n            current_beam_width = static_cast<int>(INITIAL_BEAM_WIDTH - (INITIAL_BEAM_WIDTH - FINAL_BEAM_WIDTH) * decay_factor);\n            current_beam_width = max(1, current_beam_width);\n        }\n        \n        vector<State> candidates;\n        candidates.reserve(beam_history.back().size() * 3);\n        \n        const auto& prev_beam = beam_history.back();\n        for (size_t p_idx = 0; p_idx < prev_beam.size(); ++p_idx) {\n            const auto& s = prev_beam[p_idx];\n            int stack_idx = s.box_pos[v_to_carry].first;\n            int height = s.box_pos[v_to_carry].second;\n            \n            if (s.stacks[stack_idx].size() - 1 == height) { // is on top\n                State next_s = s;\n                int box_v = next_s.stacks[stack_idx].back();\n                next_s.stacks[stack_idx].pop_back();\n                next_s.box_pos[box_v] = {-1, -1};\n                next_s.parent_idx = p_idx;\n                next_s.num_ops = 1;\n                next_s.op1 = {box_v, 0};\n                next_s.evaluate(v_to_carry + 1);\n                candidates.push_back(move(next_s));\n            } else { // not on top, must move\n                int move_v = s.stacks[stack_idx][height + 1];\n                vector<int> dest_options;\n                array<bool, M> used_dest{};\n                {\n                    // 1. Find an empty stack\n                    int empty_idx = -1;\n                    for (int i = 0; i < M; ++i) if (s.stacks[i].empty()) { empty_idx = i; break; }\n                    if (empty_idx != -1) { dest_options.push_back(empty_idx); used_dest[empty_idx] = true; }\n\n                    // 2. Find the shortest non-empty stack\n                    int shortest_idx = -1, min_size = N + 2;\n                    for (int i = 0; i < M; ++i) {\n                        if (i == stack_idx || s.stacks[i].empty()) continue;\n                        if ((int)s.stacks[i].size() < min_size) { min_size = s.stacks[i].size(); shortest_idx = i; }\n                    }\n                    if (shortest_idx != -1 && !used_dest[shortest_idx]) { dest_options.push_back(shortest_idx); used_dest[shortest_idx] = true; }\n\n                    // 3. Find stack with largest top element\n                    int largest_top_idx = -1, max_top = -1;\n                    for (int i = 0; i < M; ++i) {\n                        if (i == stack_idx || s.stacks[i].empty()) continue;\n                        if (s.stacks[i].back() > max_top) { max_top = s.stacks[i].back(); largest_top_idx = i; }\n                    }\n                    if (largest_top_idx != -1 && !used_dest[largest_top_idx]) { dest_options.push_back(largest_top_idx); }\n                    \n                    if (dest_options.empty()) for (int i = 0; i < M; ++i) if (i != stack_idx) { dest_options.push_back(i); break; }\n                }\n\n                for (int dest_idx : dest_options) {\n                    State next_s = s;\n                    auto& src_stack = next_s.stacks[stack_idx];\n                    vector<int> moved_boxes(src_stack.begin() + height + 1, src_stack.end());\n                    src_stack.resize(height + 1);\n                    next_s.cost += moved_boxes.size() + 1;\n                    auto& dest_stack = next_s.stacks[dest_idx];\n                    size_t old_dest_size = dest_stack.size();\n                    dest_stack.insert(dest_stack.end(), moved_boxes.begin(), moved_boxes.end());\n                    for (size_t i = 0; i < moved_boxes.size(); ++i) next_s.box_pos[moved_boxes[i]] = {dest_idx, (int)(old_dest_size + i)};\n                    int box_v = next_s.stacks[stack_idx].back();\n                    next_s.stacks[stack_idx].pop_back();\n                    next_s.box_pos[box_v] = {-1, -1};\n                    next_s.parent_idx = p_idx;\n                    next_s.num_ops = 2;\n                    next_s.op1 = {move_v, dest_idx + 1};\n                    next_s.op2 = {box_v, 0};\n                    next_s.evaluate(v_to_carry + 1);\n                    candidates.push_back(move(next_s));\n                }\n            }\n        }\n\n        // Key Optimization: Use nth_element instead of sort for O(K) selection.\n        if (candidates.size() > (size_t)current_beam_width) {\n            nth_element(candidates.begin(), candidates.begin() + current_beam_width, candidates.end(), \n                        [](const auto& a, const auto& b) {\n                return a.eval_score < b.eval_score;\n            });\n            candidates.resize(current_beam_width);\n        }\n\n        beam_history.push_back(move(candidates));\n    }\n    \n    const auto& final_beam = beam_history.back();\n    int best_final_idx = 0;\n    if (!final_beam.empty()) {\n        for(size_t i = 1; i < final_beam.size(); ++i) {\n            if(final_beam[i].cost < final_beam[best_final_idx].cost) {\n                best_final_idx = i;\n            }\n        }\n    }\n\n    vector<pair<int, int>> final_ops;\n    int current_beam_level = beam_history.size() - 1;\n    while(current_beam_level > 0) {\n        if(beam_history[current_beam_level].empty()) { break; } // Failsafe\n        const auto& s = beam_history[current_beam_level][best_final_idx];\n        if (s.num_ops >= 2) final_ops.push_back(s.op2);\n        if (s.num_ops >= 1) final_ops.push_back(s.op1);\n        best_final_idx = s.parent_idx;\n        current_beam_level--;\n    }\n    reverse(final_ops.begin(), final_ops.end());\n\n    for (const auto& op : final_ops) {\n        cout << op.first << \" \" << op.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc027":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <functional>\n#include <list>\n#include <set>\n#include <chrono>\n#include <map>\n#include <unordered_map>\n#include <memory>\n\n// Timer\nauto start_time = std::chrono::high_resolution_clock::now();\ndouble get_time() {\n    return std::chrono::duration_cast<std::chrono::duration<double>>(std::chrono::high_resolution_clock::now() - start_time).count();\n}\n\nstruct Pos {\n    short r, c;\n    bool operator<(const Pos& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n    bool operator==(const Pos& other) const {\n        return r == other.r && c == other.c;\n    }\n};\n\nint N;\nstd::vector<std::string> h_walls, v_walls;\nstd::vector<std::vector<int>> d;\nstd::vector<std::vector<std::vector<Pos>>> adj;\n\n// Randomness\nstd::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\nvoid build_adj() {\n    adj.assign(N, std::vector<std::vector<Pos>>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (i > 0 && h_walls[i - 1][j] == '0') adj[i][j].push_back({(short)(i - 1), (short)j});\n            if (i < N - 1 && h_walls[i][j] == '0') adj[i][j].push_back({(short)(i + 1), (short)j});\n            if (j > 0 && v_walls[i][j - 1] == '0') adj[i][j].push_back({(short)i, (short)(j - 1)});\n            if (j < N - 1 && v_walls[i][j] == '0') adj[i][j].push_back({(short)i, (short)(j + 1)});\n        }\n    }\n}\n\n// Initial path via randomized DFS\nstd::list<Pos> initial_tour;\nstd::vector<std::vector<bool>> visited;\nvoid generate_initial_path_dfs(Pos p) {\n    visited[p.r][p.c] = true;\n    initial_tour.push_back(p);\n    \n    std::vector<Pos> neighbors = adj[p.r][p.c];\n    std::shuffle(neighbors.begin(), neighbors.end(), rng);\n    \n    for (const auto& next_p : neighbors) {\n        if (!visited[next_p.r][next_p.c]) {\n            generate_initial_path_dfs(next_p);\n            initial_tour.push_back(p);\n        }\n    }\n}\n\nstd::string pos_to_moves(const std::list<Pos>& pos_path) {\n    std::string moves;\n    if (pos_path.size() <= 1) return \"\";\n    moves.reserve(pos_path.size() - 1);\n    auto it = pos_path.begin();\n    Pos current = *it;\n    ++it;\n    while (it != pos_path.end()) {\n        Pos next = *it;\n        if (next.r == current.r - 1) moves.push_back('U');\n        else if (next.r == current.r + 1) moves.push_back('D');\n        else if (next.c == current.c - 1) moves.push_back('L');\n        else moves.push_back('R');\n        current = next;\n        ++it;\n    }\n    return moves;\n}\n\n// State for SA\nstruct State {\n    using list_iterator = std::list<Pos>::iterator;\n    \n    struct IteratorHasher {\n        std::size_t operator()(const list_iterator& it) const {\n            return std::hash<const Pos*>()(&*it);\n        }\n    };\n\n    std::list<Pos> tour;\n    std::vector<std::vector<long long>> k;\n    double score_sum_d_div_k;\n\n    // For fast SA moves\n    std::vector<std::vector<std::vector<list_iterator>>> occurrences;\n    std::vector<std::vector<std::unordered_map<list_iterator, int, IteratorHasher>>> occurrences_indices;\n\n    std::vector<list_iterator> detour_centers;\n    std::unordered_map<list_iterator, int, IteratorHasher> detour_centers_indices;\n    \n    State() {\n        k.resize(N, std::vector<long long>(N, 0));\n        occurrences.resize(N, std::vector<std::vector<list_iterator>>(N));\n        occurrences_indices.resize(N, std::vector<std::unordered_map<list_iterator, int, IteratorHasher>>(N));\n    }\n\n    void add_occurrence(const Pos& p, list_iterator it) {\n        occurrences_indices[p.r][p.c][it] = occurrences[p.r][p.c].size();\n        occurrences[p.r][p.c].push_back(it);\n    }\n    void remove_occurrence(const Pos& p, list_iterator it) {\n        int idx_to_remove = occurrences_indices[p.r][p.c].at(it);\n        auto it_last = occurrences[p.r][p.c].back();\n        \n        occurrences[p.r][p.c][idx_to_remove] = it_last;\n        occurrences_indices[p.r][p.c][it_last] = idx_to_remove;\n        \n        occurrences[p.r][p.c].pop_back();\n        occurrences_indices[p.r][p.c].erase(it);\n    }\n\n    void add_detour_center(list_iterator it) {\n        detour_centers_indices[it] = detour_centers.size();\n        detour_centers.push_back(it);\n    }\n    void remove_detour_center(list_iterator it) {\n        auto map_it = detour_centers_indices.find(it);\n        if (map_it == detour_centers_indices.end()) return;\n        int idx_to_remove = map_it->second;\n\n        auto it_last = detour_centers.back();\n        \n        if (it != it_last) {\n            detour_centers[idx_to_remove] = it_last;\n            detour_centers_indices[it_last] = idx_to_remove;\n        }\n\n        detour_centers.pop_back();\n        detour_centers_indices.erase(map_it);\n    }\n    \n    void rebuild_detour_centers() {\n        detour_centers.clear();\n        detour_centers_indices.clear();\n        if (tour.size() < 3) return;\n        auto it1 = tour.begin();\n        auto it2 = std::next(it1);\n        auto it3 = std::next(it2);\n        while(it3 != tour.end()){\n            if (*it1 == *it3) {\n                add_detour_center(it2);\n            }\n            ++it1; ++it2; ++it3;\n        }\n    }\n\n    void init(const std::list<Pos>& initial_tour) {\n        tour = initial_tour;\n        score_sum_d_div_k = 0;\n        for (int i=0; i<N; ++i) for(int j=0; j<N; ++j) k[i][j] = 0;\n\n        for (auto it = tour.begin(); it != tour.end(); ++it) {\n            k[it->r][it->c]++;\n            add_occurrence(*it, it);\n        }\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (k[i][j] > 0) {\n                    score_sum_d_div_k += (double)d[i][j] / k[i][j];\n                }\n            }\n        }\n    }\n    \n    double get_energy() const {\n        if (tour.empty()) return 1e18;\n        return (double)(tour.size() - 1) * score_sum_d_div_k;\n    }\n};\n\ndouble calculate_g(long long count, int dirt) {\n    if (count == 0) return 1e18;\n    return (double)dirt / (count * (count + 1.0));\n}\nstruct PQ_Elem {\n    double score;\n    Pos p;\n    bool operator<(const PQ_Elem& other) const {\n        if (std::abs(score - other.score) > 1e-9) return score < other.score;\n        return p < other.p;\n    }\n};\n\nvoid solve() {\n    build_adj();\n\n    visited.assign(N, std::vector<bool>(N, false));\n    generate_initial_path_dfs({0,0});\n    \n    State state;\n    state.init(initial_tour);\n\n    const int MAX_L = 100000;\n    const double time_limit = 1.98;\n    const double greedy_time_limit = time_limit * 0.5;\n    {\n        std::vector<std::vector<double>> g(N, std::vector<double>(N));\n        std::vector<std::vector<Pos>> best_neighbor(N, std::vector<Pos>(N));\n        std::set<PQ_Elem> pq;\n\n        for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) g[i][j] = calculate_g(state.k[i][j], d[i][j]);\n\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                Pos p = {(short)i, (short)j};\n                double max_g = -1.0; Pos bn = {-1, -1};\n                for (const auto& neighbor : adj[i][j]) {\n                    if (g[neighbor.r][neighbor.c] > max_g) max_g = g[neighbor.r][neighbor.c], bn = neighbor;\n                }\n                best_neighbor[i][j] = bn;\n                if (bn.r != -1) pq.insert({g[i][j] + max_g, p});\n            }\n        }\n        \n        while (get_time() < greedy_time_limit && state.tour.size() + 2 <= MAX_L && !pq.empty()) {\n            PQ_Elem top = *pq.rbegin();\n            Pos u = top.p; Pos v = best_neighbor[u.r][u.c];\n            if (v.r == -1) { pq.erase(std::prev(pq.end())); continue; }\n            \n            int occ_idx = std::uniform_int_distribution<int>(0, state.occurrences[u.r][u.c].size() - 1)(rng);\n            auto it_u_old = state.occurrences[u.r][u.c][occ_idx];\n            auto it_after_u = std::next(it_u_old);\n            auto it_u_new = state.tour.insert(it_after_u, u);\n            auto it_v = state.tour.insert(it_u_new, v);\n            \n            state.score_sum_d_div_k -= ((double)d[u.r][u.c] / state.k[u.r][u.c]) + ((double)d[v.r][v.c] / state.k[v.r][v.c]);\n            state.k[u.r][u.c]++; state.k[v.r][v.c]++;\n            state.score_sum_d_div_k += ((double)d[u.r][u.c] / state.k[u.r][u.c]) + ((double)d[v.r][v.c] / state.k[v.r][v.c]);\n            state.add_occurrence(u, it_u_new); state.add_occurrence(v, it_v);\n\n            std::set<Pos> to_update_pq;\n            to_update_pq.insert(u); to_update_pq.insert(v);\n            for(const auto& n: adj[u.r][u.c]) to_update_pq.insert(n);\n            for(const auto& n: adj[v.r][v.c]) to_update_pq.insert(n);\n            \n            for (const auto& p : to_update_pq) {\n                Pos bn_old = best_neighbor[p.r][p.c];\n                if (bn_old.r != -1) pq.erase({g[p.r][p.c] + g[bn_old.r][bn_old.c], p});\n            }\n            g[u.r][u.c] = calculate_g(state.k[u.r][u.c], d[u.r][u.c]); g[v.r][v.c] = calculate_g(state.k[v.r][v.c], d[v.r][v.c]);\n            for (const auto& p : to_update_pq) {\n                double max_g = -1.0; Pos bn_new = {-1, -1};\n                if (!adj[p.r][p.c].empty()){\n                    for (const auto& n : adj[p.r][p.c]) {\n                        if (g[n.r][n.c] > max_g) max_g = g[n.r][n.c], bn_new = n;\n                    }\n                    best_neighbor[p.r][p.c] = bn_new;\n                    if (bn_new.r != -1) pq.insert({g[p.r][p.c] + max_g, p});\n                }\n            }\n        }\n    }\n\n    state.rebuild_detour_centers();\n\n    double start_temp = 1000, end_temp = 1;\n    double current_energy = state.get_energy();\n    std::uniform_real_distribution<> u_dist(0.0, 1.0);\n    int sa_iter = 0;\n    double temp = start_temp;\n\n    while (true) {\n        sa_iter++;\n        if ((sa_iter & 127) == 0) { // Batch processing\n            double time_now = get_time();\n            if (time_now > time_limit) break;\n            temp = start_temp + (end_temp - start_temp) * time_now / time_limit;\n        }\n        if ((sa_iter & 65535) == 0) {\n            state.rebuild_detour_centers();\n        }\n\n        int move_type = std::uniform_int_distribution<int>(0, 2)(rng);\n\n        if (move_type == 0 && state.tour.size() + 2 <= MAX_L) { // ADD\n            Pos p = {(short)std::uniform_int_distribution<int>(0,N-1)(rng), (short)std::uniform_int_distribution<int>(0,N-1)(rng)};\n            if (state.occurrences[p.r][p.c].empty() || adj[p.r][p.c].empty()) continue;\n            Pos v = adj[p.r][p.c][std::uniform_int_distribution<int>(0, adj[p.r][p.c].size() - 1)(rng)];\n            int occ_idx = std::uniform_int_distribution<int>(0, state.occurrences[p.r][p.c].size() - 1)(rng);\n            auto it_p_old = state.occurrences[p.r][p.c][occ_idx];\n\n            double new_sum_d_div_k = state.score_sum_d_div_k - (double)d[p.r][p.c]/state.k[p.r][p.c] + (double)d[p.r][p.c]/(state.k[p.r][p.c]+1) - (double)d[v.r][v.c]/state.k[v.r][v.c] + (double)d[v.r][v.c]/(state.k[v.r][v.c]+1);\n            double new_energy = (double)(state.tour.size() + 1) * new_sum_d_div_k;\n            double delta_e = new_energy - current_energy;\n\n            if (delta_e < 0 || u_dist(rng) < std::exp(-delta_e / temp)) {\n                auto it_after_p = std::next(it_p_old);\n                auto it_p_new = state.tour.insert(it_after_p, p);\n                auto it_v = state.tour.insert(it_p_new, v);\n                state.score_sum_d_div_k = new_sum_d_div_k;\n                state.k[p.r][p.c]++; state.k[v.r][v.c]++;\n                state.add_occurrence(p, it_p_new); state.add_occurrence(v, it_v); state.add_detour_center(it_v);\n                current_energy = new_energy;\n            }\n        } else if (move_type >= 1 && !state.detour_centers.empty()) { // REMOVE or CHANGE\n            int dc_idx = std::uniform_int_distribution<int>(0, state.detour_centers.size() - 1)(rng);\n            auto it_u = state.detour_centers[dc_idx];\n            if (it_u == state.tour.begin()) { state.remove_detour_center(it_u); continue; }\n            auto it_p1 = std::prev(it_u); auto it_p2 = std::next(it_u);\n\n            if (it_p2 == state.tour.end() || !(*it_p1 == *it_p2)) { state.remove_detour_center(it_u); continue; }\n            Pos u = *it_u, p = *it_p1;\n\n            if (move_type == 1 && state.tour.size() - 2 > (size_t)2 * (N*N-1)) { // REMOVE\n                double new_sum_d_div_k = state.score_sum_d_div_k - (double)d[p.r][p.c]/state.k[p.r][p.c] + (double)d[p.r][p.c]/(state.k[p.r][p.c]-1) - (double)d[u.r][u.c]/state.k[u.r][u.c] + (double)d[u.r][u.c]/(state.k[u.r][u.c]-1);\n                double new_energy = (double)(state.tour.size() - 3) * new_sum_d_div_k;\n                double delta_e = new_energy - current_energy;\n\n                if (delta_e < 0 || u_dist(rng) < std::exp(-delta_e / temp)) {\n                    state.remove_detour_center(it_u); state.remove_detour_center(it_p2);\n                    state.remove_occurrence(u, it_u); state.remove_occurrence(p, it_p2);\n                    state.tour.erase(it_u); state.tour.erase(it_p2);\n                    state.score_sum_d_div_k = new_sum_d_div_k;\n                    state.k[p.r][p.c]--; state.k[u.r][u.c]--;\n                    current_energy = new_energy;\n                }\n            } else if (move_type == 2) { // CHANGE\n                if (adj[p.r][p.c].size() <= 1) continue;\n                Pos v = adj[p.r][p.c][std::uniform_int_distribution<int>(0, adj[p.r][p.c].size() - 1)(rng)];\n                if (v == u) continue;\n\n                double new_sum_d_div_k = state.score_sum_d_div_k - (double)d[u.r][u.c]/state.k[u.r][u.c] + (double)d[u.r][u.c]/(state.k[u.r][u.c]-1) - (double)d[v.r][v.c]/state.k[v.r][v.c] + (double)d[v.r][v.c]/(state.k[v.r][v.c]+1);\n                double new_energy = (double)(state.tour.size() - 1) * new_sum_d_div_k;\n                double delta_e = new_energy - current_energy;\n\n                if (delta_e < 0 || u_dist(rng) < std::exp(-delta_e / temp)) {\n                    state.remove_occurrence(u, it_u); *it_u = v; state.add_occurrence(v, it_u);\n                    state.score_sum_d_div_k = new_sum_d_div_k;\n                    state.k[u.r][u.c]--; state.k[v.r][v.c]++;\n                    current_energy = new_energy;\n                }\n            }\n        }\n    }\n\n    std::string moves = pos_to_moves(state.tour);\n    std::cout << moves << std::endl;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    \n    std::cin >> N;\n    h_walls.resize(N - 1);\n    v_walls.resize(N);\n    d.assign(N, std::vector<int>(N));\n    for (int i = 0; i < N - 1; ++i) std::cin >> h_walls[i];\n    for (int i = 0; i < N; ++i) std::cin >> v_walls[i];\n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) std::cin >> d[i][j];\n    \n    solve();\n    \n    return 0;\n}","ahc028":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <random>\n\nusing namespace std;\n\n// Constants from problem statement\nconst int N_GRID = 15;\nconst int M_TARGETS = 200;\n\n// Global variables for problem input\nint start_r, start_c;\nvector<string> grid(N_GRID);\nvector<string> targets(M_TARGETS);\n\n// Precomputed data structures\nvector<pair<int, int>> char_positions[26];\nint overlaps[M_TARGETS][M_TARGETS];\ndouble avg_transition_cost[26][26];\ndouble weights[M_TARGETS][M_TARGETS];\n\n// Random number generator for SA\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// --- Utility Functions ---\n\ninline int manhattan_distance(const pair<int,int>& p1, const pair<int,int>& p2) {\n    return abs(p1.first - p2.first) + abs(p1.second - p2.second);\n}\n\n// --- Precomputation Functions ---\n\nvoid read_input() {\n    int n_in, m_in;\n    cin >> n_in >> m_in;\n    cin >> start_r >> start_c;\n    for (int i = 0; i < N_GRID; ++i) cin >> grid[i];\n    for (int i = 0; i < M_TARGETS; ++i) cin >> targets[i];\n}\n\nvoid precompute_char_positions() {\n    for (int i = 0; i < N_GRID; ++i) {\n        for (int j = 0; j < N_GRID; ++j) {\n            char_positions[grid[i][j] - 'A'].push_back({i, j});\n        }\n    }\n}\n\nvoid precompute_overlaps() {\n    for (int i = 0; i < M_TARGETS; ++i) {\n        for (int j = 0; j < M_TARGETS; ++j) {\n            if (i == j) continue;\n            for (int k = 4; k >= 1; --k) {\n                if (targets[i].substr(5 - k) == targets[j].substr(0, k)) {\n                    overlaps[i][j] = k;\n                    break;\n                }\n            }\n        }\n    }\n}\n\nvoid precompute_avg_transition_cost() {\n    for (int i = 0; i < 26; ++i) {\n        for (int j = 0; j < 26; ++j) {\n            if (char_positions[i].empty() || char_positions[j].empty()) continue;\n            double total_min_dist = 0;\n            for (const auto& p1 : char_positions[i]) {\n                int min_dist = 1e9;\n                for (const auto& p2 : char_positions[j]) {\n                    min_dist = min(min_dist, manhattan_distance(p1, p2));\n                }\n                total_min_dist += min_dist;\n            }\n            avg_transition_cost[i][j] = total_min_dist / char_positions[i].size() + 1.0;\n        }\n    }\n}\n\nvoid precompute_weights() {\n    for (int i = 0; i < M_TARGETS; ++i) {\n        for (int j = 0; j < M_TARGETS; ++j) {\n            if (i == j) continue;\n            int ov = overlaps[i][j];\n            const string& t_j = targets[j];\n            const string& t_i = targets[i];\n            \n            double cost_est = 0;\n            if (5 - ov > 0) {\n                cost_est += avg_transition_cost[t_i.back() - 'A'][t_j[ov] - 'A'];\n                for (int k = ov; k < 4; ++k) {\n                    cost_est += avg_transition_cost[t_j[k] - 'A'][t_j[k+1] - 'A'];\n                }\n            }\n            weights[i][j] = cost_est;\n        }\n    }\n}\n\n// --- Core Logic ---\n// DP-based cost calculation.\nlong long calculate_path_cost_dp(const vector<int>& path) {\n    string S;\n    S.reserve(5 * M_TARGETS);\n    if (path.empty()) return 0;\n    S += targets[path[0]];\n    for (size_t i = 1; i < path.size(); ++i) {\n        S += targets[path[i]].substr(overlaps[path[i - 1]][path[i]]);\n    }\n    if (S.length() > 5000) return 1e18;\n    if (S.empty()) return 0;\n\n    vector<long long> prev_dp;\n    const auto& pos_0 = char_positions[S[0] - 'A'];\n    prev_dp.resize(pos_0.size());\n    for (size_t i = 0; i < pos_0.size(); ++i) {\n        prev_dp[i] = manhattan_distance({start_r, start_c}, pos_0[i]) + 1;\n    }\n\n    for (size_t k = 1; k < S.length(); ++k) {\n        const auto& pos_k_minus_1 = char_positions[S[k - 1] - 'A'];\n        const auto& pos_k = char_positions[S[k] - 'A'];\n        vector<long long> current_dp(pos_k.size());\n\n        for (size_t j = 0; j < pos_k.size(); ++j) {\n            long long min_prev_cost = 1e18;\n            for (size_t i = 0; i < pos_k_minus_1.size(); ++i) {\n                long long cost = prev_dp[i] + manhattan_distance(pos_k_minus_1[i], pos_k[j]);\n                min_prev_cost = min(min_prev_cost, cost);\n            }\n            current_dp[j] = min_prev_cost + 1;\n        }\n        prev_dp = move(current_dp);\n    }\n    if (prev_dp.empty()) return 1e18;\n    return *min_element(prev_dp.begin(), prev_dp.end());\n}\n\n// Full DP with backpointers to generate final move sequence.\nvoid generate_final_moves(const vector<int>& path, vector<pair<int, int>>& move_sequence) {\n    string S;\n    S.reserve(5 * M_TARGETS);\n    if (path.empty()) return;\n    S += targets[path[0]];\n    for (size_t i = 1; i < path.size(); ++i) {\n        S += targets[path[i]].substr(overlaps[path[i-1]][path[i]]);\n    }\n    if (S.empty() || S.length() > 5000) return;\n\n    move_sequence.clear();\n    vector<vector<long long>> dp(S.length());\n    vector<vector<int>> backpointers(S.length());\n\n    const auto& pos_0 = char_positions[S[0] - 'A'];\n    dp[0].resize(pos_0.size());\n    for (size_t i = 0; i < pos_0.size(); ++i) {\n        dp[0][i] = manhattan_distance({start_r, start_c}, pos_0[i]) + 1;\n    }\n\n    for (size_t k = 1; k < S.length(); ++k) {\n        const auto& pos_k_minus_1 = char_positions[S[k - 1] - 'A'];\n        const auto& pos_k = char_positions[S[k] - 'A'];\n        dp[k].resize(pos_k.size());\n        backpointers[k].resize(pos_k.size());\n\n        for (size_t j = 0; j < pos_k.size(); ++j) {\n            long long min_prev_cost = 1e18;\n            int best_prev_idx = -1;\n            for (size_t i = 0; i < pos_k_minus_1.size(); ++i) {\n                long long cost = dp[k-1][i] + manhattan_distance(pos_k_minus_1[i], pos_k[j]);\n                if (cost < min_prev_cost) {\n                    min_prev_cost = cost;\n                    best_prev_idx = i;\n                }\n            }\n            dp[k][j] = min_prev_cost + 1;\n            backpointers[k][j] = best_prev_idx;\n        }\n    }\n\n    long long final_cost = 1e18;\n    int last_idx = -1;\n    if (!dp.back().empty()) {\n        for (size_t i = 0; i < dp.back().size(); ++i) {\n            if (dp.back()[i] < final_cost) {\n                final_cost = dp.back()[i];\n                last_idx = i;\n            }\n        }\n    }\n\n    move_sequence.resize(S.length());\n    for (int k = S.length() - 1; k >= 0; --k) {\n        move_sequence[k] = char_positions[S[k] - 'A'][last_idx];\n        if (k > 0) last_idx = backpointers[k][last_idx];\n    }\n}\n\n\ndouble calculate_approx_cost(const vector<int>& path) {\n    double cost = 0;\n    for (size_t i = 0; i < path.size() - 1; ++i) {\n        cost += weights[path[i]][path[i+1]];\n    }\n    return cost;\n}\n\nvector<int> get_initial_solution() {\n    vector<int> best_path;\n    double min_weight_sum = 1e18;\n\n    vector<int> p(M_TARGETS);\n    iota(p.begin(), p.end(), 0);\n    shuffle(p.begin(), p.end(), rng);\n    \n    for(int i = 0; i < min(M_TARGETS, 20); ++i) {\n        int start_node = p[i];\n        vector<int> path; path.reserve(M_TARGETS);\n        path.push_back(start_node);\n        vector<bool> visited(M_TARGETS, false); visited[start_node] = true;\n        int current_node = start_node;\n        double current_weight_sum = 0;\n\n        for (int k = 0; k < M_TARGETS - 1; ++k) {\n            int next_node = -1; double min_weight = 1e18;\n            for (int j = 0; j < M_TARGETS; ++j) {\n                if (!visited[j] && weights[current_node][j] < min_weight) {\n                    min_weight = weights[current_node][j]; next_node = j;\n                }\n            }\n            visited[next_node] = true; path.push_back(next_node);\n            current_weight_sum += min_weight; current_node = next_node;\n        }\n        if (current_weight_sum < min_weight_sum) {\n            min_weight_sum = current_weight_sum; best_path = path;\n        }\n    }\n    return best_path;\n}\n\nvoid solve() {\n    auto time_start = chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_MS = 1950.0;\n    const double FAST_SA_TIME_MS = 1600.0; \n\n    vector<int> current_path = get_initial_solution();\n    vector<int> best_path_overall = current_path;\n    long long best_cost_overall = calculate_path_cost_dp(best_path_overall);\n\n    uniform_int_distribution<int> dist(0, M_TARGETS - 1);\n    uniform_int_distribution<int> move_dist(0, 9);\n    uniform_real_distribution<double> accept_dist(0.0, 1.0);\n\n    // Stage 1: Fast SA with approximate cost\n    {\n        double start_temp = 50.0, end_temp = 0.1;\n        vector<int> best_path_fast = current_path;\n        double current_approx = calculate_approx_cost(current_path);\n        double best_approx = current_approx;\n        int iter_count = 0;\n        \n        while (chrono::duration<double, milli>(chrono::high_resolution_clock::now() - time_start).count() < FAST_SA_TIME_MS) {\n            iter_count++;\n            vector<int> new_path = current_path;\n            int i = dist(rng), j = dist(rng);\n            if (i == j) continue;\n            \n            int move_type = move_dist(rng);\n            if (move_type < 4) { // Reverse (40%)\n                if (i > j) swap(i, j); reverse(new_path.begin() + i, new_path.begin() + j + 1);\n            } else if (move_type < 8) { // Move (40%)\n                int element = new_path[i]; new_path.erase(new_path.begin() + i); new_path.insert(new_path.begin() + j, element);\n            } else { // Swap (20%)\n                swap(new_path[i], new_path[j]);\n            }\n\n            double new_approx = calculate_approx_cost(new_path);\n            double elapsed_frac = chrono::duration<double, milli>(chrono::high_resolution_clock::now() - time_start).count() / FAST_SA_TIME_MS;\n            double temp = start_temp * pow(end_temp / start_temp, elapsed_frac);\n            \n            if (new_approx < current_approx || accept_dist(rng) < exp((current_approx - new_approx) / temp)) {\n                current_path = move(new_path); current_approx = new_approx;\n            }\n            if (current_approx < best_approx) { best_approx = current_approx; best_path_fast = current_path; }\n\n            if (iter_count % 5000 == 0) {\n                 long long fast_sa_best_full_cost = calculate_path_cost_dp(best_path_fast);\n                 if (fast_sa_best_full_cost < best_cost_overall) {\n                     best_cost_overall = fast_sa_best_full_cost; best_path_overall = best_path_fast;\n                 }\n            }\n        }\n        long long fast_sa_best_full_cost = calculate_path_cost_dp(best_path_fast);\n        if (fast_sa_best_full_cost < best_cost_overall) {\n            best_cost_overall = fast_sa_best_full_cost; best_path_overall = best_path_fast;\n        }\n    }\n\n    // Stage 2: Slow SA with exact DP cost and kick move\n    {\n        double start_temp = 80.0, end_temp = 0.1;\n        current_path = best_path_overall;\n        long long current_full_cost = best_cost_overall;\n        int stagnation_counter = 0;\n        const int STAGNATION_THRESHOLD = 500;\n        \n        while (chrono::duration<double, milli>(chrono::high_resolution_clock::now() - time_start).count() < TIME_LIMIT_MS) {\n            if (stagnation_counter >= STAGNATION_THRESHOLD) {\n                current_path = best_path_overall;\n                uniform_int_distribution<int> len_dist(20, 40);\n                int len = len_dist(rng);\n                uniform_int_distribution<int> start_dist(0, M_TARGETS - len);\n                int start_idx = start_dist(rng);\n                shuffle(current_path.begin() + start_idx, current_path.begin() + start_idx + len, rng);\n                current_full_cost = calculate_path_cost_dp(current_path);\n                stagnation_counter = 0;\n            }\n\n            vector<int> new_path = current_path;\n            int i = dist(rng), j = dist(rng);\n            if (i == j) continue;\n            \n            int move_type = move_dist(rng);\n            if (move_type < 4) { if (i > j) swap(i, j); reverse(new_path.begin() + i, new_path.begin() + j + 1);\n            } else if (move_type < 8) { int element = new_path[i]; new_path.erase(new_path.begin() + i); new_path.insert(new_path.begin() + j, element);\n            } else { swap(new_path[i], new_path[j]); }\n\n            long long new_full_cost = calculate_path_cost_dp(new_path);\n            double time_now = chrono::duration<double, milli>(chrono::high_resolution_clock::now() - time_start).count();\n            if (time_now >= TIME_LIMIT_MS) break; \n            double elapsed_frac = (time_now - FAST_SA_TIME_MS) / (TIME_LIMIT_MS - FAST_SA_TIME_MS);\n            double temp = start_temp * pow(end_temp / start_temp, elapsed_frac);\n            \n            if (new_full_cost < current_full_cost || accept_dist(rng) < exp((double)(current_full_cost - new_full_cost) / temp)) {\n                current_path = move(new_path); current_full_cost = new_full_cost;\n            }\n\n            if (current_full_cost < best_cost_overall) { \n                best_cost_overall = current_full_cost; \n                best_path_overall = current_path;\n                stagnation_counter = 0;\n            } else {\n                stagnation_counter++;\n            }\n        }\n    }\n\n    vector<pair<int, int>> final_moves;\n    generate_final_moves(best_path_overall, final_moves);\n    for (const auto& move : final_moves) {\n        cout << move.first << \" \" << move.second << \"\\n\";\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    read_input();\n    precompute_char_positions();\n    precompute_overlaps();\n    precompute_avg_transition_cost();\n    precompute_weights();\n    solve();\n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <map>\n#include <iomanip>\n\n// Constants and Typedefs\nusing namespace std;\nusing Point = pair<int, int>;\n\n// Utilities\nstruct Timer {\n    chrono::high_resolution_clock::time_point start_time;\n    Timer() {\n        start_time = chrono::high_resolution_clock::now();\n    }\n    long long get_elapsed_ms() {\n        auto end_time = chrono::high_resolution_clock::now();\n        return chrono::duration_cast<chrono::milliseconds>(end_time - start_time).count();\n    }\n};\n\n// Global random engine\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// Problem specific structures\nstruct Polyomino {\n    int id;\n    int d;\n    vector<Point> coords;\n    int max_i = 0, max_j = 0;\n};\n\nstruct Problem {\n    int N, M;\n    double epsilon;\n    vector<Polyomino> fields;\n    vector<vector<Point>> valid_placements;\n    map<vector<Point>, vector<int>> identical_shapes;\n};\n\nstruct Particle {\n    vector<Point> placements;\n    vector<vector<int>> v_grid;\n\n    Particle(int M, int N) : placements(M), v_grid(N, vector<int>(N, 0)) {}\n\n    void compute_v_grid(const Problem& prob) {\n        for (auto& row : v_grid) fill(row.begin(), row.end(), 0);\n        for (int m = 0; m < prob.M; ++m) {\n            const auto& p = placements[m];\n            if (p.first == -1) continue;\n            for (const auto& rel_coord : prob.fields[m].coords) {\n                v_grid[p.first + rel_coord.first][p.second + rel_coord.second]++;\n            }\n        }\n    }\n};\n\n// Main solver\nclass Solver {\nprivate:\n    Problem prob;\n    int num_particles;\n    vector<Particle> particles;\n    vector<double> log_weights;\n    vector<vector<int>> known_v;\n    Timer timer;\n    int query_count = 0;\n    \npublic:\n    Solver(int N, int M, double epsilon, const vector<Polyomino>& fields, int K)\n        : prob{N, M, epsilon, fields}, num_particles(K), known_v(N, vector<int>(N, -1)) {\n        prob.valid_placements.resize(M);\n        for (int m = 0; m < M; ++m) {\n            auto& field = prob.fields[m];\n            field.max_i = 0; field.max_j = 0;\n            for(const auto& p : field.coords) {\n                field.max_i = max(field.max_i, p.first);\n                field.max_j = max(field.max_j, p.second);\n            }\n            if (field.max_i >= N || field.max_j >= N) continue; \n            for (int i = 0; i <= N - 1 - field.max_i; ++i) {\n                for (int j = 0; j <= N - 1 - field.max_j; ++j) {\n                    prob.valid_placements[m].push_back({i, j});\n                }\n            }\n        }\n        \n        for (int m = 0; m < M; ++m) {\n            vector<Point> sorted_coords = fields[m].coords;\n            sort(sorted_coords.begin(), sorted_coords.end());\n            prob.identical_shapes[sorted_coords].push_back(m);\n        }\n    }\n\n    void solve() {\n        initialize_particles();\n        perform_initial_queries();\n\n        while (timer.get_elapsed_ms() < 2700 && query_count < 2 * prob.N * prob.N) {\n            if (!run_main_loop_step()) {\n                break; \n            }\n        }\n\n        while (timer.get_elapsed_ms() < 2950 && query_count < 2 * prob.N * prob.N) {\n            auto p_grid = calculate_p_grid();\n            Point most_uncertain_cell = {-1, -1};\n            double min_dist_to_half = 1.0;\n            for (int r = 0; r < prob.N; ++r) for (int c = 0; c < prob.N; ++c) if (known_v[r][c] == -1) {\n                if (p_grid[r][c] > 0.05 && p_grid[r][c] < 0.95) {\n                    if (abs(p_grid[r][c] - 0.5) < min_dist_to_half) {\n                        min_dist_to_half = abs(p_grid[r][c] - 0.5);\n                        most_uncertain_cell = {r, c};\n                    }\n                }\n            }\n            if (most_uncertain_cell.first == -1) break;\n\n            query_drill(most_uncertain_cell.first, most_uncertain_cell.second);\n            if (timer.get_elapsed_ms() < 2950) resample_and_mutate();\n        }\n        \n        final_guess_loop();\n    }\n\nprivate:\n    void final_guess_loop() {\n        auto p_grid = calculate_p_grid();\n        vector<Point> guess;\n        for (int i = 0; i < prob.N; ++i) for (int j = 0; j < prob.N; ++j) {\n            if (known_v[i][j] != -1) { if (known_v[i][j] > 0) guess.push_back({i, j}); }\n            else { if (p_grid[i][j] > 0.5) guess.push_back({i, j}); }\n        }\n\n        while (query_count < 2 * prob.N * prob.N) {\n            cout << \"a \" << guess.size();\n            for(const auto& p : guess) cout << \" \" << p.first << \" \" << p.second;\n            cout << endl;\n\n            int result;\n            cin >> result;\n            if (result == 1) return;\n            query_count++; \n        }\n    }\n\n    bool run_main_loop_step() {\n        double max_score = -1.0;\n        vector<Point> best_query_set;\n\n        for (int i = 0; i < 40; ++i) {\n            Point center = {uniform_int_distribution<>(0, prob.N - 1)(rng), uniform_int_distribution<>(0, prob.N - 1)(rng)};\n            \n            for (int size = 2; size <= 4; ++size) {\n                vector<Point> S;\n                int half = size / 2;\n                for (int di = -(half); di < size - half; ++di) {\n                    for (int dj = -(half); dj < size - half; ++dj) {\n                        int ni = center.first + di;\n                        int nj = center.second + dj;\n                        if (ni >= 0 && ni < prob.N && nj >= 0 && nj < prob.N && known_v[ni][nj] == -1) {\n                            S.push_back({ni, nj});\n                        }\n                    }\n                }\n                if (S.size() < 2) continue;\n\n                vector<double> vS_values;\n                vS_values.reserve(num_particles);\n                for (const auto& p : particles) {\n                    int vS = 0;\n                    for (const auto& cell : S) vS += p.v_grid[cell.first][cell.second];\n                    vS_values.push_back(vS);\n                }\n                double sum = accumulate(vS_values.begin(), vS_values.end(), 0.0);\n                double mean = sum / vS_values.size();\n                double sq_sum = inner_product(vS_values.begin(), vS_values.end(), vS_values.begin(), 0.0);\n                double var = sq_sum / vS_values.size() - mean * mean;\n                \n                double score = var * sqrt(S.size());\n                \n                if (score > max_score) {\n                    max_score = score;\n                    best_query_set = S;\n                }\n            }\n        }\n\n        if (max_score > 0.1) {\n            query_divine(best_query_set);\n        } else {\n            auto p_grid = calculate_p_grid();\n            Point most_uncertain_cell = {-1, -1};\n            double min_dist_to_half = 1.0;\n\n            for (int r = 0; r < prob.N; ++r) for (int c = 0; c < prob.N; ++c) if (known_v[r][c] == -1) {\n                if (p_grid[r][c] > 0.05 && p_grid[r][c] < 0.95) {\n                    if (abs(p_grid[r][c] - 0.5) < min_dist_to_half) {\n                        min_dist_to_half = abs(p_grid[r][c] - 0.5);\n                        most_uncertain_cell = {r, c};\n                    }\n                }\n            }\n\n            if (most_uncertain_cell.first != -1) {\n                query_drill(most_uncertain_cell.first, most_uncertain_cell.second);\n            } else {\n                return false;\n            }\n        }\n        \n        resample_and_mutate();\n        return true;\n    }\n\n    void initialize_particles() {\n        particles.assign(num_particles, Particle(prob.M, prob.N));\n        for (int i = 0; i < num_particles; ++i) {\n            for (int m = 0; m < prob.M; ++m) {\n                if(prob.valid_placements[m].empty()){ particles[i].placements[m] = {-1, -1}; continue; }\n                uniform_int_distribution<> dist(0, prob.valid_placements[m].size() - 1);\n                particles[i].placements[m] = prob.valid_placements[m][dist(rng)];\n            }\n            particles[i].compute_v_grid(prob);\n        }\n        log_weights.assign(num_particles, 0.0);\n    }\n    \n    void perform_initial_queries() {\n        vector<Point> all, h_i, h_j, check;\n        for (int i=0; i<prob.N; ++i) for (int j=0; j<prob.N; ++j) {\n            all.push_back({i,j}); if (i<prob.N/2) h_i.push_back({i,j});\n            if (j<prob.N/2) h_j.push_back({i,j}); if ((i+j)%2==0) check.push_back({i,j});\n        }\n        for(const auto& q_set : {all, h_i, h_j, check}){\n            if (timer.get_elapsed_ms() > 2700 || q_set.size() < 2) continue;\n            query_divine(q_set); resample_and_mutate();\n        }\n    }\n\n    void query_drill(int r, int c) {\n        if (known_v[r][c] != -1 || query_count >= 2*prob.N*prob.N) return;\n        query_count++; cout << \"q 1 \" << r << \" \" << c << endl;\n        int v; cin >> v; known_v[r][c] = v;\n        for (int i=0; i<num_particles; ++i) if(particles[i].v_grid[r][c] != v) log_weights[i] = -HUGE_VAL;\n    }\n\n    void query_divine(const vector<Point>& S) {\n        if (S.empty() || query_count >= 2*prob.N*prob.N) return;\n        if (S.size() == 1) { query_drill(S[0].first, S[0].second); return; }\n        query_count++; cout << \"q \" << S.size(); for(const auto& p:S) cout<<\" \"<<p.first<<\" \"<<p.second; cout<<endl;\n        int O; cin >> O;\n        double var = S.size() * prob.epsilon * (1.0 - prob.epsilon), stddev = sqrt(var);\n        for (int i=0; i<num_particles; ++i) {\n            if (log_weights[i] <= -HUGE_VAL) continue;\n            int vS=0; for(const auto& p:S) vS+=particles[i].v_grid[p.first][p.second];\n            double mu = S.size()*prob.epsilon + vS*(1.0-2.0*prob.epsilon);\n            double log_p = (stddev>1e-9)? -log(stddev*sqrt(2*M_PI))-0.5*pow((O-mu)/stddev,2) : ((abs(O-mu)<0.5)?0.0:-HUGE_VAL);\n            log_weights[i] += log_p;\n        }\n    }\n\n    void resample_and_mutate() {\n        double max_log_w = -HUGE_VAL; for(double lw:log_weights) if(lw > max_log_w) max_log_w = lw;\n        if (!isfinite(max_log_w)) {\n            initialize_particles();\n            for (int r=0; r<prob.N; ++r) for(int c=0; c<prob.N; ++c) if (known_v[r][c]!=-1)\n                for(int i=0; i<num_particles; ++i) if (particles[i].v_grid[r][c] != known_v[r][c]) log_weights[i] = -HUGE_VAL;\n            return;\n        }\n        vector<double> current_weights(num_particles);\n        for(int i=0; i<num_particles; ++i) current_weights[i] = exp(log_weights[i] - max_log_w);\n        \n        vector<Particle> new_particles; new_particles.reserve(num_particles);\n        int num_elite=num_particles*0.02, num_random=num_particles*0.15;\n        \n        vector<pair<double,int>> sorted_w; sorted_w.reserve(num_particles);\n        for(int i=0; i<num_particles; ++i) sorted_w.push_back({-log_weights[i], i});\n        sort(sorted_w.begin(), sorted_w.end());\n        for(int i=0; i<num_elite; ++i) new_particles.push_back(particles[sorted_w[i].second]);\n        \n        discrete_distribution<int> dist(current_weights.begin(), current_weights.end());\n        for(int i=0; i<num_particles-num_elite-num_random; ++i) new_particles.push_back(particles[dist(rng)]);\n        for(int i=0; i<num_random; ++i){\n            new_particles.emplace_back(prob.M, prob.N);\n            for(int m=0; m<prob.M; ++m){\n                if(prob.valid_placements[m].empty()){ new_particles.back().placements[m]={-1,-1}; continue;}\n                uniform_int_distribution<> p_dist(0, prob.valid_placements[m].size()-1);\n                new_particles.back().placements[m] = prob.valid_placements[m][p_dist(rng)];\n            }\n            new_particles.back().compute_v_grid(prob);\n        }\n\n        uniform_real_distribution<> r_dist(0.0, 1.0); int dr[]={-1,1,0,0}, dc[]={0,0,-1,1};\n        for(size_t i = num_elite; i < new_particles.size(); ++i) {\n            auto& p = new_particles[i];\n            for(int m=0; m<prob.M; ++m) if(p.placements[m].first!=-1 && r_dist(rng)<0.1){\n                Point old_pos = p.placements[m], new_pos = old_pos;\n                if (r_dist(rng)<0.8) {\n                    vector<Point> neighbors; for(int k=0; k<4; ++k){\n                        Point n = {old_pos.first+dr[k], old_pos.second+dc[k]};\n                        if (n.first>=0 && n.first<=prob.N-1-prob.fields[m].max_i && n.second>=0 && n.second<=prob.N-1-prob.fields[m].max_j) neighbors.push_back(n);\n                    }\n                    if(!neighbors.empty()) new_pos = neighbors[uniform_int_distribution<>(0,neighbors.size()-1)(rng)];\n                } else {\n                    if (!prob.valid_placements[m].empty()) {\n                        new_pos = prob.valid_placements[m][uniform_int_distribution<>(0,prob.valid_placements[m].size()-1)(rng)];\n                    }\n                }\n                if (new_pos != old_pos) {\n                    p.placements[m] = new_pos;\n                    for(const auto& c:prob.fields[m].coords) {\n                        p.v_grid[old_pos.first+c.first][old_pos.second+c.second]--;\n                        p.v_grid[new_pos.first+c.first][new_pos.second+c.second]++;\n                    }\n                }\n            }\n            for(const auto& [sh, ids] : prob.identical_shapes) if (ids.size()>1 && r_dist(rng)<0.1) {\n                uniform_int_distribution<int> id_dist(0,ids.size()-1); int i1=id_dist(rng),i2=id_dist(rng);\n                if(i1!=i2) swap(p.placements[ids[i1]], p.placements[ids[i2]]);\n            }\n        }\n        particles=new_particles; log_weights.assign(num_particles,0.0);\n    }\n    \n    vector<vector<double>> calculate_p_grid() {\n        vector<vector<double>> p_grid(prob.N, vector<double>(prob.N, 0.0));\n        int valid_particles = 0;\n        for (const auto& p : particles) {\n             bool is_valid=true; for(const auto& pl:p.placements) if(pl.first==-1) {is_valid=false; break;}\n             if(!is_valid) continue; valid_particles++;\n             for(int i=0; i<prob.N; ++i) for(int j=0; j<prob.N; ++j) if(p.v_grid[i][j]>0) p_grid[i][j]+=1.0;\n        }\n        if(valid_particles>0) for(auto& r:p_grid) for(auto& c:r) c/=valid_particles;\n        return p_grid;\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false); cin.tie(NULL);\n    int N, M; double epsilon; cin >> N >> M >> epsilon;\n    vector<Polyomino> fields(M);\n    for (int i=0; i<M; ++i) {\n        fields[i].id = i; cin >> fields[i].d; fields[i].coords.resize(fields[i].d);\n        for(int j=0; j<fields[i].d; ++j) cin>>fields[i].coords[j].first>>fields[i].coords[j].second;\n    }\n    int K = 3000;\n    if (N <= 12) K = 2500;\n    if (M >= 15 || N >= 18) K = 5000;\n    Solver solver(N, M, epsilon, fields, K);\n    solver.solve();\n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n#include <functional>\n\nusing namespace std;\n\n// Constants\nconstexpr int W = 1000;\nint D, N;\n\n// Structures\nstruct Rect {\n    int r0, c0, r1, c1;\n    long long area() const {\n        return (long long)(r1 - r0) * (c1 - c0);\n    }\n};\n\nstruct Node {\n    bool is_leaf;\n    int k_min, k_max; // range of reservation indices\n    Node *left = nullptr, *right = nullptr;\n    Node *parent = nullptr;\n\n    // For internal nodes\n    bool is_vertical_split;\n    int split_idx;\n\n    // For leaf nodes\n    int k;\n};\n\n// Globals\nvector<vector<long long>> a;\nvector<Node> tree_nodes;\nint node_idx_counter;\nvector<Rect> current_rects;\nvector<int> split_coords;\nvector<Node*> split_idx_to_node;\n\nvector<vector<bool>> h_prev_exists, v_prev_exists;\nvector<vector<int>> h_curr_count, v_curr_count;\n\n// Randomness\nuint64_t xor_shift() {\n    static uint64_t x = 88172645463325252ULL;\n    x ^= x << 13;\n    x ^= x >> 7;\n    x ^= x << 17;\n    return x;\n}\n\nint rand_int(int min_val, int max_val) {\n    if (min_val > max_val) return min_val;\n    return min_val + xor_shift() % (max_val - min_val + 1);\n}\n\ndouble rand_double() {\n    return (double)xor_shift() / UINT64_MAX;\n}\n\n// Tree building\nNode* build_tree(int k_min, int k_max, const Rect& region) {\n    Node* node = &tree_nodes[node_idx_counter++];\n    node->k_min = k_min;\n    node->k_max = k_max;\n\n    if (k_max - k_min == 1) {\n        node->is_leaf = true;\n        node->k = k_min;\n        return node;\n    }\n\n    node->is_leaf = false;\n    int k_mid = k_min + (k_max - k_min) / 2;\n    \n    node->is_vertical_split = (region.c1 - region.c0 >= region.r1 - region.r0);\n    \n    Rect left_region, right_region;\n    if (node->is_vertical_split) {\n        int c_split = region.c0 + (region.c1 - region.c0) / 2;\n        left_region = {region.r0, region.c0, region.r1, c_split};\n        right_region = {region.r0, c_split, region.r1, region.c1};\n    } else {\n        int r_split = region.r0 + (region.r1 - region.r0) / 2;\n        left_region = {region.r0, region.c0, r_split, region.c1};\n        right_region = {r_split, region.c0, region.r1, region.c1};\n    }\n    \n    node->left = build_tree(k_min, k_mid, left_region);\n    node->left->parent = node;\n    node->right = build_tree(k_mid, k_max, right_region);\n    node->right->parent = node;\n    return node;\n}\n\nvoid assign_split_indices(Node* node, int& split_idx_counter) {\n    if (node->is_leaf) return;\n    node->split_idx = split_idx_counter++;\n    split_idx_to_node[node->split_idx] = node;\n    assign_split_indices(node->left, split_idx_counter);\n    assign_split_indices(node->right, split_idx_counter);\n}\n\n\n// Layout and cost calculations\nvoid get_rects_from_coords(Node* node, const Rect& region, const vector<int>& coords, vector<Rect>& rects_out) {\n    if (node->is_leaf) {\n        rects_out[node->k] = region;\n        return;\n    }\n\n    int coord = coords[node->split_idx];\n    Rect left_region, right_region;\n\n    if (node->is_vertical_split) {\n        left_region = {region.r0, region.c0, region.r1, coord};\n        right_region = {region.r0, coord, region.r1, region.c1};\n    } else {\n        left_region = {region.r0, region.c0, coord, region.c1};\n        right_region = {coord, region.c0, region.r1, region.c1};\n    }\n    get_rects_from_coords(node->left, left_region, coords, rects_out);\n    get_rects_from_coords(node->right, right_region, coords, rects_out);\n}\n\nvoid get_ideal_coords(Node* node, const Rect& region, int d, vector<int>& coords) {\n    if (node->is_leaf) return;\n    \n    long long total_area_left = 0;\n    for (int k = node->left->k_min; k < node->left->k_max; ++k) total_area_left += a[d][k];\n    \n    long long total_area_right = 0;\n    for (int k = node->right->k_min; k < node->right->k_max; ++k) total_area_right += a[d][k];\n\n    long long total_area_node = total_area_left + total_area_right;\n    if (total_area_node == 0) total_area_node = 1;\n\n    int coord;\n    Rect left_region, right_region;\n    if (node->is_vertical_split) {\n        coord = region.c0 + round((double)(region.c1 - region.c0) * total_area_left / total_area_node);\n        coord = clamp(coord, region.c0 + 1, region.c1 - 1);\n        left_region = {region.r0, region.c0, region.r1, coord};\n        right_region = {region.r0, coord, region.r1, region.c1};\n    } else {\n        coord = region.r0 + round((double)(region.r1 - region.r0) * total_area_left / total_area_node);\n        coord = clamp(coord, region.r0 + 1, region.r1 - 1);\n        left_region = {region.r0, region.c0, coord, region.c1};\n        right_region = {coord, region.c0, region.r1, region.c1};\n    }\n    coords[node->split_idx] = coord;\n    get_ideal_coords(node->left, left_region, d, coords);\n    get_ideal_coords(node->right, right_region, d, coords);\n}\n\nlong long calculate_area_cost(int d, const vector<Rect>& rects) {\n    long long cost = 0;\n    for (int k = 0; k < N; ++k) {\n        cost += 100 * max(0LL, a[d][k] - rects[k].area());\n    }\n    return cost;\n}\n\nvoid populate_partition_counts(const vector<Rect>& rects) {\n    for (int i=1; i<W; ++i) fill(h_curr_count[i].begin(), h_curr_count[i].end(), 0);\n    for (int i=0; i<W; ++i) fill(v_curr_count[i].begin(), v_curr_count[i].end(), 0);\n    \n    for (int k = 0; k < N; ++k) {\n        const auto& r = rects[k];\n        if (r.r0 > 0) for (int c = r.c0; c < r.c1; ++c) h_curr_count[r.r0][c]++;\n        if (r.r1 < W) for (int c = r.c0; c < r.c1; ++c) h_curr_count[r.r1][c]++;\n        if (r.c0 > 0) for (int i = r.r0; i < r.r1; ++i) v_curr_count[i][r.c0]++;\n        if (r.c1 < W) for (int i = r.r0; i < r.r1; ++i) v_curr_count[i][r.c1]++;\n    }\n}\n\nlong long calculate_partition_change_cost_full() {\n    long long cost = 0;\n    for (int i = 1; i < W; ++i) {\n        for (int j = 0; j < W; ++j) {\n            cost += (h_prev_exists[i][j] != (h_curr_count[i][j] > 0));\n        }\n    }\n    for (int i = 0; i < W; ++i) {\n        for (int j = 1; j < W; ++j) {\n            cost += (v_prev_exists[i][j] != (v_curr_count[i][j] > 0));\n        }\n    }\n    return cost;\n}\n\nvoid update_prev_partitions() {\n    for (int i = 1; i < W; ++i) {\n        for (int j = 0; j < W; ++j) {\n            h_prev_exists[i][j] = (h_curr_count[i][j] > 0);\n        }\n    }\n    for (int i = 0; i < W; ++i) {\n        for (int j = 1; j < W; ++j) {\n            v_prev_exists[i][j] = (v_curr_count[i][j] > 0);\n        }\n    }\n}\n\n// Main logic\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int W_in;\n    cin >> W_in >> D >> N; \n    a.resize(D, vector<long long>(N));\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            cin >> a[d][k];\n        }\n    }\n\n    tree_nodes.resize(2 * N);\n    node_idx_counter = 0;\n    split_idx_to_node.resize(N - 1);\n    Node* root = build_tree(0, N, {0, 0, W, W});\n    int split_idx_counter = 0;\n    assign_split_indices(root, split_idx_counter);\n\n    current_rects.resize(N);\n    split_coords.resize(N - 1);\n    \n    h_prev_exists.resize(W + 1, vector<bool>(W + 1, false));\n    v_prev_exists.resize(W + 1, vector<bool>(W + 1, false));\n    h_curr_count.resize(W + 1, vector<int>(W + 1, 0));\n    v_curr_count.resize(W + 1, vector<int>(W + 1, 0));\n\n    // Day 0\n    get_ideal_coords(root, {0, 0, W, W}, 0, split_coords);\n    get_rects_from_coords(root, {0, 0, W, W}, split_coords, current_rects);\n    populate_partition_counts(current_rects);\n    update_prev_partitions();\n\n    vector<vector<Rect>> solution(D, vector<Rect>(N));\n    solution[0] = current_rects;\n\n    auto global_start_time = chrono::high_resolution_clock::now();\n\n    // Day 1 to D-1\n    for (int d = 1; d < D; ++d) {\n        get_rects_from_coords(root, {0, 0, W, W}, split_coords, current_rects);\n        populate_partition_counts(current_rects);\n        \n        long long current_area_cost = calculate_area_cost(d, current_rects);\n        long long partition_change_cost = calculate_partition_change_cost_full();\n        long long current_total_cost = current_area_cost + partition_change_cost;\n        \n        vector<int> best_coords = split_coords;\n        long long best_total_cost = current_total_cost;\n        \n        auto day_start_time = chrono::high_resolution_clock::now();\n        double time_limit_per_day = (2950.0 - chrono::duration_cast<chrono::milliseconds>(day_start_time - global_start_time).count()) / (D - d);\n\n        double temp = 5000;\n        int iter = 0;\n        while (true) {\n            iter++;\n            if (iter % 128 == 0) {\n                 auto now = chrono::high_resolution_clock::now();\n                 double elapsed = chrono::duration_cast<chrono::milliseconds>(now - day_start_time).count();\n                 if (elapsed > time_limit_per_day) break;\n            }\n            temp *= 0.9999;\n\n            int split_to_change = rand_int(0, N - 2);\n            Node* target_node = split_idx_to_node[split_to_change];\n            \n            Rect split_region = {0, 0, W, W};\n            Node* temp_node = target_node;\n            while(temp_node->parent != nullptr) {\n                Node* p = temp_node->parent;\n                int p_coord = split_coords[p->split_idx];\n                if (p->is_vertical_split) {\n                    if (temp_node == p->left) split_region.c1 = min(split_region.c1, p_coord);\n                    else split_region.c0 = max(split_region.c0, p_coord);\n                } else {\n                    if (temp_node == p->left) split_region.r1 = min(split_region.r1, p_coord);\n                    else split_region.r0 = max(split_region.r0, p_coord);\n                }\n                temp_node = p;\n            }\n\n            int old_coord = split_coords[split_to_change];\n            int range_min, range_max;\n            if (target_node->is_vertical_split) {\n                range_min = split_region.c0 + 1; range_max = split_region.c1 - 1;\n            } else {\n                range_min = split_region.r0 + 1; range_max = split_region.r1 - 1;\n            }\n            if (range_min >= range_max) continue;\n\n            int move_range = max(1, (int)((range_max - range_min) * 0.1 * temp / 5000.0));\n            int new_coord = old_coord + rand_int(-move_range, move_range);\n            new_coord = clamp(new_coord, range_min, range_max);\n            \n            if (new_coord == old_coord) continue;\n\n            vector<Rect> new_subtree_rects(N);\n            vector<int> next_coords = split_coords;\n            next_coords[split_to_change] = new_coord;\n\n            std::function<void(Node*, Rect)> compute_subtree_rects = \n                [&](Node* node, Rect region) {\n                    if (node->is_leaf) {\n                        new_subtree_rects[node->k] = region;\n                        return;\n                    }\n                    int coord = next_coords[node->split_idx];\n                    Rect left_region, right_region;\n                    if (node->is_vertical_split) {\n                        left_region = {region.r0, region.c0, region.r1, coord};\n                        right_region = {region.r0, coord, region.r1, region.c1};\n                    } else {\n                        left_region = {region.r0, region.c0, coord, region.c1};\n                        right_region = {coord, region.c0, region.r1, region.c1};\n                    }\n                    compute_subtree_rects(node->left, left_region);\n                    compute_subtree_rects(node->right, right_region);\n            };\n            compute_subtree_rects(target_node, split_region);\n\n            long long area_cost_delta = 0;\n            for(int k=target_node->k_min; k<target_node->k_max; ++k) {\n                area_cost_delta -= 100 * max(0LL, a[d][k] - current_rects[k].area());\n                area_cost_delta += 100 * max(0LL, a[d][k] - new_subtree_rects[k].area());\n            }\n\n            long long partition_cost_delta = 0;\n            if (target_node->is_vertical_split) {\n                for (int i = split_region.r0; i < split_region.r1; ++i) {\n                    partition_cost_delta -= (v_prev_exists[i][old_coord] != (v_curr_count[i][old_coord] > 0));\n                    v_curr_count[i][old_coord]--;\n                    partition_cost_delta += (v_prev_exists[i][old_coord] != (v_curr_count[i][old_coord] > 0));\n                    partition_cost_delta -= (v_prev_exists[i][new_coord] != (v_curr_count[i][new_coord] > 0));\n                    v_curr_count[i][new_coord]++;\n                    partition_cost_delta += (v_prev_exists[i][new_coord] != (v_curr_count[i][new_coord] > 0));\n                }\n            } else {\n                for (int j = split_region.c0; j < split_region.c1; ++j) {\n                    partition_cost_delta -= (h_prev_exists[old_coord][j] != (h_curr_count[old_coord][j] > 0));\n                    h_curr_count[old_coord][j]--;\n                    partition_cost_delta += (h_prev_exists[old_coord][j] != (h_curr_count[old_coord][j] > 0));\n                    partition_cost_delta -= (h_prev_exists[new_coord][j] != (h_curr_count[new_coord][j] > 0));\n                    h_curr_count[new_coord][j]++;\n                    partition_cost_delta += (h_prev_exists[new_coord][j] != (h_curr_count[new_coord][j] > 0));\n                }\n            }\n\n            long long cost_delta = area_cost_delta + partition_cost_delta;\n\n            if (cost_delta < 0 || (temp > 1 && rand_double() < exp(-(double)cost_delta / temp))) {\n                current_total_cost += cost_delta;\n                split_coords[split_to_change] = new_coord;\n                for(int k=target_node->k_min; k<target_node->k_max; ++k) {\n                    current_rects[k] = new_subtree_rects[k];\n                }\n                \n                if (current_total_cost < best_total_cost) {\n                    best_total_cost = current_total_cost;\n                    best_coords = split_coords;\n                }\n            } else { // revert counts\n                if (target_node->is_vertical_split) {\n                    for (int i = split_region.r0; i < split_region.r1; ++i) {\n                        v_curr_count[i][old_coord]++; v_curr_count[i][new_coord]--;\n                    }\n                } else {\n                    for (int j = split_region.c0; j < split_region.c1; ++j) {\n                        h_curr_count[old_coord][j]++; h_curr_count[new_coord][j]--;\n                    }\n                }\n            }\n        }\n        \n        split_coords = best_coords;\n        get_rects_from_coords(root, {0, 0, W, W}, split_coords, current_rects);\n        solution[d] = current_rects;\n        populate_partition_counts(current_rects);\n        update_prev_partitions();\n    }\n\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            const auto& r = solution[d][k];\n            cout << r.r0 << \" \" << r.c0 << \" \" << r.r1 << \" \" << r.c1 << \"\\n\";\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <optional>\n#include <cmath>\n#include <array>\n#include <cstdint>\n\n// --- Constants ---\nconstexpr int N = 9;\nconstexpr int M = 20;\nconstexpr int K = 81;\nconstexpr long long P = 998244353;\nconstexpr int MAX_POS_COORD = N - 3;\n\n// --- Type Definitions ---\nusing Board = std::vector<std::vector<long long>>;\nusing Stamp = std::vector<std::vector<long long>>;\n\nstruct Operation {\n    int m, p, q;\n};\n\n// --- Global Variables ---\nstd::vector<Stamp> stamps(M, Stamp(3, std::vector<long long>(3)));\nBoard initial_board(N, std::vector<long long>(N));\n\n// --- Timer ---\nstd::chrono::steady_clock::time_point start_time;\n\n// --- Fast Random Number Generator (xoshiro256**) ---\nstruct Xoshiro256StarStar {\n    uint64_t s[4];\n    static inline uint64_t rotl(const uint64_t x, int k) { return (x << k) | (x >> (64 - k)); }\n    void seed(uint64_t seed) { for(int i = 0; i < 4; ++i) { uint64_t z = seed + 0x9e3779b97f4a7c15 * (i + 1); z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; z = (z ^ (z >> 27)) * 0x94d049bb133111eb; s[i] = z ^ (z >> 31); } }\n    uint64_t next() { const uint64_t result = rotl(s[1] * 5, 7) * 9; const uint64_t t = s[1] << 17; s[2] ^= s[0]; s[3] ^= s[1]; s[1] ^= s[2]; s[0] ^= s[3]; s[2] ^= t; s[3] = rotl(s[3], 45); return result; }\n    int next_int(int min, int max) { if (min > max) return min; return min + next() % (uint64_t)(max - min + 1); }\n    double next_double() { return (next() >> 11) * (1.0 / 9007199254740992.0); }\n};\nXoshiro256StarStar fast_rng;\n\n// --- Utility Functions ---\nlong long current_time_ms() { return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count(); }\nlong long positive_modulo(long long i, long long n) { return (i % n + n) % n; }\nBoard apply_operations(const std::vector<Operation>& ops) { Board b = initial_board; for (const auto& op : ops) for (int i = 0; i < 3; ++i) for (int j = 0; j < 3; ++j) b[op.p + i][op.q + j] += stamps[op.m][i][j]; return b; }\nlong long calculate_score(const Board& board) { long long s = 0; for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) s += positive_modulo(board[i][j], P); return s; }\n\n// --- Fast Greedy Algorithm ---\nstd::vector<Operation> fast_greedy_solution() {\n    std::vector<Operation> ops;\n    Board current_board = initial_board;\n    for (int k = 0; k < K; ++k) {\n        long long best_delta_score = 0;\n        std::optional<Operation> best_op;\n        for (int m = 0; m < M; ++m) {\n            for (int p = 0; p <= MAX_POS_COORD; ++p) {\n                for (int q = 0; q <= MAX_POS_COORD; ++q) {\n                    long long current_delta_score = 0;\n                    for (int i=0; i<3; ++i) for (int j=0; j<3; ++j) {\n                        long long old_v = current_board[p+i][q+j];\n                        long long new_v = old_v + stamps[m][i][j];\n                        current_delta_score += positive_modulo(new_v, P) - positive_modulo(old_v, P);\n                    }\n                    if (current_delta_score > best_delta_score) { best_delta_score = current_delta_score; best_op = {m,p,q}; }\n                }\n            }\n        }\n        if (best_op) { ops.push_back(*best_op); for (int i=0; i<3; ++i) for (int j=0; j<3; ++j) current_board[best_op->p+i][best_op->q+j] += stamps[best_op->m][i][j]; }\n        else break;\n    }\n    return ops;\n}\n\n// --- Simulated Annealing ---\nvoid simulated_annealing(std::vector<Operation>& solution) {\n    long long time_limit = 1980;\n    Board current_board = apply_operations(solution);\n    long long current_score = calculate_score(current_board);\n    \n    std::vector<Operation> best_solution = solution;\n    long long best_score = current_score;\n    Board best_board = current_board;\n\n    double start_temp = 1e10, end_temp = 1;\n    std::array<long long, N*N> deltas{};\n    std::vector<int> dirty_keys; dirty_keys.reserve(18);\n\n    long long iter_count = 0;\n    long long last_best_update = 0;\n\n    while (true) {\n        long long elapsed_time = current_time_ms();\n        if (elapsed_time >= time_limit) break;\n        iter_count++;\n\n        double progress = (double)elapsed_time / time_limit;\n        \n        long long PATIENCE = 50000 + (long long)(100000.0 * (1.0 - progress));\n        if (iter_count - last_best_update > PATIENCE) {\n            solution = best_solution;\n            current_board = best_board;\n            current_score = best_score;\n            last_best_update = iter_count;\n        }\n\n        double temp = start_temp * std::pow(end_temp / start_temp, progress * progress); // Adaptive schedule\n        \n        int r = fast_rng.next_int(0, 99), move_type;\n        int op_count = solution.size();\n\n        if (op_count == K) { if (r < 80) move_type = 0; else move_type = 2; }\n        else if (op_count == 0) { move_type = 1; }\n        else { if (r < 80) move_type = 0; else if (r < 95) move_type = 1; else move_type = 2; }\n        \n        std::optional<Operation> old_op, new_op;\n        int op_idx = -1;\n\n        if (move_type == 0) {\n            op_idx = fast_rng.next_int(0, solution.size() - 1); old_op = solution[op_idx];\n            int change_r = fast_rng.next_int(0, 99);\n            if (change_r < 45) { // Jump position\n                Operation c=*old_op; do {c.p=fast_rng.next_int(0,MAX_POS_COORD);c.q=fast_rng.next_int(0,MAX_POS_COORD);} while(c.p==old_op->p&&c.q==old_op->q); new_op=c;\n            } else if (change_r < 90) { // Change stamp\n                Operation c=*old_op; do {c.m=fast_rng.next_int(0,M-1);} while(c.m==old_op->m); new_op=c;\n            } else { // Change both\n                Operation c; do {c.m=fast_rng.next_int(0,M-1);c.p=fast_rng.next_int(0,MAX_POS_COORD);c.q=fast_rng.next_int(0,MAX_POS_COORD);} while(c.m==old_op->m&&c.p==old_op->p&&c.q==old_op->q); new_op=c;\n            }\n        } else if (move_type == 1) { new_op = {fast_rng.next_int(0,M-1),fast_rng.next_int(0,MAX_POS_COORD),fast_rng.next_int(0,MAX_POS_COORD)}; }\n        else { op_idx = fast_rng.next_int(0, solution.size()-1); old_op = solution[op_idx]; }\n        \n        if(!new_op && !old_op) continue;\n        if(old_op){for(int i=0;i<3;++i)for(int j=0;j<3;++j){int k=(old_op->p+i)*N+old_op->q+j;if(deltas[k]==0)dirty_keys.push_back(k);deltas[k]-=stamps[old_op->m][i][j];}}\n        if(new_op){for(int i=0;i<3;++i)for(int j=0;j<3;++j){int k=(new_op->p+i)*N+new_op->q+j;if(deltas[k]==0)dirty_keys.push_back(k);deltas[k]+=stamps[new_op->m][i][j];}}\n        \n        long long delta_score=0; for(int k:dirty_keys){long long ov=current_board[k/N][k%N],nv=ov+deltas[k];delta_score+=positive_modulo(nv,P)-positive_modulo(ov,P);}\n        \n        if(delta_score > 0 || fast_rng.next_double() < std::exp((double)delta_score/temp)){\n            current_score+=delta_score; for(int k:dirty_keys)current_board[k/N][k%N]+=deltas[k];\n            if(move_type==0)solution[op_idx]=*new_op; else if(move_type==1)solution.push_back(*new_op); else solution.erase(solution.begin()+op_idx);\n            if(current_score > best_score){best_score=current_score; best_solution=solution; best_board=current_board; last_best_update=iter_count;}\n        }\n        for(int k:dirty_keys)deltas[k]=0; dirty_keys.clear();\n    }\n    solution = best_solution;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false); std::cin.tie(NULL);\n    start_time = std::chrono::steady_clock::now();\n    fast_rng.seed(std::chrono::duration_cast<std::chrono::nanoseconds>(start_time.time_since_epoch()).count());\n    \n    int n,m,k; std::cin>>n>>m>>k;\n    for(int i=0;i<N;++i)for(int j=0;j<N;++j)std::cin>>initial_board[i][j];\n    for(int i=0;i<M;++i)for(int r=0;r<3;++r)for(int c=0;c<3;++c)std::cin>>stamps[i][r][c];\n    \n    auto solution = fast_greedy_solution();\n    simulated_annealing(solution);\n\n    std::cout << solution.size() << '\\n';\n    for (const auto& op : solution) {\n        std::cout << op.m << \" \" << op.p << \" \" << op.q << '\\n';\n    }\n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <map>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nconst int N = 5;\nconst int MAX_TURNS = 10000;\n\nstruct Pos {\n    int r, c;\n    bool operator==(const Pos& other) const { return r == other.r && c == other.c; }\n    bool operator!=(const Pos& other) const { return !(*this == other); }\n    bool operator<(const Pos& other) const { if (r != other.r) return r < other.r; return c < other.c; }\n};\n\nenum TaskType { NONE, IDLE_MOVE, UNLOAD, SORT, DISPATCH };\n\nstruct Task {\n    TaskType type = NONE;\n    int container_id = -1;\n    Pos from;\n    Pos to;\n};\n\nstruct Crane {\n    int id; Pos pos; int payload = -1; Task task; bool bombed = false;\n};\n\nint grid[N][N];\nPos container_pos[N * N];\nCrane cranes[N];\nint arrival_idx[N];\nint dispatch_next[N];\nvector<string> history(N);\n\nvoid init_state() {\n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) grid[i][j] = -1;\n    for (int i = 0; i < N * N; ++i) container_pos[i] = {-1, -1};\n    for (int i = 0; i < N; ++i) {\n        cranes[i] = {i, {i, 0}, -1, {}, false};\n        arrival_idx[i] = 0; dispatch_next[i] = N * i;\n    }\n}\n\nvoid apply_actions_to_state(const string& actions) {\n    for (int i = 0; i < N; ++i) {\n        if (cranes[i].bombed) continue;\n        char act = actions[i];\n        if (act == 'P') {\n            cranes[i].payload = grid[cranes[i].pos.r][cranes[i].pos.c];\n            container_pos[grid[cranes[i].pos.r][cranes[i].pos.c]] = {-2,-2};\n            grid[cranes[i].pos.r][cranes[i].pos.c] = -1;\n        } else if (act == 'Q') {\n            grid[cranes[i].pos.r][cranes[i].pos.c] = cranes[i].payload;\n            container_pos[cranes[i].payload] = cranes[i].pos;\n            cranes[i].payload = -1;\n        } else if (act == 'B') cranes[i].bombed = true;\n    }\n    for (int i = 0; i < N; ++i) {\n        if (cranes[i].bombed) continue;\n        char act = actions[i];\n        if (act == 'U') cranes[i].pos.r--; else if (act == 'D') cranes[i].pos.r++;\n        else if (act == 'L') cranes[i].pos.c--; else if (act == 'R') cranes[i].pos.c++;\n    }\n}\n\nPos get_next_pos(Pos current, char action) {\n    if (action == 'U') return {current.r - 1, current.c}; if (action == 'D') return {current.r + 1, current.c};\n    if (action == 'L') return {current.r, current.c - 1}; if (action == 'R') return {current.r, current.c + 1};\n    return current;\n}\nchar get_move_action(Pos from, Pos to) {\n    if (from.r < to.r) return 'D'; if (from.r > to.r) return 'U';\n    if (from.c < to.c) return 'R'; if (from.c > to.c) return 'L';\n    return '.';\n}\n\nchar find_path_and_get_first_move(Pos start, Pos end, const vector<vector<bool>>& obstacles) {\n    if (start == end) return '.';\n    queue<Pos> q; q.push(start);\n    map<Pos, Pos> parent;\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    visited[start.r][start.c] = true;\n    int dr[] = {-1, 1, 0, 0}; int dc[] = {0, 0, -1, 1};\n    bool found = false;\n    while (!q.empty()) {\n        Pos curr = q.front(); q.pop();\n        if (curr == end) { found = true; break; }\n        for (int i = 0; i < 4; ++i) {\n            Pos next = {curr.r + dr[i], curr.c + dc[i]};\n            if (next.r >= 0 && next.r < N && next.c >= 0 && next.c < N && !visited[next.r][next.c] && !obstacles[next.r][next.c]) {\n                visited[next.r][next.c] = true; parent[next] = curr; q.push(next);\n            }\n        }\n    }\n    if (!found) return '.';\n    Pos curr = end;\n    while (parent.count(curr) && parent[curr] != start) curr = parent[curr];\n    return get_move_action(start, curr);\n}\n\nint dist(Pos a, Pos b) { return abs(a.r - b.r) + abs(a.c - b.c); }\n\nint main() {\n    ios_base::sync_with_stdio(false); cin.tie(NULL);\n    int n_dummy; cin >> n_dummy;\n    vector<vector<int>> A(N, vector<int>(N));\n    for (int i=0; i<N; ++i) for (int j=0; j<N; ++j) cin >> A[i][j];\n\n    init_state();\n    int dispatched_count = 0;\n\n    for (int t=0; t<MAX_TURNS; ++t) {\n        if (dispatched_count == N*N) break;\n\n        for (int i=0; i<N; ++i) {\n            bool gate_blocked = false;\n            for(int k=0; k<N; ++k) if(!cranes[k].bombed && cranes[k].pos == Pos{i,0} && cranes[k].payload != -1) gate_blocked = true;\n            if (arrival_idx[i] < N && grid[i][0] == -1 && !gate_blocked) {\n                int c = A[i][arrival_idx[i]]; grid[i][0] = c; container_pos[c] = {i,0}; arrival_idx[i]++;\n            }\n        }\n\n        string actions(N, '.');\n        for(auto& crane : cranes) if(crane.payload == -1) crane.task.type = NONE;\n            \n        vector<bool> container_is_tasked(N*N, false);\n        for(const auto& c : cranes) {\n            if (c.payload != -1) container_is_tasked[c.payload] = true;\n            if (c.task.type != NONE && c.task.container_id != -1) container_is_tasked[c.task.container_id] = true;\n        }\n\n        for (int k=0; k<N; ++k) {\n            if (cranes[k].bombed || cranes[k].payload != -1 || cranes[k].task.type != NONE) continue;\n            \n            Task best_task = {NONE}; int best_score = -1e9;\n\n            // Priority 1: Dispatch\n            int c_to_dispatch = dispatch_next[k];\n            if (c_to_dispatch < N*(k+1) && grid[k][N-1] == -1) {\n                if(container_pos[c_to_dispatch].r != -1 && container_pos[c_to_dispatch].r != -2 && !container_is_tasked[c_to_dispatch]) {\n                    Task current_task = {DISPATCH, c_to_dispatch, container_pos[c_to_dispatch], {k,N-1}};\n                    int score = 1000 - dist(cranes[k].pos, current_task.from);\n                    if (score > best_score) { best_score = score; best_task = current_task; }\n                }\n            }\n\n            // Priority 2: Unload (Crane 0 only)\n            if (k == 0) {\n                for (int r_from=0; r_from<N; ++r_from) if (grid[r_from][0] != -1) {\n                    int c = grid[r_from][0];\n                    if (!container_is_tasked[c]) {\n                        Pos best_to = {-1,-1}; int min_dist_to = 1e9;\n                        for(int r_to=0; r_to<N; ++r_to) for(int c_to=1; c_to<3; ++c_to) if(grid[r_to][c_to]==-1) {\n                            if (dist({r_from,0}, {r_to,c_to}) < min_dist_to) { min_dist_to = dist({r_from,0}, {r_to,c_to}); best_to = {r_to,c_to};}\n                        }\n                        if(best_to.r != -1) {\n                            Task current_task = {UNLOAD, c, {r_from,0}, best_to};\n                            int score = 500 - dist(cranes[k].pos, current_task.from);\n                            if (score > best_score) { best_score = score; best_task = current_task; }\n                        }\n                    }\n                }\n            }\n            \n            if (best_task.type != NONE) {\n                cranes[k].task = best_task;\n                if(best_task.container_id != -1) container_is_tasked[best_task.container_id] = true;\n            } else {\n                if (k > 0) {\n                     Pos idle_dest = {k, N-1};\n                     if(grid[idle_dest.r][idle_dest.c] != -1) idle_dest = {k, N-2};\n                     if(cranes[k].pos != idle_dest) cranes[k].task = {IDLE_MOVE, -1, {}, idle_dest};\n                }\n            }\n        }\n            \n        vector<Pos> future_pos(N); for(int i=0; i<N; ++i) future_pos[i] = cranes[i].pos;\n        for(int k=0; k<N; ++k) {\n            if (cranes[k].bombed) continue;\n            Pos target_pos = {-1, -1}; char terminal_action = '.'; const auto& task = cranes[k].task;\n            if (task.type != NONE) {\n                if (cranes[k].payload != -1) { target_pos = task.to; terminal_action = 'Q';} \n                else {\n                    target_pos = task.from; terminal_action = 'P';\n                    if (task.type == IDLE_MOVE) { target_pos = task.to; terminal_action = '.'; }\n                }\n            }\n            char planned_action;\n            if (target_pos.r == -1) planned_action = '.';\n            else if (cranes[k].pos == target_pos) { planned_action = (terminal_action == 'P' && (grid[target_pos.r][target_pos.c] != task.container_id || cranes[k].payload != -1)) ? '.' : terminal_action; } \n            else {\n                vector<vector<bool>> obstacles(N, vector<bool>(N, false));\n                for(int j=0; j<k; ++j) if (!cranes[j].bombed) obstacles[future_pos[j].r][future_pos[j].c] = true;\n                for(int j=k+1; j<N; ++j) if (!cranes[j].bombed) obstacles[cranes[j].pos.r][cranes[j].pos.c] = true;\n                if (cranes[k].payload != -1 && k > 0) { for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) if(grid[r][c]!=-1) obstacles[r][c] = true; }\n                planned_action = find_path_and_get_first_move(cranes[k].pos, target_pos, obstacles);\n            }\n            Pos next_p = get_next_pos(cranes[k].pos, planned_action);\n            bool is_swap = false;\n            for (int j=0; j<k; ++j) if (!cranes[j].bombed && next_p == cranes[j].pos && future_pos[j] == cranes[k].pos) is_swap = true;\n            actions[k] = is_swap ? '.' : planned_action;\n            future_pos[k] = get_next_pos(cranes[k].pos, actions[k]);\n        }\n        for(int i=1; i<N; ++i) if(!cranes[i].bombed && dispatch_next[i] >= N*(i+1) && cranes[i].payload == -1 && future_pos[0]!=cranes[i].pos) actions[i] = 'B';\n        \n        for (int i=0; i<N; ++i) history[i] += actions[i];\n        apply_actions_to_state(actions);\n        \n        for (int i=0; i<N; ++i) {\n            if (grid[i][N-1] != -1) {\n                int c = grid[i][N-1];\n                if (c/N==i && dispatch_next[i]==c) dispatch_next[i]++;\n                grid[i][N-1] = -1; container_pos[c] = {-1,-1}; dispatched_count++;\n            }\n        }\n    }\n    size_t max_len=0; for(const auto& s:history) max_len=max(max_len, s.length()); if(max_len==0)max_len=1;\n    for (int i=0; i<N; ++i) { history[i].resize(max_len, '.'); cout << history[i] << endl; }\n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <cmath>\n#include <map>\n#include <algorithm>\n#include <chrono>\n#include <random>\n\n#include <atcoder/mincostflow>\n\nusing namespace std;\n\n// --- Utilities ---\nstruct XorShift {\n    unsigned int x, y, z, w;\n    XorShift() : x(123456789), y(362436069), z(521288629), w(88675123) {}\n    unsigned int next() {\n        unsigned int t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));\n    }\n    int next_int(int upper) { return next() % upper; }\n    int next_int(int lower, int upper) { return lower + next() % (upper - lower + 1); }\n    double next_double() { return next() / 4294967295.0; }\n};\nXorShift rnd;\n\nauto start_time = chrono::steady_clock::now();\ndouble time_limit = 1.95;\n\nbool is_time_up() {\n    auto now = chrono::steady_clock::now();\n    double elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count() / 1000.0;\n    return elapsed > time_limit;\n}\n\n// --- Problem specific structures ---\nconst int N = 20;\nconst int SPLIT_THRESHOLD = 7;\n\nstruct Pos {\n    int r, c;\n};\n\nint manhattan_dist(const Pos& p1, const Pos& p2) {\n    return abs(p1.r - p2.r) + abs(p1.c - p2.c);\n}\n\nvector<Pos> sources, sinks;\nvector<int> source_supply, sink_demand;\n\nusing Plan = vector<vector<int>>;\nusing Stops = vector<pair<int, int>>;\n\nstruct TripResult {\n    long long cost = 0;\n    Pos end_pos;\n    vector<string> ops;\n};\n\n// --- Core Logic ---\n\nvoid optimize_tour(const Pos& start_pos, Stops& tour) {\n    if (tour.size() <= 2) return;\n\n    auto get_tour_dist = [&](const Stops& current_tour) {\n        long long d = 0;\n        Pos current_pos = start_pos;\n        for (const auto& stop : current_tour) {\n            d += manhattan_dist(current_pos, sinks[stop.first]);\n            current_pos = sinks[stop.first];\n        }\n        return d;\n    };\n    \n    int max_iter = min(400, (int)tour.size() * (int)tour.size() * 2);\n\n    for (int iter = 0; iter < max_iter; ++iter) {\n        int i = rnd.next_int(tour.size());\n        int j = rnd.next_int(tour.size());\n        if (i == j) continue;\n        if (i > j) swap(i, j);\n\n        Stops next_tour = tour;\n        reverse(next_tour.begin() + i, next_tour.begin() + j + 1);\n\n        if (get_tour_dist(next_tour) < get_tour_dist(tour)) {\n            tour = next_tour;\n        }\n    }\n}\n\nTripResult calculate_trip(Pos truck_pos, int s_idx, const Stops& stops, bool generate_ops) {\n    TripResult res;\n    res.end_pos = truck_pos;\n    if (stops.empty()) return res;\n\n    Pos s_pos = sources[s_idx];\n    res.cost += (long long)manhattan_dist(truck_pos, s_pos) * 100;\n    if (generate_ops) {\n        int dr = s_pos.r - truck_pos.r;\n        int dc = s_pos.c - truck_pos.c;\n        if (dr > 0) for(int i=0; i<dr; ++i) res.ops.push_back(\"D\");\n        if (dr < 0) for(int i=0; i<-dr; ++i) res.ops.push_back(\"U\");\n        if (dc > 0) for(int i=0; i<dc; ++i) res.ops.push_back(\"R\");\n        if (dc < 0) for(int i=0; i<-dc; ++i) res.ops.push_back(\"L\");\n    }\n    truck_pos = s_pos;\n\n    int total_load = 0;\n    for (const auto& stop : stops) total_load += stop.second;\n    res.cost += total_load;\n    if (generate_ops && total_load > 0) {\n        res.ops.push_back(\"+\" + to_string(total_load));\n    }\n    \n    Stops tour;\n    Stops remaining_stops = stops;\n    Pos nn_builder_pos = truck_pos;\n    while (!remaining_stops.empty()) {\n        auto best_it = remaining_stops.end();\n        int min_dist_t = 1e9;\n        for (auto it = remaining_stops.begin(); it != remaining_stops.end(); ++it) {\n            int d = manhattan_dist(nn_builder_pos, sinks[it->first]);\n            if (d < min_dist_t) {\n                min_dist_t = d;\n                best_it = it;\n            }\n        }\n        tour.push_back(*best_it);\n        nn_builder_pos = sinks[best_it->first];\n        remaining_stops.erase(best_it);\n    }\n    \n    optimize_tour(truck_pos, tour);\n\n    int truck_load = total_load;\n    for (const auto& stop : tour) {\n        Pos t_pos = sinks[stop.first];\n        res.cost += (long long)manhattan_dist(truck_pos, t_pos) * (100 + truck_load);\n        if (generate_ops) {\n            int dr = t_pos.r - truck_pos.r;\n            int dc = t_pos.c - truck_pos.c;\n            if (dr > 0) for(int i=0; i<dr; ++i) res.ops.push_back(\"D\");\n            if (dr < 0) for(int i=0; i<-dr; ++i) res.ops.push_back(\"U\");\n            if (dc > 0) for(int i=0; i<dc; ++i) res.ops.push_back(\"R\");\n            if (dc < 0) for(int i=0; i<-dc; ++i) res.ops.push_back(\"L\");\n            res.ops.push_back(\"-\" + to_string(stop.second));\n        }\n        res.cost += stop.second;\n        truck_load -= stop.second;\n        truck_pos = t_pos;\n    }\n    res.end_pos = truck_pos;\n    return res;\n}\n\nvector<Stops> split_stops(const Stops& stops) {\n    if (stops.size() < 2) return {stops};\n    \n    int s1 = -1, s2 = -1;\n    int max_d = -1;\n    for(size_t i=0; i<stops.size(); ++i) {\n        for(size_t j=i+1; j<stops.size(); ++j) {\n            int d = manhattan_dist(sinks[stops[i].first], sinks[stops[j].first]);\n            if (d > max_d) {\n                max_d = d;\n                s1 = stops[i].first;\n                s2 = stops[j].first;\n            }\n        }\n    }\n    \n    Stops c1, c2;\n    for(const auto& stop : stops) {\n        if (manhattan_dist(sinks[stop.first], sinks[s1]) < manhattan_dist(sinks[stop.first], sinks[s2])) {\n            c1.push_back(stop);\n        } else {\n            c2.push_back(stop);\n        }\n    }\n    if (c1.empty() || c2.empty()) return {stops};\n    return {c1, c2};\n}\n\nlong long evaluate(const Plan& plan, vector<string>* ops = nullptr) {\n    bool generate_ops = (ops != nullptr);\n    if (generate_ops) ops->clear();\n    \n    long long total_cost = 0;\n    Pos current_pos = {0, 0};\n\n    map<int, Stops> deliveries_by_source;\n    vector<int> active_sources_indices;\n    for (size_t s_idx = 0; s_idx < sources.size(); ++s_idx) {\n        bool has_delivery = false;\n        for (size_t t_idx = 0; t_idx < sinks.size(); ++t_idx) {\n            if (plan[s_idx][t_idx] > 0) {\n                deliveries_by_source[s_idx].push_back({(int)t_idx, plan[s_idx][t_idx]});\n                has_delivery = true;\n            }\n        }\n        if (has_delivery) {\n            active_sources_indices.push_back(s_idx);\n        }\n    }\n    \n    while (!active_sources_indices.empty()) {\n        int best_s_idx = -1;\n        int min_dist = 1e9;\n        size_t best_vec_idx = -1;\n        for (size_t i = 0; i < active_sources_indices.size(); ++i) {\n            int s_idx = active_sources_indices[i];\n            int d = manhattan_dist(current_pos, sources[s_idx]);\n            if (d < min_dist) {\n                min_dist = d;\n                best_s_idx = s_idx;\n                best_vec_idx = i;\n            }\n        }\n        \n        const auto& all_stops = deliveries_by_source.at(best_s_idx);\n        \n        bool do_split = false;\n        if (all_stops.size() >= SPLIT_THRESHOLD) {\n            auto clusters = split_stops(all_stops);\n            if (clusters.size() == 2) {\n                long long cost_single = calculate_trip(current_pos, best_s_idx, all_stops, false).cost;\n                TripResult trip1_res = calculate_trip(current_pos, best_s_idx, clusters[0], false);\n                TripResult trip2_res = calculate_trip(trip1_res.end_pos, best_s_idx, clusters[1], false);\n                if (trip1_res.cost + trip2_res.cost < cost_single) {\n                    do_split = true;\n                }\n            }\n        }\n\n        if (do_split) {\n            auto clusters = split_stops(all_stops);\n            TripResult trip1_res = calculate_trip(current_pos, best_s_idx, clusters[0], generate_ops);\n            total_cost += trip1_res.cost;\n            if (generate_ops) ops->insert(ops->end(), trip1_res.ops.begin(), trip1_res.ops.end());\n            current_pos = trip1_res.end_pos;\n\n            TripResult trip2_res = calculate_trip(current_pos, best_s_idx, clusters[1], generate_ops);\n            total_cost += trip2_res.cost;\n            if (generate_ops) ops->insert(ops->end(), trip2_res.ops.begin(), trip2_res.ops.end());\n            current_pos = trip2_res.end_pos;\n        } else {\n            TripResult trip_res = calculate_trip(current_pos, best_s_idx, all_stops, generate_ops);\n            total_cost += trip_res.cost;\n            if (generate_ops) ops->insert(ops->end(), trip_res.ops.begin(), trip_res.ops.end());\n            current_pos = trip_res.end_pos;\n        }\n\n        active_sources_indices.erase(active_sources_indices.begin() + best_vec_idx);\n    }\n    return total_cost;\n}\n\nvoid solve() {\n    vector<vector<int>> h(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> h[i][j];\n            if (h[i][j] > 0) {\n                sources.push_back({i, j});\n                source_supply.push_back(h[i][j]);\n            } else if (h[i][j] < 0) {\n                sinks.push_back({i, j});\n                sink_demand.push_back(-h[i][j]);\n            }\n        }\n    }\n    \n    if (sources.empty()) return;\n\n    int num_s = sources.size();\n    int num_t = sinks.size();\n    atcoder::mcf_graph<int, int> g(num_s + num_t + 2);\n    int S_node = num_s + num_t;\n    int T_node = S_node + 1;\n\n    long long total_supply_val = 0;\n    for (int i = 0; i < num_s; ++i) {\n        g.add_edge(S_node, i, source_supply[i], 0);\n        total_supply_val += source_supply[i];\n    }\n    for (int i = 0; i < num_t; ++i) {\n        g.add_edge(num_s + i, T_node, sink_demand[i], 0);\n    }\n    for (int i = 0; i < num_s; ++i) {\n        for (int j = 0; j < num_t; ++j) {\n            g.add_edge(i, num_s + j, 1e9, manhattan_dist(sources[i], sinks[j]));\n        }\n    }\n    \n    g.flow(S_node, T_node, total_supply_val);\n    \n    Plan current_plan(num_s, vector<int>(num_t, 0));\n    for (const auto& e : g.edges()) {\n        if (e.from >= 0 && e.from < num_s && e.to >= num_s && e.to < num_s + num_t) {\n            if (e.flow > 0) {\n                current_plan[e.from][e.to-num_s] = e.flow;\n            }\n        }\n    }\n\n    Plan best_plan = current_plan;\n    long long best_cost = evaluate(best_plan);\n    long long current_cost = best_cost;\n    \n    double start_temp = 5000, end_temp = 10;\n    \n    while (!is_time_up()) {\n        double elapsed_ratio = chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count() / 1000.0 / time_limit;\n        double temp = start_temp * pow(end_temp / start_temp, elapsed_ratio);\n\n        int s1 = rnd.next_int(num_s);\n        int s2 = rnd.next_int(num_s);\n        int t1 = rnd.next_int(num_t);\n        int t2 = rnd.next_int(num_t);\n\n        if (s1 == s2 || t1 == t2) continue;\n        \n        int amount1 = current_plan[s1][t1];\n        int amount2 = current_plan[s2][t2];\n        if (amount1 == 0 || amount2 == 0) continue;\n        \n        int d = rnd.next_int(1, min(amount1, amount2));\n        \n        Plan new_plan = current_plan;\n        new_plan[s1][t1] -= d;\n        new_plan[s2][t2] -= d;\n        new_plan[s1][t2] += d;\n        new_plan[s2][t1] += d;\n\n        long long new_cost = evaluate(new_plan);\n        \n        if (new_cost < current_cost || rnd.next_double() < exp((double)(current_cost - new_cost) / temp)) {\n            current_plan = new_plan;\n            current_cost = new_cost;\n            if (current_cost < best_cost) {\n                best_cost = current_cost;\n                best_plan = current_plan;\n            }\n        }\n    }\n    \n    vector<string> ops;\n    evaluate(best_plan, &ops);\n    for (const auto& op : ops) {\n        cout << op << '\\n';\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    int N_dummy;\n    cin >> N_dummy;\n    solve();\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n#include <random>\n#include <unordered_set>\n\n// --- Constants ---\nconstexpr int N = 6;\nconstexpr int M = 15;\nconstexpr int T = 10;\nconstexpr int SEED_COUNT = 2 * N * (N - 1); // 60\nconstexpr int GRID_SIZE = N * N;             // 36\nconstexpr long long TIME_LIMIT_MS = 190;\nconstexpr int TOP_K_SELECTION = 3; // Consider top K seeds for each criterion\n\n// --- Type Definitions ---\nstruct Seed {\n    int id;\n    std::vector<int> x;\n    int total_value;\n};\n\n// --- Global State ---\nstd::vector<Seed> current_seeds;\nstd::mt19937 rng;\nauto turn_start_time = std::chrono::high_resolution_clock::now();\n\n// --- Helper Functions ---\nvoid read_seeds() {\n    current_seeds.assign(SEED_COUNT, Seed());\n    for (int i = 0; i < SEED_COUNT; ++i) {\n        current_seeds[i].id = i;\n        current_seeds[i].x.resize(M);\n        current_seeds[i].total_value = 0;\n        for (int j = 0; j < M; ++j) {\n            std::cin >> current_seeds[i].x[j];\n            current_seeds[i].total_value += current_seeds[i].x[j];\n        }\n    }\n}\n\n// --- Core Logic for a Single Turn ---\nvoid solve_turn() {\n    // 1. REFINED SEED SELECTION: \"Top-K\" strategy\n    // This strategy selects seeds based on how many times they appear in the\n    // top K for any criterion. This prioritizes seeds that are champions or\n    // strong contenders in one or more areas, increasing the chance of\n    // combining multiple high-value traits.\n    \n    std::vector<int> top_K_counts(SEED_COUNT, 0);\n    std::vector<std::pair<int, int>> ranked_seeds(SEED_COUNT);\n\n    for (int j = 0; j < M; ++j) {\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            ranked_seeds[i] = {current_seeds[i].x[j], i};\n        }\n        std::sort(ranked_seeds.rbegin(), ranked_seeds.rend());\n        \n        for (int k = 0; k < TOP_K_SELECTION; ++k) {\n            top_K_counts[ranked_seeds[k].second]++;\n        }\n    }\n\n    std::vector<int> all_indices(SEED_COUNT);\n    std::iota(all_indices.begin(), all_indices.end(), 0);\n\n    // Sort all seeds by their top-K appearance count, then by total value as a tie-breaker.\n    std::sort(all_indices.begin(), all_indices.end(), [&](int a, int b) {\n        if (top_K_counts[a] != top_K_counts[b]) {\n            return top_K_counts[a] > top_K_counts[b];\n        }\n        return current_seeds[a].total_value > current_seeds[b].total_value;\n    });\n\n    std::vector<int> seeds_to_plant_indices;\n    seeds_to_plant_indices.reserve(GRID_SIZE);\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        seeds_to_plant_indices.push_back(all_indices[i]);\n    }\n\n    // 2. PLACEMENT using SIMULATED ANNEALING\n    \n    // Pre-calculate desirability for all pairs of selected seeds.\n    std::vector<std::vector<double>> desirability_cache(GRID_SIZE, std::vector<double>(GRID_SIZE));\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = i; j < GRID_SIZE; ++j) {\n            int seed_idx1 = seeds_to_plant_indices[i];\n            int seed_idx2 = seeds_to_plant_indices[j];\n            double d = 0;\n            for (int k = 0; k < M; ++k) {\n                d += std::max(current_seeds[seed_idx1].x[k], current_seeds[seed_idx2].x[k]);\n            }\n            desirability_cache[i][j] = desirability_cache[j][i] = d;\n        }\n    }\n\n    // Initialize with a random placement.\n    std::vector<int> p_indices(GRID_SIZE);\n    std::iota(p_indices.begin(), p_indices.end(), 0);\n    std::shuffle(p_indices.begin(), p_indices.end(), rng);\n\n    std::vector<std::vector<int>> current_placement(N, std::vector<int>(N));\n    for(int i = 0; i < GRID_SIZE; ++i) {\n        current_placement[i/N][i%N] = p_indices[i];\n    }\n    \n    auto calculate_total_desirability = [&](const auto& placement) {\n        double total_d = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (i + 1 < N) total_d += desirability_cache[placement[i][j]][placement[i + 1][j]];\n                if (j + 1 < N) total_d += desirability_cache[placement[i][j]][placement[i][j + 1]];\n            }\n        }\n        return total_d;\n    };\n    \n    double current_desirability = calculate_total_desirability(current_placement);\n    auto best_placement = current_placement;\n    double best_desirability = current_desirability;\n    \n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n\n    // Fast delta calculation for a swap move.\n    auto calculate_delta = [&](int r1, int c1, int r2, int c2) {\n        double delta = 0;\n        int s1_idx = current_placement[r1][c1];\n        int s2_idx = current_placement[r2][c2];\n\n        for (int k=0; k<4; ++k) {\n            int nr = r1 + dr[k], nc = c1 + dc[k];\n            if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n            if (nr == r2 && nc == c2) continue;\n            int neighbor_idx = current_placement[nr][nc];\n            delta += desirability_cache[s2_idx][neighbor_idx] - desirability_cache[s1_idx][neighbor_idx];\n        }\n        for (int k=0; k<4; ++k) {\n            int nr = r2 + dr[k], nc = c2 + dc[k];\n            if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n            if (nr == r1 && nc == c1) continue;\n            int neighbor_idx = current_placement[nr][nc];\n            delta += desirability_cache[s1_idx][neighbor_idx] - desirability_cache[s2_idx][neighbor_idx];\n        }\n        return delta;\n    };\n\n    // Auto-tune starting temperature.\n    double T_start = 2000.0, T_end = 0.1;\n    double avg_bad_delta = 0;\n    int bad_move_count = 0;\n    std::uniform_int_distribution<> dis_pos(0, GRID_SIZE - 1);\n    for (int i = 0; i < 500; ++i) { // Increased samples for better tuning\n        int p1_idx = dis_pos(rng), p2_idx = dis_pos(rng);\n        if (p1_idx == p2_idx) continue;\n        double delta = calculate_delta(p1_idx / N, p1_idx % N, p2_idx / N, p2_idx % N);\n        if (delta < 0) {\n            avg_bad_delta += -delta;\n            bad_move_count++;\n        }\n    }\n    if (bad_move_count > 0) {\n        avg_bad_delta /= bad_move_count;\n        T_start = avg_bad_delta / log(2.0);\n    }\n\n    std::uniform_real_distribution<double> accept_dis(0.0, 1.0);\n    int iter_count = 0;\n    while (true) {\n        iter_count++;\n        if (iter_count % 1024 == 0) {\n            if (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - turn_start_time).count() > TIME_LIMIT_MS) break;\n        }\n\n        double progress = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - turn_start_time).count() / (double)TIME_LIMIT_MS;\n        if (progress >= 1.0) break;\n        double temp = T_start * std::pow(T_end / T_start, progress);\n\n        int p1_idx = dis_pos(rng), p2_idx = dis_pos(rng);\n        if (p1_idx == p2_idx) continue;\n\n        int r1 = p1_idx / N, c1 = p1_idx % N;\n        int r2 = p2_idx / N, c2 = p2_idx % N;\n        \n        double delta_desirability = calculate_delta(r1, c1, r2, c2);\n        \n        if (delta_desirability > 0 || (temp > 1e-9 && accept_dis(rng) < std::exp(delta_desirability / temp))) {\n            std::swap(current_placement[r1][c1], current_placement[r2][c2]);\n            current_desirability += delta_desirability;\n            if (current_desirability > best_desirability) {\n                best_desirability = current_desirability;\n                best_placement = current_placement;\n            }\n        }\n    }\n\n    // 3. OUTPUT the best placement found.\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int placement_idx = best_placement[i][j];\n            int seed_id_to_print = seeds_to_plant_indices[placement_idx];\n            std::cout << seed_id_to_print << (j == N - 1 ? \"\" : \" \");\n        }\n        std::cout << std::endl;\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    rng.seed(std::chrono::steady_clock::now().time_since_epoch().count());\n    \n    int n_in, m_in, t_in;\n    std::cin >> n_in >> m_in >> t_in;\n\n    read_seeds();\n\n    for (int t = 0; t < T; ++t) {\n        turn_start_time = std::chrono::high_resolution_clock::now();\n        solve_turn();\n        if (t < T - 1) {\n            read_seeds();\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <set>\n#include <map>\n#include <tuple>\n#include <chrono>\n#include <functional>\n\n#include <atcoder/mincostflow>\n\nusing namespace std;\n\n// --- Utilities ---\nstruct Timer {\n    chrono::steady_clock::time_point start_time;\n    Timer() { start_time = chrono::steady_clock::now(); }\n    double get_elapsed_time() const {\n        return chrono::duration_cast<chrono::duration<double>>(chrono::steady_clock::now() - start_time).count();\n    }\n};\n\nstruct Point {\n    int r, c;\n    bool operator<(const Point& other) const { return tie(r, c) < tie(other.r, other.c); }\n    bool operator==(const Point& other) const { return r == other.r && c == other.c; }\n};\n\nPoint operator+(const Point& a, const Point& b) { return {a.r + b.r, a.c + b.c}; }\nPoint operator-(const Point& a, const Point& b) { return {a.r - b.r, a.c - b.c}; }\nPoint operator*(const Point& p, int scalar) { return {p.r * scalar, p.c * scalar}; }\nint manhattan(const Point& a, const Point& b) { return abs(a.r - b.r) + abs(a.c - b.c); }\n\nconst Point DIRS[] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};\nconst char MOVE_CHARS[] = {'U', 'R', 'D', 'L'};\nconst Point REL_DIRS[] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};\n\nint N, M, V;\n\nstruct Arm {\n    int v_count;\n    Point root_pos;\n    vector<int> parent, length;\n    vector<vector<int>> children;\n    vector<int> edge_dir;\n    vector<Point> abs_pos;\n    vector<int> finger_indices;\n\n    Arm(int v, Point root, const vector<pair<int, int>>& edges) : v_count(v), root_pos(root) {\n        parent.assign(v, -1); length.assign(v, 0); children.assign(v, vector<int>());\n        edge_dir.assign(v, 0); abs_pos.resize(v);\n        for(int i = 1; i < v; ++i) {\n            parent[i] = edges[i-1].first; length[i] = edges[i-1].second;\n            children[parent[i]].push_back(i);\n        }\n        for (int i = 0; i < v; ++i) if (children[i].empty()) finger_indices.push_back(i);\n        update_abs_pos();\n    }\n    void update_abs_pos() {\n        abs_pos[0] = root_pos;\n        vector<int> q = {0};\n        for(size_t i = 0; i < q.size(); ++i) {\n            int u = q[i];\n            for(int v : children[u]) {\n                abs_pos[v] = abs_pos[u] + (REL_DIRS[edge_dir[v]] * length[v]);\n                q.push_back(v);\n            }\n        }\n    }\n    void apply_command(const string& cmd) {\n        if (cmd[0] == 'U') root_pos.r--; else if (cmd[0] == 'D') root_pos.r++;\n        else if (cmd[0] == 'L') root_pos.c--; else if (cmd[0] == 'R') root_pos.c++;\n        for (int i = 1; i < v_count; ++i) {\n            if (cmd[i] == 'L') edge_dir[i] = (edge_dir[i] + 3) % 4;\n            else if (cmd[i] == 'R') edge_dir[i] = (edge_dir[i] + 1) % 4;\n        }\n        update_abs_pos();\n    }\n};\n\nstruct GameState {\n    Arm arm;\n    set<Point> sources_left;\n    map<int, Point> held_by_finger;\n    map<Point, Point> s_to_t_map;\n    GameState(Arm a, set<Point> s, map<Point, Point> stm) : arm(a), sources_left(s), s_to_t_map(stm) {}\n};\n\nstruct TargetConfig {\n    bool is_pickup; Point root_pos; vector<int> edge_dirs;\n    map<int, Point> finger_assignments; double value = -1e18;\n};\n\nTargetConfig find_best_config(const GameState& state, bool is_pickup, const Timer& timer, double time_limit) {\n    TargetConfig best_config; best_config.is_pickup = is_pickup;\n    \n    set<Point> anchor_tasks;\n    vector<Point> tasks;\n    if (is_pickup) {\n        if (state.sources_left.empty()) return best_config;\n        tasks.assign(state.sources_left.begin(), state.sources_left.end());\n    } else {\n        if (state.held_by_finger.empty()) return best_config;\n        for(auto const& [f,s]:state.held_by_finger) tasks.push_back(state.s_to_t_map.at(s));\n    }\n    \n    long long sum_r=0, sum_c=0; for(auto p:tasks) {sum_r+=p.r; sum_c+=p.c;}\n    Point centroid = {(int)round((double)sum_r/tasks.size()), (int)round((double)sum_c/tasks.size())};\n    \n    vector<pair<int, Point>> sorted_by_root, sorted_by_centroid;\n    sorted_by_root.reserve(tasks.size());\n    sorted_by_centroid.reserve(tasks.size());\n    for(auto const& t : tasks){\n        sorted_by_root.push_back({manhattan(state.arm.root_pos, t), t});\n        sorted_by_centroid.push_back({manhattan(centroid, t), t});\n    }\n    const int K_ANCHORS = 15;\n    if (sorted_by_root.size() > K_ANCHORS) {\n        partial_sort(sorted_by_root.begin(), sorted_by_root.begin() + K_ANCHORS, sorted_by_root.end());\n        partial_sort(sorted_by_centroid.begin(), sorted_by_centroid.begin() + K_ANCHORS, sorted_by_centroid.end());\n    }\n    for(int i=0; i<min((int)sorted_by_root.size(), K_ANCHORS); ++i) anchor_tasks.insert(sorted_by_root[i].second);\n    for(int i=0; i<min((int)sorted_by_centroid.size(), K_ANCHORS); ++i) anchor_tasks.insert(sorted_by_centroid[i].second);\n    \n    for (const Point& p_anchor : anchor_tasks) {\n        if (timer.get_elapsed_time() > time_limit) break;\n        for (int f_anchor_idx : state.arm.finger_indices) {\n            if (state.arm.parent[f_anchor_idx] != 0) continue;\n            for (int dir = 0; dir < 4; ++dir) {\n                Point cand_root_pos = p_anchor - (REL_DIRS[dir] * state.arm.length[f_anchor_idx]);\n                map<int, Point> assignments; vector<int> cand_dirs(state.arm.v_count, 0); int score = 0;\n                set<Point> used_locs;\n\n                for(int f_idx : state.arm.finger_indices) {\n                    for (int f_dir = 0; f_dir < 4; ++f_dir) {\n                        Point f_pos = cand_root_pos + (REL_DIRS[f_dir] * state.arm.length[f_idx]);\n                        bool can_use = false;\n                        if(is_pickup){\n                            if(state.sources_left.count(f_pos) && !state.held_by_finger.count(f_idx)) can_use = true;\n                        } else {\n                            for(auto const& [held_f, held_s] : state.held_by_finger) {\n                                if(held_f == f_idx && state.s_to_t_map.at(held_s) == f_pos) { can_use = true; break;}\n                            }\n                        }\n                        if(can_use && !used_locs.count(f_pos)) {\n                            assignments[f_idx] = f_pos; cand_dirs[f_idx] = f_dir;\n                            score++; used_locs.insert(f_pos);\n                            break;\n                        }\n                    }\n                }\n                \n                int dist_cost = manhattan(state.arm.root_pos, cand_root_pos);\n                double value = (double)score * score * 100.0 - dist_cost;\n                if (value > best_config.value) {\n                    best_config.value = value; best_config.root_pos = cand_root_pos;\n                    best_config.finger_assignments = assignments; best_config.edge_dirs = cand_dirs;\n                }\n            }\n        }\n    }\n    return best_config;\n}\n\nstring get_next_command(const GameState& state, const TargetConfig& target) {\n    Arm arm = state.arm; string command(2 * arm.v_count, '.');\n    bool at_config = (arm.root_pos == target.root_pos);\n    if(at_config) for (auto const& [f,p]:target.finger_assignments) if(arm.edge_dir[f] != target.edge_dirs[f]) at_config=false;\n    if (at_config) { for(auto const& [f,p]:target.finger_assignments) command[arm.v_count+f]='P'; return command; }\n    \n    char best_move = '.'; int min_dist = manhattan(arm.root_pos, target.root_pos);\n    if(min_dist > 0) for (int i=0; i<4; ++i) { Point new_pos = arm.root_pos + DIRS[i]; if(new_pos.r>=0&&new_pos.r<N&&new_pos.c>=0&&new_pos.c<N&&manhattan(new_pos, target.root_pos)<min_dist) { min_dist=manhattan(new_pos, target.root_pos); best_move=MOVE_CHARS[i]; } }\n    command[0] = best_move;\n\n    for(int i=1; i<arm.v_count; ++i) {\n        if(arm.parent[i] != 0 || !target.finger_assignments.count(i)) continue;\n        int cur_dir = arm.edge_dir[i]; int tar_dir = target.edge_dirs[i];\n        if (cur_dir == tar_dir) continue;\n        if ((cur_dir + 1) % 4 == tar_dir) command[i] = 'R';\n        else if ((cur_dir + 3) % 4 == tar_dir) command[i] = 'L';\n        else command[i] = 'R'; \n    }\n    return command;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false); cin.tie(NULL); Timer timer;\n    cin >> N >> M >> V;\n    set<Point> sources, targets;\n    for (int i=0; i<N; ++i) { string r; cin>>r; for (int j=0; j<N; ++j) if (r[j]=='1') sources.insert({i, j}); }\n    for (int i=0; i<N; ++i) { string r; cin>>r; for (int j=0; j<N; ++j) if (r[j]=='1') targets.insert({i, j}); }\n\n    int v_to_use = V; vector<pair<int, int>> edges;\n    int num_fingers = v_to_use > 1 ? v_to_use - 1 : 0;\n    if (num_fingers > 0) {\n        int L_small = 1, L_large = max(2, (int)round(N/3.0));\n        for(int i=0; i < num_fingers/2; ++i) edges.push_back({0, L_small});\n        for(int i=0; i < num_fingers-num_fingers/2; ++i) edges.push_back({0, L_large});\n    }\n    \n    long long sr=0,sc=0; for(auto p:sources) { sr+=p.r; sc+=p.c; }\n    Point initial_root = {(int)round((double)sr/M), (int)round((double)sc/M)};\n    cout << v_to_use << endl; for (auto e:edges) cout << e.first << \" \" << e.second << endl; cout << initial_root.r << \" \" << initial_root.c << endl;\n\n    map<Point, Point> s_to_t_map;\n    vector<Point> s_vec(sources.begin(), sources.end()), t_vec(targets.begin(), targets.end());\n    atcoder::mcf_graph<int, int> g(2*M+2); int S=2*M, T=2*M+1;\n    for (int i=0; i<M; ++i) { g.add_edge(S, i, 1, 0); g.add_edge(M+i, T, 1, 0); for (int j=0; j<M; ++j) g.add_edge(i, M+j, 1, manhattan(s_vec[i],t_vec[j])); }\n    g.flow(S, T, M);\n    for (auto e:g.edges()) if (e.from<M && e.to>=M && e.to<2*M && e.flow>0) s_to_t_map[s_vec[e.from]]=t_vec[e.to-M];\n\n    GameState state(Arm(v_to_use, initial_root, edges), sources, s_to_t_map);\n    TargetConfig current_target; int plan_life = 0; const double TIME_LIMIT = 2.95;\n\n    for (int turn=0; turn<100000; ++turn) {\n        if (state.sources_left.empty() && state.held_by_finger.empty() || timer.get_elapsed_time() > TIME_LIMIT) break;\n        if (plan_life <= 0) {\n            TargetConfig pickup_cfg;\n            if (state.held_by_finger.size() < state.arm.finger_indices.size()) {\n                pickup_cfg = find_best_config(state, true, timer, TIME_LIMIT);\n            }\n\n            TargetConfig dropoff_cfg;\n            if (!state.held_by_finger.empty()) {\n                dropoff_cfg = find_best_config(state, false, timer, TIME_LIMIT);\n            }\n\n            TargetConfig best_cfg = pickup_cfg.value >= dropoff_cfg.value ? pickup_cfg : dropoff_cfg;\n            \n            if (best_cfg.value > 0) {\n                current_target = best_cfg;\n                plan_life = manhattan(state.arm.root_pos, current_target.root_pos) + 3;\n            } else { cout << string(2 * v_to_use, '.') << endl; continue; }\n        }\n        string cmd = get_next_command(state, current_target); cout << cmd << endl;\n        state.arm.apply_command(cmd);\n        \n        bool acted = false;\n        for (int i=0; i<v_to_use; ++i) if (cmd[v_to_use+i]=='P') {\n            acted = true;\n            Point p = state.arm.abs_pos[i];\n            if (current_target.is_pickup) {\n                state.sources_left.erase(p); state.held_by_finger[i]=p;\n            } else {\n                state.held_by_finger.erase(i);\n            }\n        }\n        if(acted) plan_life=0; else if (plan_life > 0) plan_life--;\n    }\n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n#include <random>\n#include <set>\n#include <map>\n#include <queue>\n\n#ifndef M_PI\n#define M_PI 3.14159265358979323846\n#endif\n\n// --- Utilities ---\nstruct Point {\n    int x, y;\n    bool operator<(const Point& other) const {\n        if (x != other.x) return x < other.x;\n        return y < other.y;\n    }\n     bool operator==(const Point& other) const {\n        return x == other.x && y == other.y;\n    }\n};\n\nlong long cross_product(Point a, Point b, Point c) {\n    return (long long)(b.x - a.x) * (c.y - a.y) - (long long)(b.y - a.y) * (c.x - a.x);\n}\n\n// Global timer\nstd::chrono::high_resolution_clock::time_point start_time;\n\n// --- Polygon Utilities ---\nstruct Polygon {\n    std::vector<Point> vertices;\n\n    bool is_inside(Point p) const {\n        if (vertices.empty()) return false;\n        int n = vertices.size();\n        bool inside = false;\n        for (int i = 0; i < n; ++i) {\n            const Point& p1 = vertices[i];\n            const Point& p2 = vertices[(i + 1) % n];\n            \n            if (p1.y == p2.y && p.y == p1.y && p.x >= std::min(p1.x, p2.x) && p.x <= std::max(p1.x, p2.x)) {\n                return true;\n            }\n            if (p1.x == p2.x && p.x == p1.x && p.y >= std::min(p1.y, p2.y) && p.y <= std::max(p1.y, p2.y)) {\n                return true;\n            }\n\n            if ((p1.y > p.y) != (p2.y > p.y)) {\n                double intersect_x = (double)(p2.x - p1.x) * (p.y - p1.y) / (double)(p2.y - p1.y) + p1.x;\n                if (p.x < intersect_x) {\n                    inside = !inside;\n                }\n            }\n        }\n        return inside;\n    }\n\n    long long calculate_perimeter() const {\n        if (vertices.size() < 2) return 0;\n        long long p = 0;\n        for (size_t i = 0; i < vertices.size(); ++i) {\n            const auto& v1 = vertices[i];\n            const auto& v2 = vertices[(i + 1) % vertices.size()];\n            p += std::abs(v1.x - v2.x) + std::abs(v1.y - v2.y);\n        }\n        return p;\n    }\n};\n\n// --- Problem Data ---\nint N;\nstd::vector<Point> mackerels;\nstd::vector<Point> sardines;\n\n// --- Main Algorithm ---\n\nusing GridPoint = std::pair<int, int>;\nconst int DX[] = {0, 1, 0, -1};\nconst int DY[] = {1, 0, -1, 0};\n\nPolygon generate_polygon_from_cells(const std::set<GridPoint>& cells, int cell_size) {\n    if (cells.empty()) return Polygon{};\n\n    std::map<Point, std::vector<Point>> adj;\n    for (const auto& cell : cells) {\n        int gx = cell.first;\n        int gy = cell.second;\n        Point p00 = {gx * cell_size, gy * cell_size};\n        Point p10 = {(gx + 1) * cell_size, gy * cell_size};\n        Point p01 = {gx * cell_size, (gy + 1) * cell_size};\n        Point p11 = {(gx + 1) * cell_size, (gy + 1) * cell_size};\n\n        if (cells.find({gx, gy + 1}) == cells.end()) { adj[p01].push_back(p11); adj[p11].push_back(p01); }\n        if (cells.find({gx, gy - 1}) == cells.end()) { adj[p10].push_back(p00); adj[p00].push_back(p10); }\n        if (cells.find({gx + 1, gy}) == cells.end()) { adj[p11].push_back(p10); adj[p10].push_back(p11); }\n        if (cells.find({gx - 1, gy}) == cells.end()) { adj[p00].push_back(p01); adj[p01].push_back(p00); }\n    }\n\n    if (adj.empty()) return Polygon{};\n\n    Point start_node = adj.begin()->first;\n     for(const auto& [p, _] : adj) {\n        if (p.y < start_node.y || (p.y == start_node.y && p.x < start_node.x)) {\n            start_node = p;\n        }\n    }\n\n    std::vector<Point> vertices;\n    Point current_node = start_node;\n    Point prev_node = {start_node.x, start_node.y - 1};\n\n    for (size_t i = 0; i < 2 * adj.size() + 5; ++i) {\n        vertices.push_back(current_node);\n        auto& neighbors = adj.at(current_node);\n\n        Point next_node = {-1, -1};\n        double best_delta_angle = 4 * M_PI;\n        double prev_angle = atan2(prev_node.y - current_node.y, prev_node.x - current_node.x);\n\n        for (const auto& neighbor : neighbors) {\n            double angle = atan2(neighbor.y - current_node.y, neighbor.x - current_node.x);\n            double delta_angle = prev_angle - angle;\n            if (delta_angle <= 1e-9) delta_angle += 2 * M_PI;\n            if (delta_angle < best_delta_angle) {\n                best_delta_angle = delta_angle;\n                next_node = neighbor;\n            }\n        }\n\n        if (next_node.x == -1) return Polygon{};\n        \n        prev_node = current_node;\n        current_node = next_node;\n        if (current_node == start_node) break;\n    }\n    \n    if (vertices.size() > 2) {\n        std::vector<Point> simplified;\n        for (size_t i = 0; i < vertices.size(); ++i) {\n            Point current_vertex = vertices[i];\n            if (simplified.size() < 2) {\n                simplified.push_back(current_vertex);\n            } else {\n                Point p_prev = simplified[simplified.size() - 2];\n                Point p_mid = simplified.back();\n                if (cross_product(p_prev, p_mid, current_vertex) == 0) {\n                    simplified.back() = current_vertex;\n                } else {\n                    simplified.push_back(current_vertex);\n                }\n            }\n        }\n        while (simplified.size() >= 3) {\n            Point p_prev = simplified[simplified.size() - 2];\n            Point p_mid = simplified.back();\n            Point p_curr = simplified.front();\n            if (cross_product(p_prev, p_mid, p_curr) == 0) {\n                simplified.pop_back();\n            } else {\n                break;\n            }\n        }\n         while (simplified.size() >= 3) {\n            Point p_prev = simplified.back();\n            Point p_mid = simplified.front();\n            Point p_curr = simplified[1];\n            if (cross_product(p_prev, p_mid, p_curr) == 0) {\n                simplified.front() = simplified.back();\n                simplified.pop_back();\n            } else {\n                break;\n            }\n        }\n        vertices = simplified;\n    }\n    return Polygon{vertices};\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    start_time = std::chrono::high_resolution_clock::now();\n\n    std::cin >> N;\n    mackerels.resize(N);\n    sardines.resize(N);\n    for (int i = 0; i < N; ++i) std::cin >> mackerels[i].x >> mackerels[i].y;\n    for (int i = 0; i < N; ++i) std::cin >> sardines[i].x >> sardines[i].y;\n    \n    int best_a = 0, best_b = 0;\n    Polygon best_polygon;\n    \n    std::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n    std::vector<int> cell_sizes = {1000, 500, 250, 200};\n    \n    for (size_t grid_idx = 0; grid_idx < cell_sizes.size(); ++grid_idx) {\n        int cell_size = cell_sizes[grid_idx];\n        long long time_limit_ms = 1950 * (grid_idx + 1) / cell_sizes.size();\n        \n        int grid_dim_x = 100001 / cell_size + 2;\n        int grid_dim_y = 100001 / cell_size + 2;\n        std::vector<std::vector<int>> grid_scores(grid_dim_x, std::vector<int>(grid_dim_y, 0));\n\n        for (const auto& p : mackerels) grid_scores[p.x / cell_size][p.y / cell_size]++;\n        for (const auto& s : sardines) grid_scores[s.x / cell_size][s.y / cell_size]--;\n        \n        std::vector<GridPoint> positive_cells;\n        for (int gx = 0; gx < grid_dim_x; ++gx) {\n            for (int gy = 0; gy < grid_dim_y; ++gy) {\n                if (grid_scores[gx][gy] > 0) {\n                    positive_cells.push_back({gx, gy});\n                }\n            }\n        }\n        std::sort(positive_cells.begin(), positive_cells.end(), [&](const GridPoint& a, const GridPoint& b){\n            return grid_scores[a.first][a.second] > grid_scores[b.first][b.second];\n        });\n\n        std::vector<std::vector<bool>> visited(grid_dim_x, std::vector<bool>(grid_dim_y, false));\n        int components_processed = 0;\n        \n        for (const auto& start_cell : positive_cells) {\n            if (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start_time).count() > time_limit_ms) break;\n            if (components_processed > 20) break;\n\n            int gx = start_cell.first;\n            int gy = start_cell.second;\n\n            if (!visited[gx][gy]) {\n                components_processed++;\n                std::set<GridPoint> component_cells;\n                std::queue<GridPoint> q;\n\n                q.push({gx, gy});\n                visited[gx][gy] = true;\n                long long initial_comp_score = 0;\n                while (!q.empty()) {\n                    GridPoint curr = q.front(); q.pop();\n                    component_cells.insert(curr);\n                    initial_comp_score += grid_scores[curr.first][curr.second];\n                    for (int i = 0; i < 4; ++i) {\n                        GridPoint next = {curr.first + DX[i], curr.second + DY[i]};\n                        if (next.first >= 0 && next.first < grid_dim_x && next.second >= 0 && next.second < grid_dim_y &&\n                            !visited[next.first][next.second] && grid_scores[next.first][next.second] > 0) {\n                            visited[next.first][next.second] = true;\n                            q.push(next);\n                        }\n                    }\n                }\n                if (component_cells.empty()) continue;\n\n                std::vector<GridPoint> cells_vec(component_cells.begin(), component_cells.end());\n                std::map<GridPoint, int> cell_to_idx;\n                for(size_t i=0; i<cells_vec.size(); ++i) cell_to_idx[cells_vec[i]] = i;\n                \n                double T_start = std::max(1.0, (double)initial_comp_score / 3.0);\n                double T_end = 0.01;\n                double T = T_start;\n                \n                int max_iter = 12000;\n                for(int iter = 0; iter < max_iter; ++iter) {\n                    if (iter % 128 == 0) {\n                        T = T_start * pow(T_end / T_start, (double)iter / max_iter);\n                        if (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start_time).count() > time_limit_ms) break;\n                    }\n                    if (cells_vec.empty()) break;\n                    \n                    std::uniform_int_distribution<int> dist_cell_idx(0, cells_vec.size() - 1);\n                    GridPoint rand_cell = cells_vec[dist_cell_idx(rng)];\n\n                    std::uniform_int_distribution<int> dist_dir(0, 3);\n                    GridPoint cand_cell = {rand_cell.first + DX[dist_dir(rng)], rand_cell.second + DY[dist_dir(rng)]};\n                    if (cand_cell.first < 0 || cand_cell.first >= grid_dim_x || cand_cell.second < 0 || cand_cell.second >= grid_dim_y) continue;\n                    \n                    bool is_in = cell_to_idx.count(cand_cell);\n                    long long delta_score = grid_scores[cand_cell.first][cand_cell.second];\n                    if (is_in) delta_score = -delta_score;\n\n                    int delta_penalty = 0;\n                    int cx = cand_cell.first; int cy = cand_cell.second;\n                    for (int dx = -1; dx <= 0; ++dx) {\n                        for (int dy = -1; dy <= 0; ++dy) {\n                            int hx = cx + dx; int hy = cy + dy;\n                            if (hx < 0 || hx >= grid_dim_x - 1 || hy < 0 || hy >= grid_dim_y - 1) continue;\n                            \n                            bool s[2][2];\n                            s[0][0] = cell_to_idx.count({hx, hy}); s[1][0] = cell_to_idx.count({hx + 1, hy});\n                            s[0][1] = cell_to_idx.count({hx, hy + 1}); s[1][1] = cell_to_idx.count({hx + 1, hy + 1});\n                            \n                            auto is_checker = [](bool b[2][2]){ return (b[0][0] && b[1][1] && !b[1][0] && !b[0][1]) || (!b[0][0] && !b[1][1] && b[1][0] && b[0][1]); };\n                            \n                            int old_p = is_checker(s);\n                            s[cx - hx][cy - hy] = !s[cx - hx][cy - hy];\n                            int new_p = is_checker(s);\n                            delta_penalty += new_p - old_p;\n                        }\n                    }\n                    \n                    const double PENALTY_WEIGHT = 5.0;\n                    double delta_energy = -delta_score + PENALTY_WEIGHT * delta_penalty;\n                    if(is_in && cells_vec.size() == 1) continue;\n\n                    std::uniform_real_distribution<double> prob_dist(0.0, 1.0);\n                    if (delta_energy < 0 || prob_dist(rng) < std::exp(-delta_energy / T)) {\n                        if (is_in) {\n                            int idx_to_remove = cell_to_idx.at(cand_cell);\n                            GridPoint back_cell = cells_vec.back();\n                            cells_vec[idx_to_remove] = back_cell;\n                            cell_to_idx[back_cell] = idx_to_remove;\n                            cells_vec.pop_back();\n                            cell_to_idx.erase(cand_cell);\n                        } else {\n                            cell_to_idx[cand_cell] = cells_vec.size();\n                            cells_vec.push_back(cand_cell);\n                        }\n                    }\n                }\n                \n                if(!cells_vec.empty()){\n                    std::set<GridPoint> current_cells(cells_vec.begin(), cells_vec.end());\n                    for(int pass = 0; pass < 5; ++pass) {\n                        bool changed = false;\n                        std::vector<GridPoint> cells_to_check(current_cells.begin(), current_cells.end());\n                        for (const auto& cell : cells_to_check) {\n                            for(int dx = -1; dx <= 0; ++dx) {\n                                for(int dy = -1; dy <= 0; ++dy) {\n                                    int hx = cell.first + dx; int hy = cell.second + dy;\n                                    if (hx < 0 || hx >= grid_dim_x - 1 || hy < 0 || hy >= grid_dim_y - 1) continue;\n                                    bool s00 = current_cells.count({hx, hy}); bool s10 = current_cells.count({hx + 1, hy});\n                                    bool s01 = current_cells.count({hx, hy + 1}); bool s11 = current_cells.count({hx + 1, hy + 1});\n                                    if ((s00 && s11 && !s10 && !s01)) {\n                                        if (grid_scores[hx + 1][hy] > grid_scores[hx][hy + 1]) { if(current_cells.insert({hx+1, hy}).second) changed=true; }\n                                        else { if(current_cells.insert({hx, hy+1}).second) changed=true; }\n                                    } else if ((!s00 && !s11 && s10 && s01)) {\n                                        if (grid_scores[hx][hy] > grid_scores[hx + 1][hy + 1]) { if(current_cells.insert({hx, hy}).second) changed=true; }\n                                        else { if(current_cells.insert({hx+1, hy+1}).second) changed=true; }\n                                    }\n                                }\n                            }\n                        }\n                        if (!changed) break;\n                    }\n\n                    Polygon p = generate_polygon_from_cells(current_cells, cell_size);\n                    if (p.vertices.size() >= 3 && p.vertices.size() <= 1000 && p.calculate_perimeter() <= 400000) {\n                        int current_a = 0, current_b = 0;\n                        for (const auto& m : mackerels) if (p.is_inside(m)) current_a++;\n                        for (const auto& s : sardines) if (p.is_inside(s)) current_b++;\n\n                        if (current_a - current_b > best_a - best_b) {\n                            best_a = current_a;\n                            best_b = current_b;\n                            best_polygon = p;\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    if (best_polygon.vertices.empty()) {\n        if (!mackerels.empty()) {\n            Point m = mackerels[0];\n            best_polygon.vertices = {{m.x, m.y}, {m.x + 1, m.y}, {m.x + 1, m.y + 1}, {m.x, m.y + 1}};\n        } else {\n             best_polygon.vertices = {{0,0}, {1,0}, {1,1}, {0,1}};\n        }\n    }\n\n    if (best_polygon.vertices.size() < 4) {\n         if (!mackerels.empty()) {\n            Point m = mackerels[0];\n            best_polygon.vertices = {{m.x, m.y}, {m.x + 1, m.y}, {m.x + 1, m.y + 1}, {m.x, m.y + 1}};\n         } else {\n             best_polygon.vertices = {{0,0}, {1,0}, {1,1}, {0,1}};\n         }\n    }\n    std::cout << best_polygon.vertices.size() << '\\n';\n    for (const auto& v : best_polygon.vertices) {\n        std::cout << v.x << \" \" << v.y << '\\n';\n    }\n\n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <string>\n#include <chrono>\n#include <random>\n#include <numeric>\n#include <algorithm>\n#include <map>\n#include <tuple>\n#include <cmath>\n#include <set>\n\n#include <Eigen/Dense>\n\n// --- Timer ---\nusing namespace std;\nusing namespace std::chrono;\n\nlong long start_time;\n\nlong long get_time() {\n    return duration_cast<milliseconds>(high_resolution_clock::now().time_since_epoch()).count();\n}\n\n// --- Random ---\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// --- Problem specific structs ---\nstruct Rect {\n    long long x, y, w, h;\n    int p_idx;\n};\n\nstruct Action {\n    int p, r;\n    char d;\n    int b;\n};\n\nusing Plan = vector<Action>;\n\n// --- Globals ---\nint N, T;\ndouble SIGMA;\nvector<double> w_obs, h_obs;\nvector<double> w_mean, h_mean;\nvector<tuple<Plan, long long, long long>> history;\nlong long global_best_score = -1;\nPlan global_best_plan;\n\n// O(plan.size() * plan.size()) simulation.\npair<long long, long long> simulate(const Plan& plan) {\n    if (plan.empty()) return {0,0};\n    vector<Rect> placed_rects;\n    long long W = 0, H = 0;\n    map<int, int> p_to_idx;\n\n    for (const auto& action : plan) {\n        long long w = round((action.r == 0) ? w_mean[action.p] : h_mean[action.p]);\n        long long h = round((action.r == 0) ? h_mean[action.p] : w_mean[action.p]);\n        long long new_x, new_y;\n        if (action.d == 'U') {\n            new_x = 0;\n            if (action.b != -1) {\n                const auto& ref_rect = placed_rects[p_to_idx.at(action.b)];\n                new_x = ref_rect.x + ref_rect.w;\n            }\n            new_y = 0;\n            for (const auto& rect : placed_rects) {\n                if (max(new_x, rect.x) < min(new_x + w, rect.x + rect.w)) {\n                    new_y = max(new_y, rect.y + rect.h);\n                }\n            }\n        } else { // 'L'\n            new_y = 0;\n            if (action.b != -1) {\n                const auto& ref_rect = placed_rects[p_to_idx.at(action.b)];\n                new_y = ref_rect.y + ref_rect.h;\n            }\n            new_x = 0;\n            for (const auto& rect : placed_rects) {\n                if (max(new_y, rect.y) < min(new_y + h, rect.y + rect.h)) {\n                    new_x = max(new_x, rect.x + rect.w);\n                }\n            }\n        }\n        p_to_idx[action.p] = placed_rects.size();\n        placed_rects.push_back({new_x, new_y, w, h, action.p});\n        W = max(W, new_x + w);\n        H = max(H, new_y + h);\n    }\n    return {W, H};\n}\n\nlong long eval_plan(const Plan& plan) {\n    vector<bool> used(N, false);\n    for(const auto& action : plan) used[action.p] = true;\n    \n    long long penalty = 0;\n    for(int i=0; i<N; ++i) {\n        if (!used[i]) {\n            penalty += round(w_mean[i] + h_mean[i]);\n        }\n    }\n\n    if (plan.empty()) return penalty;\n    \n    auto [W, H] = simulate(plan);\n    return W + H + penalty;\n}\n\nvoid update_estimates_by_lsq() {\n    int num_vars = 2 * N;\n    \n    vector<vector<pair<int, double>>> A_rows;\n    vector<double> b_vals;\n\n    for (int i = 0; i < N; ++i) {\n        A_rows.push_back({{i, 1.0}}); b_vals.push_back(w_obs[i]);\n        A_rows.push_back({{N + i, 1.0}}); b_vals.push_back(h_obs[i]);\n    }\n    for (const auto& [plan, W_prime, H_prime] : history) {\n        if(plan.empty()) continue;\n        \n        bool is_sum_plan_W = plan.size() > 0;\n        if (plan[0].d != 'L') is_sum_plan_W = false;\n        for(size_t j=1; j<plan.size() && is_sum_plan_W; ++j) if(plan[j].d != 'L') is_sum_plan_W = false;\n        if(is_sum_plan_W) {\n            vector<pair<int, double>> row;\n            for (const auto& action : plan) { if (action.r == 0) row.push_back({action.p, 1.0}); else row.push_back({N + action.p, 1.0}); }\n            if(!row.empty()){ A_rows.push_back(row); b_vals.push_back(W_prime); }\n        }\n\n        bool is_sum_plan_H = plan.size() > 0;\n        if (plan[0].d != 'U') is_sum_plan_H = false;\n        for(size_t j=1; j<plan.size() && is_sum_plan_H; ++j) if(plan[j].d != 'U') is_sum_plan_H = false;\n        if(is_sum_plan_H){\n            vector<pair<int, double>> row;\n            for (const auto& action : plan) { if (action.r == 0) row.push_back({N + action.p, 1.0}); else row.push_back({action.p, 1.0}); }\n            if(!row.empty()){ A_rows.push_back(row); b_vals.push_back(H_prime); }\n        }\n    }\n\n    int num_equations = A_rows.size();\n    if(num_equations == 0) return;\n    Eigen::MatrixXd A(num_equations, num_vars); Eigen::VectorXd b(num_equations); A.setZero();\n    for(int i=0; i<num_equations; ++i){\n        for(auto const& [col, val] : A_rows[i]) A(i, col) = val;\n        b(i) = b_vals[i];\n    }\n    \n    Eigen::VectorXd x = A.bdcSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(b);\n    for (int i = 0; i < N; ++i) { w_mean[i] = max(1.0, x(i)); h_mean[i] = max(1.0, x(N + i)); }\n}\n\nAction find_best_action_for_p(int p, const vector<Rect>& placed_rects, const map<int, int>& p_to_idx, long long current_W, long long current_H) {\n    Action best_action; long long best_score = -1;\n    for (int r = 0; r < 2; ++r) {\n        long long w = round((r == 0) ? w_mean[p] : h_mean[p]), h = round((r == 0) ? h_mean[p] : w_mean[p]);\n        for (char d : {'U', 'L'}) {\n            vector<int> b_candidates; b_candidates.push_back(-1);\n            if (!placed_rects.empty()) {\n                b_candidates.push_back(placed_rects.back().p_idx);\n                uniform_int_distribution<int> dist(0, placed_rects.size() - 1);\n                for (int k = 0; k < 8 && k < placed_rects.size(); ++k) b_candidates.push_back(placed_rects[dist(rng)].p_idx);\n            }\n            sort(b_candidates.begin(), b_candidates.end()); b_candidates.erase(unique(b_candidates.begin(), b_candidates.end()), b_candidates.end());\n            for (int b_p_idx : b_candidates) {\n                long long new_x, new_y;\n                if(d == 'U'){\n                    new_x = 0; if (b_p_idx != -1) new_x = placed_rects[p_to_idx.at(b_p_idx)].x + placed_rects[p_to_idx.at(b_p_idx)].w;\n                    new_y = 0; for(const auto& rect : placed_rects) if(max(new_x, rect.x) < min(new_x+w, rect.x+rect.w)) new_y = max(new_y, rect.y+rect.h);\n                } else {\n                    new_y = 0; if (b_p_idx != -1) new_y = placed_rects[p_to_idx.at(b_p_idx)].y + placed_rects[p_to_idx.at(b_p_idx)].h;\n                    new_x = 0; for(const auto& rect : placed_rects) if(max(new_y, rect.y) < min(new_y+h, rect.y+rect.h)) new_x = max(new_x, rect.x+rect.w);\n                }\n                long long score = max(current_W, new_x+w) + max(current_H, new_y+h);\n                if (best_score == -1 || score < best_score) { best_score = score; best_action = {p, r, d, b_p_idx}; }\n            }\n        }\n    }\n    return best_action;\n}\n\nPlan constructive_search(const vector<bool>& use_rect) {\n    Plan plan; vector<Rect> placed_rects; map<int, int> p_to_idx; long long current_W = 0, current_H = 0;\n    \n    int num_to_place = 0;\n    for(int i=0; i<N; ++i) if (use_rect[i]) num_to_place++;\n\n    for (int i = 0; i < num_to_place; ++i) {\n        int last_p = plan.empty() ? -1 : plan.back().p;\n        set<int> p_candidates;\n        vector<int> available_p;\n        for (int p_idx = last_p + 1; p_idx < N; ++p_idx) if(use_rect[p_idx]) available_p.push_back(p_idx);\n        if (available_p.empty()) break;\n\n        p_candidates.insert(available_p[0]);\n        sort(available_p.begin(), available_p.end(), [&](int a, int b){ return w_mean[a]*h_mean[a] > w_mean[b]*h_mean[b]; });\n        for(int k=0; k<2 && k<available_p.size(); ++k) p_candidates.insert(available_p[k]);\n        sort(available_p.begin(), available_p.end(), [&](int a, int b){ return max(w_mean[a],h_mean[a]) > max(w_mean[b],h_mean[b]); });\n        for(int k=0; k<2 && k<available_p.size(); ++k) p_candidates.insert(available_p[k]);\n        shuffle(available_p.begin(), available_p.end(), rng);\n        for(int k=0; k<3 && k<available_p.size(); ++k) p_candidates.insert(available_p[k]);\n\n        long long best_total_score = -1; Action best_action_for_turn;\n        for (int p : p_candidates) {\n            Action action_for_p = find_best_action_for_p(p, placed_rects, p_to_idx, current_W, current_H);\n            long long w = round((action_for_p.r == 0) ? w_mean[p] : h_mean[p]), h = round((action_for_p.r == 0) ? h_mean[p] : w_mean[p]);\n            long long new_x, new_y;\n            if(action_for_p.d == 'U'){\n                new_x = 0; if (action_for_p.b != -1) new_x = placed_rects[p_to_idx.at(action_for_p.b)].x + placed_rects[p_to_idx.at(action_for_p.b)].w;\n                new_y = 0; for(const auto& rect : placed_rects) if(max(new_x, rect.x) < min(new_x+w, rect.x+rect.w)) new_y = max(new_y, rect.y+rect.h);\n            } else {\n                new_y = 0; if (action_for_p.b != -1) new_y = placed_rects[p_to_idx.at(action_for_p.b)].y + placed_rects[p_to_idx.at(action_for_p.b)].h;\n                new_x = 0; for(const auto& rect : placed_rects) if(max(new_y, rect.y) < min(new_y+h, rect.y+rect.h)) new_x = max(new_x, rect.x+rect.w);\n            }\n            long long score = max(current_W, new_x+w) + max(current_H, new_y+h);\n            if (best_total_score == -1 || score < best_total_score) { best_total_score = score; best_action_for_turn = action_for_p; }\n        }\n        \n        plan.push_back(best_action_for_turn);\n        int p=best_action_for_turn.p, r=best_action_for_turn.r, b_p_idx=best_action_for_turn.b; char d=best_action_for_turn.d;\n        long long w = round((r == 0) ? w_mean[p] : h_mean[p]), h = round((r == 0) ? h_mean[p] : w_mean[p]);\n        long long new_x, new_y;\n        if(d == 'U'){\n            new_x = 0; if (b_p_idx!=-1) new_x = placed_rects[p_to_idx.at(b_p_idx)].x + placed_rects[p_to_idx.at(b_p_idx)].w;\n            new_y = 0; for(const auto& rect : placed_rects) if(max(new_x, rect.x) < min(new_x+w, rect.x+rect.w)) new_y = max(new_y, rect.y+rect.h);\n        } else {\n            new_y = 0; if (b_p_idx!=-1) new_y = placed_rects[p_to_idx.at(b_p_idx)].y + placed_rects[p_to_idx.at(b_p_idx)].h;\n            new_x = 0; for(const auto& rect : placed_rects) if(max(new_y, rect.y) < min(new_y+h, rect.y+rect.h)) new_x = max(new_x, rect.x+rect.w);\n        }\n        p_to_idx[p] = placed_rects.size();\n        placed_rects.push_back({new_x, new_y, w, h, p});\n        current_W = max(current_W, new_x+w); current_H = max(current_H, new_y+h);\n    }\n    return plan;\n}\n\nPlan simulated_annealing(Plan initial_plan, int time_limit_ms) {\n    if (initial_plan.empty()) return initial_plan;\n    long long turn_start_time = get_time();\n    Plan current_plan = initial_plan;\n    long long current_score = eval_plan(current_plan);\n    Plan best_plan = current_plan;\n    long long best_score = current_score;\n    double start_temp = (double)current_score * 0.05; double end_temp = 0.01;\n\n    while(true) {\n        long long elapsed_time = get_time() - turn_start_time;\n        if (elapsed_time >= time_limit_ms) break;\n        \n        Plan neighbor_plan = current_plan;\n        int i = uniform_int_distribution<int>(0, current_plan.size() - 1)(rng);\n        \n        int change_type = uniform_int_distribution<int>(0, 2)(rng);\n        if (change_type == 0) { neighbor_plan[i].r = 1 - neighbor_plan[i].r; }\n        else if (change_type == 1) { neighbor_plan[i].d = (neighbor_plan[i].d == 'U' ? 'L' : 'U'); }\n        else {\n            if (i > 0) {\n                int b_p_idx = -1;\n                uniform_int_distribution<int> b_dist(-1, i - 1);\n                int b_plan_idx = b_dist(rng);\n                if (b_plan_idx != -1) b_p_idx = current_plan[b_plan_idx].p;\n                neighbor_plan[i].b = b_p_idx;\n            }\n        }\n        \n        long long neighbor_score = eval_plan(neighbor_plan);\n        double temp = start_temp * pow(end_temp / start_temp, (double)elapsed_time / max(1, time_limit_ms));\n        \n        if (neighbor_score < current_score || (temp > 1e-9 && uniform_real_distribution<double>(0.0, 1.0)(rng) < exp((double)(current_score - neighbor_score) / temp))) {\n            current_plan = neighbor_plan; current_score = neighbor_score;\n        }\n        if (current_score < best_score) { best_score = current_score; best_plan = current_plan; }\n    }\n    return best_plan;\n}\n\nvoid solve() {\n    cin >> N >> T >> SIGMA;\n    w_obs.resize(N); h_obs.resize(N); w_mean.resize(N); h_mean.resize(N);\n    for (int i = 0; i < N; ++i) { cin >> w_obs[i] >> h_obs[i]; w_mean[i] = w_obs[i]; h_mean[i] = h_obs[i]; }\n    \n    vector<Plan> exploratory_plans;\n    for (int k = 0; k < 2; ++k) {\n        Plan p_L, p_U;\n        vector<int> p_indices(N); iota(p_indices.begin(), p_indices.end(), 0);\n        for (int i = 0; i < N; ++i) {\n            int p = p_indices[i];\n            p_L.push_back({p, (int)(rng() % 2), 'L', i > 0 ? p_indices[i-1] : -1});\n            p_U.push_back({p, (int)(rng() % 2), 'U', i > 0 ? p_indices[i-1] : -1});\n        }\n        exploratory_plans.push_back(p_L); exploratory_plans.push_back(p_U);\n    }\n    int K = min((int)exploratory_plans.size(), T / 2);\n\n    set<int> update_turns;\n    if (T > K) { update_turns.insert(K - 1); for(int i=1; i<=3; ++i) update_turns.insert(K + i*(T - K -1) / 4); }\n    \n    for (int t = 0; t < T; ++t) {\n        Plan p_to_submit;\n        if (t < K) {\n            p_to_submit = exploratory_plans[t];\n        } else {\n            long long time_left = 2750 - (get_time() - start_time);\n            long long time_per_turn = (T - t > 0) ? (time_left / (T - t)) : time_left;\n            \n            vector<bool> use_rect(N, true);\n            int strategy = (t - K) % 10; int k=0;\n            if (strategy < 3) k = strategy + 1; else if (strategy >= 5 && strategy < 8) k = strategy - 4;\n            if (k > 0) {\n                vector<pair<double, int>> metrics;\n                if (strategy < 5) for(int i=0; i<N; ++i) metrics.push_back({-w_mean[i]*h_mean[i], i});\n                else for(int i=0; i<N; ++i) metrics.push_back({-max(w_mean[i], h_mean[i]), i});\n                sort(metrics.begin(), metrics.end());\n                for(int i=0; i<k && i<N; ++i) use_rect[metrics[i].second] = false;\n            }\n            \n            Plan candidate = constructive_search(use_rect);\n            long long candidate_score = eval_plan(candidate);\n            \n            Plan initial_plan;\n            long long best_known_score = eval_plan(global_best_plan);\n            if (global_best_plan.empty() || candidate_score < best_known_score) {\n                 initial_plan = candidate;\n            } else {\n                 initial_plan = global_best_plan;\n            }\n            \n            Plan optimized_plan = simulated_annealing(initial_plan, max(1LL, time_per_turn));\n\n            long long optimized_score = eval_plan(optimized_plan);\n            best_known_score = eval_plan(global_best_plan);\n            if (global_best_plan.empty() || optimized_score < best_known_score) {\n                p_to_submit = optimized_plan;\n            } else { p_to_submit = global_best_plan; }\n        }\n        \n        cout << p_to_submit.size() << endl;\n        for (const auto& action : p_to_submit) { cout << action.p << \" \" << action.r << \" \" << action.d << \" \" << action.b << endl; }\n\n        long long W_prime, H_prime; cin >> W_prime >> H_prime;\n        history.emplace_back(p_to_submit, W_prime, H_prime);\n        if (update_turns.count(t)) { update_estimates_by_lsq(); }\n        \n        long long penalty = 0;\n        vector<bool> used(N, false); for(const auto& action : p_to_submit) used[action.p] = true;\n        for(int i=0; i<N; ++i) if (!used[i]) penalty += round(w_mean[i] + h_mean[i]);\n        long long current_score = W_prime + H_prime + penalty;\n\n        if (global_best_score == -1 || current_score < global_best_score) {\n            global_best_score = current_score; global_best_plan = p_to_submit;\n        }\n    }\n}\n\nint main() {\n    start_time = get_time();\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <cmath>\n#include <tuple>\n\nusing namespace std;\n\n// --- Utilities ---\nstruct XorShift {\n    unsigned int x, y, z, w;\n    XorShift(unsigned int seed) : x(seed), y(362436069), z(521288629), w(88675123) {}\n    unsigned int next() {\n        unsigned int t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));\n    }\n    int next_int(int n) {\n        if (n == 0) return 0;\n        return next() % n;\n    }\n    double next_double() {\n        return (double)next() / ((long long)1 << 32);\n    }\n};\n\nXorShift rnd(12345);\nauto start_time = chrono::steady_clock::now();\n\n// --- Problem data ---\nint N, M, H;\nvector<int> A;\nvector<pair<int, int>> edges;\nvector<vector<int>> adj;\n\n// --- Solution state and helpers ---\nstruct Solution {\n    vector<int> p;\n    long long score;\n\n    vector<vector<int>> children;\n    vector<int> h;\n    vector<int> max_d;\n    vector<long long> sum_A_sub;\n    vector<int> root_of;\n\n    Solution() {}\n\n    void init(int n_nodes) {\n        p.assign(n_nodes, -1);\n        children.assign(n_nodes, {});\n        h.assign(n_nodes, 0);\n        max_d.assign(n_nodes, 0);\n        sum_A_sub.assign(n_nodes, 0);\n        root_of.assign(n_nodes, -1);\n    }\n\n    void compute_properties() {\n        for(int i=0; i<N; ++i) children[i].clear();\n        vector<int> roots;\n        for (int i = 0; i < N; ++i) {\n            if (p[i] == -1) {\n                roots.push_back(i);\n            } else {\n                children[p[i]].push_back(i);\n            }\n        }\n\n        for (int r : roots) {\n            vector<int> q;\n            q.push_back(r);\n            root_of[r] = r;\n            h[r] = 0;\n            \n            int head = 0;\n            while(head < q.size()){\n                int u = q[head++];\n                for(int v : children[u]){\n                    h[v] = h[u] + 1;\n                    root_of[v] = r;\n                    q.push_back(v);\n                }\n            }\n            \n            reverse(q.begin(), q.end());\n            for(int u : q){\n                sum_A_sub[u] = A[u];\n                max_d[u] = 0;\n                for(int v : children[u]){\n                    sum_A_sub[u] += sum_A_sub[v];\n                    max_d[u] = max(max_d[u], max_d[v] + 1);\n                }\n            }\n        }\n        score = 0;\n        for(int i=0; i<N; ++i) {\n            if (h[i] > H) {\n                score = -1; // Invalid\n                return;\n            }\n            score += (long long)(h[i] + 1) * A[i];\n        }\n    }\n};\n\nvoid solve() {\n    Solution sol;\n    sol.init(N);\n    \n    // --- Greedy construction ---\n    double greedy_time_limit = 0.8;\n    int roots_count = N;\n    while(roots_count > 1) {\n        auto current_time = chrono::steady_clock::now();\n        double elapsed_time = chrono::duration_cast<chrono::milliseconds>(current_time - start_time).count() / 1000.0;\n        if (elapsed_time > greedy_time_limit) break;\n\n        sol.compute_properties();\n\n        double best_gain = -1.0;\n        int best_u = -1, best_v = -1;\n\n        for (const auto& edge : edges) {\n            int u1 = edge.first;\n            int v1 = edge.second;\n\n            if (sol.root_of[u1] == sol.root_of[v1]) continue;\n\n            // Try u1 -> v1\n            if (sol.p[v1] == -1) {\n                if (sol.h[u1] + 1 + sol.max_d[v1] <= H) {\n                    double gain = (double)(sol.h[u1] + 1) * sol.sum_A_sub[v1];\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        best_u = u1;\n                        best_v = v1;\n                    }\n                }\n            }\n            // Try v1 -> u1\n            if (sol.p[u1] == -1) {\n                if (sol.h[v1] + 1 + sol.max_d[u1] <= H) {\n                    double gain = (double)(sol.h[v1] + 1) * sol.sum_A_sub[u1];\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        best_u = v1;\n                        best_v = u1;\n                    }\n                }\n            }\n        }\n\n        if (best_u == -1) break;\n        sol.p[best_v] = best_u;\n        roots_count--;\n    }\n\n    sol.compute_properties();\n    Solution best_sol = sol;\n\n    // --- Simulated Annealing ---\n    double time_limit = 1.95;\n    double temp_start = 500.0, temp_end = 0.1;\n\n    while (true) {\n        auto current_time = chrono::steady_clock::now();\n        double elapsed_time = chrono::duration_cast<chrono::milliseconds>(current_time - start_time).count() / 1000.0;\n        if (elapsed_time > time_limit) break;\n\n        double progress = (elapsed_time - greedy_time_limit) / (time_limit - greedy_time_limit);\n        if (progress < 0) progress = 0;\n        if (progress > 1) progress = 1;\n\n        double temp = temp_start * pow(temp_end / temp_start, progress);\n\n        int v = rnd.next_int(N);\n        \n        vector<int> candidates = adj[v];\n        candidates.push_back(-1);\n        int u = candidates[rnd.next_int(candidates.size())];\n\n        int old_p = sol.p[v];\n        if (u == old_p) continue;\n        \n        bool is_ancestor = false;\n        if (u != -1) {\n            int curr = u;\n            while(curr != -1) {\n                if (curr == v) {\n                    is_ancestor = true;\n                    break;\n                }\n                curr = sol.p[curr];\n            }\n        }\n        if (is_ancestor) continue;\n        \n        int u_h = (u == -1) ? -1 : sol.h[u];\n        if (u_h + 1 + sol.max_d[v] > H) continue;\n\n        int old_p_h = (old_p == -1) ? -1 : sol.h[old_p];\n        long long score_delta = (long long)(u_h - old_p_h) * sol.sum_A_sub[v];\n\n        if (score_delta > 0 || (temp > 1e-9 && rnd.next_double() < exp(score_delta / temp))) {\n            sol.p[v] = u;\n            sol.compute_properties();\n            if (sol.score > best_sol.score) {\n                best_sol = sol;\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << best_sol.p[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N >> M >> H;\n    A.resize(N);\n    adj.resize(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        edges.push_back({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    solve();\n\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <array>\n#include <chrono>\n#include <queue>\n#include <memory>\n#include <unordered_map>\n#include <boost/container_hash/hash.hpp>\n\nusing namespace std;\nusing namespace std::chrono;\n\nconst int N = 20;\nconst int BEAM_WIDTH = 250; \nconst double TIME_LIMIT_MS = 1950.0;\n\nstruct Piece {\n    int id; \n    int r, c;\n    bool removed;\n};\n\nstruct MacroMove {\n    char dir;\n    int line_idx;\n    int cost;\n};\n\nstruct PiecePos {\n    int r, c;\n    bool operator<(const PiecePos& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n};\n\nstruct State {\n    shared_ptr<const vector<Piece>> onis;\n    shared_ptr<const vector<Piece>> fukus;\n    \n    vector<MacroMove> history;\n    int total_cost = 0;\n    int uncovered_count = 0;\n\n    double score = 0.0; // g + h\n\n    bool operator>(const State& other) const {\n        if (abs(score - other.score) > 1e-9) {\n            return score > other.score;\n        }\n        return total_cost > other.total_cost;\n    }\n};\n\n\nsize_t calculate_state_hash(const State& s) {\n    vector<PiecePos> positions;\n    positions.reserve(s.onis->size() + s.fukus->size());\n    for (const auto& p : *s.onis) if (!p.removed) positions.push_back({p.r, p.c});\n    for (const auto& p : *s.fukus) if (!p.removed) positions.push_back({p.r, p.c});\n    sort(positions.begin(), positions.end());\n\n    size_t seed = 0;\n    for(const auto& pos : positions) {\n        boost::hash_combine(seed, pos.r);\n        boost::hash_combine(seed, pos.c);\n    }\n    return seed;\n}\n\ndouble calculate_heuristic(const State& s) {\n    if (s.uncovered_count == 0) return 0.0;\n\n    double h = 0;\n    for (const auto& oni : *s.onis) {\n        if (oni.removed) continue;\n        \n        int min_cost = 1e9;\n        \n        bool safe_u = true;\n        for(const auto& fuku : *s.fukus) if (!fuku.removed && fuku.c == oni.c && fuku.r < oni.r) { safe_u = false; break; }\n        if(safe_u) min_cost = min(min_cost, oni.r + 1);\n\n        bool safe_d = true;\n        for(const auto& fuku : *s.fukus) if (!fuku.removed && fuku.c == oni.c && fuku.r > oni.r) { safe_d = false; break; }\n        if(safe_d) min_cost = min(min_cost, N - oni.r);\n\n        bool safe_l = true;\n        for(const auto& fuku : *s.fukus) if (!fuku.removed && fuku.r == oni.r && fuku.c < oni.c) { safe_l = false; break; }\n        if(safe_l) min_cost = min(min_cost, oni.c + 1);\n        \n        bool safe_r = true;\n        for(const auto& fuku : *s.fukus) if (!fuku.removed && fuku.r == oni.r && fuku.c > oni.c) { safe_r = false; break; }\n        if(safe_r) min_cost = min(min_cost, N - oni.c);\n\n        if (min_cost < 1e8) h += min_cost;\n        else return 1e18; // Unsolvable state\n    }\n    return h;\n}\n\nvector<MacroMove> generate_actions(const State& s) {\n    vector<MacroMove> actions;\n    \n    vector<vector<int>> onis_in_row(N), fukus_in_row(N);\n    vector<vector<int>> onis_in_col(N), fukus_in_col(N);\n    \n    for (const auto& oni : *s.onis) if (!oni.removed) { onis_in_row[oni.r].push_back(oni.id); onis_in_col[oni.c].push_back(oni.id); }\n    for (const auto& fuku : *s.fukus) if (!fuku.removed) { fukus_in_row[fuku.r].push_back(fuku.id); fukus_in_col[fuku.c].push_back(fuku.id); }\n\n    auto generate_for_line = [&](char dir, int idx) {\n        int cost = 0;\n        bool has_target = false;\n        \n        const auto& line_oni_ids = (dir == 'U' || dir == 'D') ? onis_in_col[idx] : onis_in_row[idx];\n        const auto& line_fuku_ids = (dir == 'U' || dir == 'D') ? fukus_in_col[idx] : fukus_in_row[idx];\n        \n        for (int oni_id : line_oni_ids) {\n            bool safe = true;\n            for (int fuku_id : line_fuku_ids) {\n                if ((dir == 'U' && (*s.fukus)[fuku_id].r < (*s.onis)[oni_id].r) ||\n                    (dir == 'D' && (*s.fukus)[fuku_id].r > (*s.onis)[oni_id].r) ||\n                    (dir == 'L' && (*s.fukus)[fuku_id].c < (*s.onis)[oni_id].c) ||\n                    (dir == 'R' && (*s.fukus)[fuku_id].c > (*s.onis)[oni_id].c)) {\n                    safe = false;\n                    break;\n                }\n            }\n            if (safe) {\n                has_target = true;\n                if(dir == 'U') cost = max(cost, (*s.onis)[oni_id].r + 1);\n                if(dir == 'D') cost = max(cost, N - (*s.onis)[oni_id].r);\n                if(dir == 'L') cost = max(cost, (*s.onis)[oni_id].c + 1);\n                if(dir == 'R') cost = max(cost, N - (*s.onis)[oni_id].c);\n            }\n        }\n        if (has_target) actions.push_back({dir, idx, cost});\n    };\n    \n    for (int i = 0; i < N; ++i) { generate_for_line('L', i); generate_for_line('R', i); }\n    for (int j = 0; j < N; ++j) { generate_for_line('U', j); generate_for_line('D', j); }\n\n    return actions;\n}\n\nState apply_action_to_state(const State& current, const MacroMove& action) {\n    State next;\n    next.history = current.history;\n    next.history.push_back(action);\n    next.total_cost = current.total_cost + action.cost;\n    next.uncovered_count = current.uncovered_count;\n\n    auto next_onis = make_shared<vector<Piece>>(*current.onis);\n    auto next_fukus = make_shared<vector<Piece>>(*current.fukus);\n\n    auto update_piece = [&](Piece& p) {\n        if (p.removed) return;\n        bool piece_removed = false;\n        switch(action.dir) {\n            case 'U': if (p.c == action.line_idx) { if (p.r < action.cost) piece_removed = true; else p.r -= action.cost; } break;\n            case 'D': if (p.c == action.line_idx) { if (p.r > N - 1 - action.cost) piece_removed = true; else p.r += action.cost; } break;\n            case 'L': if (p.r == action.line_idx) { if (p.c < action.cost) piece_removed = true; else p.c -= action.cost; } break;\n            case 'R': if (p.r == action.line_idx) { if (p.c > N - 1 - action.cost) piece_removed = true; else p.c += action.cost; } break;\n        }\n        if (piece_removed) {\n            p.removed = true;\n            if (p.id >= 0) next.uncovered_count--;\n        }\n    };\n\n    for (auto& oni : *next_onis) update_piece(oni);\n    for (auto& fuku : *next_fukus) update_piece(fuku);\n    \n    next.onis = next_onis;\n    next.fukus = next_fukus;\n\n    return next;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    auto start_time = high_resolution_clock::now();\n\n    int n_dummy;\n    cin >> n_dummy;\n\n    State initial_state;\n    auto initial_onis = make_shared<vector<Piece>>();\n    auto initial_fukus = make_shared<vector<Piece>>();\n    int oni_id_counter = 0;\n    int fuku_id_counter = 0;\n    for (int i = 0; i < N; ++i) {\n        string row_str;\n        cin >> row_str;\n        for (int j = 0; j < N; ++j) {\n            if (row_str[j] == 'x') {\n                initial_onis->push_back({oni_id_counter++, i, j, false});\n            } else if (row_str[j] == 'o') {\n                initial_fukus->push_back({fuku_id_counter++, i, j, false});\n            }\n        }\n    }\n    initial_state.onis = initial_onis;\n    initial_state.fukus = initial_fukus;\n    initial_state.uncovered_count = initial_state.onis->size();\n    \n    priority_queue<State, vector<State>, greater<State>> beam;\n    initial_state.score = calculate_heuristic(initial_state);\n    beam.push(initial_state);\n\n    State best_solution;\n    best_solution.total_cost = 1e9;\n    unordered_map<size_t, int> min_costs;\n\n    size_t initial_hash = calculate_state_hash(initial_state);\n    min_costs[initial_hash] = 0;\n\n    while(true) {\n        auto current_time = high_resolution_clock::now();\n        if (duration_cast<milliseconds>(current_time - start_time).count() > TIME_LIMIT_MS) break;\n        if (beam.empty()) break;\n\n        priority_queue<State, vector<State>, greater<State>> next_beam_candidates;\n        int beam_proc_count = 0;\n        while(!beam.empty() && beam_proc_count < BEAM_WIDTH) {\n            State current = beam.top();\n            beam.pop();\n\n            if (current.total_cost >= best_solution.total_cost) continue;\n            \n            size_t current_hash = calculate_state_hash(current);\n            if (min_costs.count(current_hash) && current.total_cost > min_costs[current_hash]) continue;\n\n            if (current.uncovered_count == 0) {\n                 if (current.total_cost < best_solution.total_cost) best_solution = current;\n                continue;\n            }\n\n            vector<MacroMove> possible_actions = generate_actions(current);\n\n            for (const auto& action : possible_actions) {\n                State next_state = apply_action_to_state(current, action);\n                size_t next_hash = calculate_state_hash(next_state);\n\n                if (!min_costs.count(next_hash) || next_state.total_cost < min_costs[next_hash]) {\n                    min_costs[next_hash] = next_state.total_cost;\n                    double h = calculate_heuristic(next_state);\n                    if (h > 1e17) continue;\n                    next_state.score = next_state.total_cost + h;\n                    next_beam_candidates.push(next_state);\n                }\n            }\n            beam_proc_count++;\n        }\n        \n        beam = priority_queue<State, vector<State>, greater<State>>();\n        int count = 0;\n        while (!next_beam_candidates.empty() && count < BEAM_WIDTH) {\n            beam.push(next_beam_candidates.top());\n            next_beam_candidates.pop();\n            count++;\n        }\n    }\n    \n    for (const auto& macro_move : best_solution.history) {\n        for (int i = 0; i < macro_move.cost; ++i) {\n            cout << macro_move.dir << \" \" << macro_move.line_idx << \"\\n\";\n        }\n    }\n\n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <tuple>\n\n// --- Start of Timer and RNG Utilities ---\nclass Timer {\n    std::chrono::high_resolution_clock::time_point start_time;\npublic:\n    Timer() {\n        start_time = std::chrono::high_resolution_clock::now();\n    }\n    double get_elapsed_sec() {\n        auto now = std::chrono::high_resolution_clock::now();\n        return std::chrono::duration_cast<std::chrono::duration<double>>(now - start_time).count();\n    }\n};\n\nclass XorShiftRng {\n    uint64_t x;\npublic:\n    XorShiftRng(uint64_t seed) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 13;\n        x ^= x >> 7;\n        x ^= x << 17;\n        return x;\n    }\n    int next_int(int max) { // [0, max-1]\n        if (max <= 0) return 0;\n        return next() % max;\n    }\n    double next_double() { // [0.0, 1.0)\n        return static_cast<double>(next()) / UINT64_MAX;\n    }\n};\n// --- End of Timer and RNG Utilities ---\n\nconst int N_CONST = 100;\nconst int L_CONST = 500000;\nconst double TIME_LIMIT_SEC = 1.95;\n\nstruct EvalResult {\n    long long error;\n    std::vector<int> t;\n    std::vector<int> count_a;\n    std::vector<int> count_b;\n};\n\nEvalResult evaluate(const std::vector<int>& a, const std::vector<int>& b, const std::vector<int>& T) {\n    std::vector<int> t(N_CONST, 0);\n    std::vector<int> count_a(N_CONST, 0);\n    std::vector<int> count_b(N_CONST, 0);\n    \n    int cleaner = 0;\n    t[cleaner]++;\n    \n    for (int k = 1; k < L_CONST; ++k) {\n        int last_cleaner = cleaner;\n        int count_of_last_cleaner = t[last_cleaner];\n        \n        if (count_of_last_cleaner % 2 != 0) {\n            cleaner = a[last_cleaner];\n            count_a[last_cleaner]++;\n        } else {\n            cleaner = b[last_cleaner];\n            count_b[last_cleaner]++;\n        }\n        t[cleaner]++;\n    }\n    \n    long long error = 0;\n    for (int i = 0; i < N_CONST; ++i) {\n        error += std::abs(static_cast<long long>(t[i]) - T[i]);\n    }\n    \n    return {error, std::move(t), std::move(count_a), std::move(count_b)};\n}\n\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    Timer timer;\n    \n    int n_in, l_in;\n    std::cin >> n_in >> l_in; \n    std::vector<int> T(N_CONST);\n    for (int i = 0; i < N_CONST; ++i) {\n        std::cin >> T[i];\n    }\n\n    uint64_t seed = std::chrono::high_resolution_clock::now().time_since_epoch().count();\n    XorShiftRng rng(seed);\n\n    // --- Initial solution ---\n    std::vector<int> a(N_CONST), b(N_CONST);\n    \n    std::vector<double> weights;\n    double total_weight = 0;\n    for(int i = 0; i < N_CONST; ++i) {\n        double w = T[i] > 0 ? static_cast<double>(T[i]) : 1.0;\n        weights.push_back(w);\n        total_weight += w;\n    }\n    auto select_weighted = [&](const std::vector<double>& w, double total_w) {\n        double r = rng.next_double() * total_w;\n        for(size_t i = 0; i < w.size(); ++i) {\n            r -= w[i];\n            if (r <= 0) return (int)i;\n        }\n        return (int)w.size() - 1;\n    };\n    for (int i = 0; i < N_CONST; ++i) {\n        a[i] = select_weighted(weights, total_weight);\n        b[i] = select_weighted(weights, total_weight);\n    }\n    \n    auto global_best_a = a;\n    auto global_best_b = b;\n    long long global_best_error = evaluate(a, b, T).error;\n\n    auto make_random_move = [&](std::vector<int>& target_a, std::vector<int>& target_b) {\n        int change_i = rng.next_int(N_CONST);\n        int change_ab = rng.next_int(2);\n        int new_val = rng.next_int(N_CONST);\n        if (change_ab == 0) target_a[change_i] = new_val;\n        else target_b[change_i] = new_val;\n    };\n\n    while (timer.get_elapsed_sec() < TIME_LIMIT_SEC) {\n        // --- One run of SA Local Search ---\n        auto current_eval = evaluate(a, b, T);\n        long long current_error = current_eval.error;\n        auto& current_t = current_eval.t;\n        auto& current_count_a = current_eval.count_a;\n        auto& current_count_b = current_eval.count_b;\n\n        auto run_best_a = a;\n        auto run_best_b = b;\n        long long run_best_error = current_error;\n\n        const double T_start = 3000.0;\n        const double T_end = 0.1;\n        const int ITERS_PER_RUN = 2500;\n\n        auto make_weighted_smart_move = [&](std::vector<int>& target_a, std::vector<int>& target_b) -> bool {\n            std::vector<std::pair<int, double>> over_candidates, under_candidates;\n            for (int i=0; i<N_CONST; ++i) {\n                if (current_t[i] > T[i]) over_candidates.push_back({i, (double)current_t[i] - T[i]});\n                else if (current_t[i] < T[i]) under_candidates.push_back({i, (double)T[i] - current_t[i]});\n            }\n            if (over_candidates.empty() || under_candidates.empty()) return false;\n            \n            double total_over_w = 0; for(const auto& p : over_candidates) total_over_w += p.second;\n            double r_over = rng.next_double() * total_over_w;\n            int v = -1;\n            for(const auto& p : over_candidates) { r_over -= p.second; if(r_over <= 0) {v = p.first; break;} }\n            if (v == -1) v = over_candidates.back().first;\n\n            double total_under_w = 0; for(const auto& p : under_candidates) total_under_w += p.second;\n            double r_under = rng.next_double() * total_under_w;\n            int w = -1;\n            for(const auto& p : under_candidates) { r_under -= p.second; if(r_under <= 0) {w = p.first; break;} }\n            if (w == -1) w = under_candidates.back().first;\n            \n            std::vector<std::tuple<int, int, double>> active_edges;\n            for (int u = 0; u < N_CONST; ++u) {\n                if (a[u] == v && current_count_a[u] > 0) active_edges.emplace_back(u, 0, current_count_a[u]);\n                if (b[u] == v && current_count_b[u] > 0) active_edges.emplace_back(u, 1, current_count_b[u]);\n            }\n            if (active_edges.empty()) return false;\n\n            double total_edge_w = 0; for(const auto& t : active_edges) total_edge_w += std::get<2>(t);\n            double r_edge = rng.next_double() * total_edge_w;\n            const auto* edge_to_change = &active_edges.back();\n            for(const auto& t : active_edges) { r_edge -= std::get<2>(t); if(r_edge <= 0) {edge_to_change = &t; break;} }\n\n            int u = std::get<0>(*edge_to_change), ab = std::get<1>(*edge_to_change);\n            if (ab == 0) target_a[u] = w; else target_b[u] = w;\n            return true;\n        };\n\n        for (int i = 0; i < ITERS_PER_RUN && timer.get_elapsed_sec() < TIME_LIMIT_SEC; ++i) {\n            double progress = (double)i / ITERS_PER_RUN;\n            double temp = T_start * std::pow(T_end / T_start, progress);\n\n            std::vector<int> next_a = a, next_b = b;\n            \n            if (rng.next_double() < 0.05) {\n                make_random_move(next_a, next_b);\n            } else {\n                if (!make_weighted_smart_move(next_a, next_b)) {\n                    make_random_move(next_a, next_b);\n                }\n            }\n            \n            auto neighbor_eval = evaluate(next_a, next_b, T);\n            long long neighbor_error = neighbor_eval.error;\n            double delta_e = static_cast<double>(neighbor_error) - current_error;\n\n            if (delta_e <= 0 || rng.next_double() < std::exp(-delta_e / temp)) {\n                a = std::move(next_a);\n                b = std::move(next_b);\n                current_error = neighbor_error;\n                current_t = std::move(neighbor_eval.t);\n                current_count_a = std::move(neighbor_eval.count_a);\n                current_count_b = std::move(neighbor_eval.count_b);\n                if (current_error < run_best_error) {\n                    run_best_error = current_error;\n                    run_best_a = a;\n                    run_best_b = b;\n                }\n            }\n        }\n\n        // Update global best\n        if (run_best_error < global_best_error) {\n            global_best_error = run_best_error;\n            global_best_a = run_best_a;\n            global_best_b = run_best_b;\n        }\n\n        // Perturbation for next run\n        a = run_best_a;\n        b = run_best_b;\n        const int PERTURB_STRENGTH = 10;\n        for (int k = 0; k < PERTURB_STRENGTH; ++k) {\n            make_random_move(a, b);\n        }\n    }\n\n    for (int i = 0; i < N_CONST; ++i) {\n        std::cout << global_best_a[i] << \" \" << global_best_b[i] << \"\\n\";\n    }\n    \n    return 0;\n}","ahc045":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <set>\n#include <map>\n#include <queue>\n#include <tuple>\n#include <chrono>\n\n// Start timer\nauto start_time = std::chrono::high_resolution_clock::now();\ndouble time_limit = 1.95; // seconds\n\nstruct City {\n    int id;\n    long long lx, rx, ly, ry;\n    long long cx, cy;\n};\n\n// Z-order curve (Morton code)\nuint64_t z_order(uint32_t x, uint32_t y) {\n    uint64_t z = 0;\n    x &= 0x7FFF; // Max coord is 10000, 15 bits are enough\n    y &= 0x7FFF;\n    for (int i = 0; i < 15; ++i) {\n        z |= (static_cast<uint64_t>(x) & (1u << i)) << (i + 1);\n        z |= (static_cast<uint64_t>(y) & (1u << i)) << i;\n    }\n    return z;\n}\n\nstruct DSU {\n    std::vector<int> parent;\n    DSU(int n) {\n        parent.resize(n);\n        std::iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int i) {\n        if (parent[i] == i)\n            return i;\n        return parent[i] = find(parent[i]);\n    }\n    void unite(int i, int j) {\n        int root_i = find(i);\n        int root_j = find(j);\n        if (root_i != root_j) {\n            parent[root_i] = root_j;\n        }\n    }\n};\n\n// Use expected squared distance for estimations\nlong double expected_dist_sq(const City& a, const City& b) {\n    long double w_a = a.rx - a.lx;\n    long double w_b = b.rx - b.lx;\n    long double h_a = a.ry - a.ly;\n    long double h_b = b.ry - b.ly;\n\n    long double var_x_a = w_a * w_a / 12.0;\n    long double var_x_b = w_b * w_b / 12.0;\n    long double var_y_a = h_a * h_a / 12.0;\n    long double var_y_b = h_b * h_b / 12.0;\n\n    long double mean_x_a = a.lx + w_a / 2.0;\n    long double mean_x_b = b.lx + w_b / 2.0;\n    long double mean_y_a = a.ly + h_a / 2.0;\n    long double mean_y_b = b.ly + h_b / 2.0;\n    \n    long double dx = mean_x_a - mean_x_b;\n    long double dy = mean_y_a - mean_y_b;\n    \n    return var_x_a + var_x_b + dx * dx + var_y_a + var_y_b + dy * dy;\n}\n\nstd::vector<std::pair<int, int>> do_query(const std::vector<int>& c) {\n    std::cout << \"? \" << c.size();\n    for (int city_id : c) {\n        std::cout << \" \" << city_id;\n    }\n    std::cout << std::endl;\n\n    std::vector<std::pair<int, int>> edges;\n    if (c.size() > 1) {\n        for (size_t i = 0; i < c.size() - 1; ++i) {\n            int u, v;\n            std::cin >> u >> v;\n            edges.emplace_back(u, v);\n        }\n    }\n    return edges;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    \n    std::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\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<City> cities(N);\n    for (int i = 0; i < N; ++i) {\n        cities[i].id = i;\n        std::cin >> cities[i].lx >> cities[i].rx >> cities[i].ly >> cities[i].ry;\n        cities[i].cx = (cities[i].lx + cities[i].rx) / 2;\n        cities[i].cy = (cities[i].ly + cities[i].ry) / 2;\n    }\n\n    // 1. Grouping\n    std::vector<int> city_indices(N);\n    std::iota(city_indices.begin(), city_indices.end(), 0);\n    std::sort(city_indices.begin(), city_indices.end(), [&](int a, int b) {\n        return z_order(cities[a].cx, cities[a].cy) < z_order(cities[b].cx, cities[b].cy);\n    });\n    \n    std::vector<std::vector<int>> groups(M);\n    int current_city_idx = 0;\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < G[i]; ++j) {\n            groups[i].push_back(city_indices[current_city_idx++]);\n        }\n    }\n    \n    // 2. Querying\n    int queries_left = Q;\n    DSU global_dsu(N);\n    std::vector<std::pair<int, int>> known_edges_per_group[M];\n    \n    // Phase 0: Initial queries for small groups\n    for(int k=0; k<M; ++k) {\n        if (queries_left > 0 && G[k] >= 2 && G[k] <= L) {\n            auto edges = do_query(groups[k]);\n            queries_left--;\n            for (const auto& edge : edges) {\n                known_edges_per_group[k].push_back(edge);\n                global_dsu.unite(edge.first, edge.second);\n            }\n        }\n    }\n\n    // Phase 1: Connectivity for large groups\n    std::vector<std::tuple<long double, int, int, int>> mst_edges_to_verify;\n    for (int k = 0; k < M; ++k) {\n        if (G[k] <= L) continue;\n        const auto& group_cities = groups[k];\n        std::vector<std::tuple<long double, int, int>> candidate_edges;\n        for (size_t i = 0; i < group_cities.size(); ++i) {\n            for (size_t j = i + 1; j < group_cities.size(); ++j) {\n                int u = group_cities[i];\n                int v = group_cities[j];\n                candidate_edges.emplace_back(expected_dist_sq(cities[u], cities[v]), u, v);\n            }\n        }\n        std::sort(candidate_edges.begin(), candidate_edges.end());\n\n        DSU mst_dsu(N);\n        for (const auto& [w, u, v] : candidate_edges) {\n            if (mst_dsu.find(u) != mst_dsu.find(v)) {\n                mst_dsu.unite(u, v);\n                mst_edges_to_verify.emplace_back(w, u, v, k);\n            }\n        }\n    }\n    std::sort(mst_edges_to_verify.begin(), mst_edges_to_verify.end());\n\n    for (const auto& [w, u, v, k] : mst_edges_to_verify) {\n        if (queries_left == 0) break;\n        auto now = std::chrono::high_resolution_clock::now();\n        if (std::chrono::duration<double>(now - start_time).count() > time_limit) break;\n\n        if (global_dsu.find(u) != global_dsu.find(v)) {\n            std::vector<int> query_cities;\n            query_cities.push_back(u);\n            query_cities.push_back(v);\n            \n            long long mid_x = (cities[u].cx + cities[v].cx) / 2;\n            long long mid_y = (cities[u].cy + cities[v].cy) / 2;\n            \n            std::vector<std::pair<long long, int>> dist_to_mid;\n            for (int city_id : groups[k]) {\n                if (city_id == u || city_id == v) continue;\n                long long dx = cities[city_id].cx - mid_x;\n                long long dy = cities[city_id].cy - mid_y;\n                dist_to_mid.push_back({dx * dx + dy * dy, city_id});\n            }\n            std::sort(dist_to_mid.begin(), dist_to_mid.end());\n            for (size_t i = 0; i < dist_to_mid.size() && query_cities.size() < (size_t)L; ++i) {\n                query_cities.push_back(dist_to_mid[i].second);\n            }\n\n            auto edges = do_query(query_cities);\n            queries_left--;\n            for (const auto& edge : edges) {\n                known_edges_per_group[k].push_back(edge);\n                global_dsu.unite(edge.first, edge.second);\n            }\n        }\n    }\n    \n    // Phase 2: Improvement for large groups\n    if (queries_left > 0) {\n        std::vector<std::tuple<long double, int, int, int>> improvement_candidates;\n        for (int k = 0; k < M; ++k) {\n            if (G[k] <= L) continue;\n\n            DSU group_dsu_known(N);\n            for(const auto& edge : known_edges_per_group[k]){\n                group_dsu_known.unite(edge.first, edge.second);\n            }\n\n            std::map<int, std::vector<int>> components;\n            for (int city_id : groups[k]) {\n                components[group_dsu_known.find(city_id)].push_back(city_id);\n            }\n\n            if (components.size() > 1) {\n                std::vector<std::tuple<long double, int, int>> component_edges;\n                auto it1 = components.begin();\n                while (it1 != components.end()) {\n                    auto it2 = std::next(it1);\n                    while (it2 != components.end()) {\n                        for (int c1 : it1->second) {\n                            for (int c2 : it2->second) {\n                                component_edges.emplace_back(expected_dist_sq(cities[c1], cities[c2]), c1, c2);\n                            }\n                        }\n                        it2++;\n                    }\n                    it1++;\n                }\n                std::sort(component_edges.begin(), component_edges.end());\n                \n                for (const auto& [w, c1, c2] : component_edges) {\n                    if (group_dsu_known.find(c1) != group_dsu_known.find(c2)) {\n                        group_dsu_known.unite(c1, c2);\n                        improvement_candidates.emplace_back(w, c1, c2, k);\n                    }\n                }\n            }\n        }\n        std::sort(improvement_candidates.rbegin(), improvement_candidates.rend()); \n\n        for (const auto& [w, u, v, k] : improvement_candidates) {\n            if (queries_left == 0) break;\n            auto now = std::chrono::high_resolution_clock::now();\n            if (std::chrono::duration<double>(now - start_time).count() > time_limit) break;\n\n            std::vector<int> query_cities;\n            query_cities.push_back(u);\n            query_cities.push_back(v);\n            \n            long long mid_x = (cities[u].cx + cities[v].cx) / 2;\n            long long mid_y = (cities[u].cy + cities[v].cy) / 2;\n            \n            std::vector<std::pair<long long, int>> dist_to_mid;\n            for (int city_id : groups[k]) {\n                if (city_id == u || city_id == v) continue;\n                long long dx = cities[city_id].cx - mid_x;\n                long long dy = cities[city_id].cy - mid_y;\n                dist_to_mid.push_back({dx * dx + dy * dy, city_id});\n            }\n            std::sort(dist_to_mid.begin(), dist_to_mid.end());\n            for (size_t i = 0; i < dist_to_mid.size() && query_cities.size() < (size_t)L; ++i) {\n                query_cities.push_back(dist_to_mid[i].second);\n            }\n            \n            auto edges = do_query(query_cities);\n            queries_left--;\n            for (const auto& edge : edges) {\n                known_edges_per_group[k].push_back(edge);\n            }\n        }\n    }\n\n\n    // 3. Output\n    std::cout << \"!\" << std::endl;\n    for (int k = 0; k < M; ++k) {\n        for (size_t i = 0; i < groups[k].size(); ++i) {\n            std::cout << groups[k][i] << (i == groups[k].size() - 1 ? \"\" : \" \");\n        }\n        std::cout << std::endl;\n\n        if (G[k] > 1) {\n            std::vector<std::pair<int, int>> final_edges;\n            DSU group_dsu(N);\n            \n            std::sort(known_edges_per_group[k].begin(), known_edges_per_group[k].end());\n            known_edges_per_group[k].erase(std::unique(known_edges_per_group[k].begin(), known_edges_per_group[k].end()), known_edges_per_group[k].end());\n\n            for (const auto& edge : known_edges_per_group[k]) {\n                if (group_dsu.find(edge.first) != group_dsu.find(edge.second)) {\n                    group_dsu.unite(edge.first, edge.second);\n                    final_edges.push_back(edge);\n                }\n            }\n\n            if ((int)final_edges.size() < G[k] - 1) {\n                std::map<int, std::vector<int>> components;\n                for (int city_id : groups[k]) {\n                    components[group_dsu.find(city_id)].push_back(city_id);\n                }\n\n                if (components.size() > 1) {\n                    std::vector<std::tuple<long double, int, int>> component_edges;\n                    auto it1 = components.begin();\n                    while (it1 != components.end()) {\n                        auto it2 = std::next(it1);\n                        while (it2 != components.end()) {\n                            for (int c1 : it1->second) {\n                                for (int c2 : it2->second) {\n                                    component_edges.emplace_back(expected_dist_sq(cities[c1], cities[c2]), c1, c2);\n                                }\n                            }\n                            it2++;\n                        }\n                        it1++;\n                    }\n                    std::sort(component_edges.begin(), component_edges.end());\n                    \n                    for (const auto& [w, c1, c2] : component_edges) {\n                        if (group_dsu.find(c1) != group_dsu.find(c2)) {\n                            group_dsu.unite(c1, c2);\n                            final_edges.emplace_back(c1, c2);\n                        }\n                        if ((int)final_edges.size() >= G[k] - 1) break;\n                    }\n                }\n            }\n\n            for (const auto& edge : final_edges) {\n                std::cout << edge.first << \" \" << edge.second << std::endl;\n            }\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <map>\n#include <set>\n#include <cmath>\n#include <algorithm>\n#include <tuple>\n\nusing namespace std;\n\nconst int N = 20;\nconst int M = 40;\nconst int K = 20; // Max blocks allowed\n\nstruct Pos {\n    int r, c;\n    bool operator<(const Pos& other) const { if (r != other.r) return r < other.r; return c < other.c; }\n    bool operator==(const Pos& other) const { return r == other.r && c == other.c; }\n};\n\nint manhattan_distance(const Pos& a, const Pos& b) { return abs(a.r - b.r) + abs(a.c - b.c); }\nbool is_valid(const Pos& p) { return p.r >= 0 && p.r < N && p.c >= 0 && p.c < N; }\n\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\nconst char dir_char[] = {'U', 'D', 'L', 'R'};\n\nstruct Action { char act, dir; };\n\nmap<Pos, int> dijkstra(const Pos& start, const set<Pos>& blocks) {\n    map<Pos, int> dist;\n    priority_queue<pair<int, Pos>, vector<pair<int, Pos>>, greater<pair<int, Pos>>> pq;\n    if (blocks.count(start)) return dist;\n    dist[start] = 0;\n    pq.push({0, start});\n    while (!pq.empty()) {\n        auto [cost, pos] = pq.top(); pq.pop();\n        if (cost > dist.at(pos)) continue;\n        for (int i = 0; i < 4; ++i) { // Move\n            Pos next_pos = {pos.r + dr[i], pos.c + dc[i]};\n            if (is_valid(next_pos) && !blocks.count(next_pos)) {\n                int next_cost = cost + 1;\n                if (!dist.count(next_pos) || next_cost < dist.at(next_pos)) {\n                    dist[next_pos] = next_cost; pq.push({next_cost, next_pos});\n                }\n            }\n        }\n        for (int i = 0; i < 4; ++i) { // Slide\n            Pos stop_pos = pos; Pos next_pos = {stop_pos.r + dr[i], stop_pos.c + dc[i]};\n            while (is_valid(next_pos) && !blocks.count(next_pos)) { stop_pos = next_pos; next_pos = {stop_pos.r + dr[i], stop_pos.c + dc[i]}; }\n            if (stop_pos == pos) continue;\n            int next_cost = cost + 1;\n            if (!dist.count(stop_pos) || next_cost < dist.at(stop_pos)) {\n                dist[stop_pos] = next_cost; pq.push({next_cost, stop_pos});\n            }\n        }\n    }\n    return dist;\n}\n\npair<int, vector<Action>> a_star_full(const Pos& start, const Pos& end, const set<Pos>& blocks) {\n    if (start == end) return {0, {}};\n    if (blocks.count(end)) return {1000000, {}};\n    map<Pos, int> dist; map<Pos, Action> parent_action; map<Pos, Pos> parent_pos;\n    priority_queue<pair<int, Pos>, vector<pair<int, Pos>>, greater<pair<int, Pos>>> pq;\n    dist[start] = 0; pq.push({manhattan_distance(start, end), start});\n    while (!pq.empty()) {\n        auto [est_cost_pq, pos] = pq.top(); pq.pop();\n        int cost = dist.at(pos);\n        if (dist.count(pos) && cost > dist.at(pos)) continue;\n        if (pos == end) {\n            vector<Action> actions; Pos curr = end;\n            while (!(curr == start)) { actions.push_back(parent_action.at(curr)); curr = parent_pos.at(curr); }\n            reverse(actions.begin(), actions.end()); return {cost, actions};\n        }\n        for (int i = 0; i < 4; ++i) { // Move\n            Pos next_pos = {pos.r + dr[i], pos.c + dc[i]};\n            if (is_valid(next_pos) && !blocks.count(next_pos)) {\n                int next_cost = cost + 1;\n                if (!dist.count(next_pos) || next_cost < dist.at(next_pos)) {\n                    dist[next_pos] = next_cost; parent_pos[next_pos] = pos; parent_action[next_pos] = {'M', dir_char[i]};\n                    pq.push({next_cost + manhattan_distance(next_pos, end), next_pos});\n                }\n            }\n        }\n        for (int i = 0; i < 4; ++i) { // Slide\n            Pos stop_pos = pos; Pos next_pos = {stop_pos.r + dr[i], stop_pos.c + dc[i]};\n            while (is_valid(next_pos) && !blocks.count(next_pos)) { stop_pos = next_pos; next_pos = {stop_pos.r + dr[i], stop_pos.c + dc[i]}; }\n            if (stop_pos == pos) continue;\n            int next_cost = cost + 1;\n            if (!dist.count(stop_pos) || next_cost < dist.at(stop_pos)) {\n                dist[stop_pos] = next_cost; parent_pos[stop_pos] = pos; parent_action[stop_pos] = {'S', dir_char[i]};\n                pq.push({next_cost + manhattan_distance(stop_pos, end), stop_pos});\n            }\n        }\n    }\n    return {1000000, {}};\n}\n\nPos find_block_to_evict(const set<Pos>& current_blocks, int future_target_idx, const vector<Pos>& all_targets) {\n    Pos to_evict; long long max_score = -1;\n    for (const auto& b : current_blocks) {\n        long long current_score = 0;\n        for (size_t i = future_target_idx; i < all_targets.size(); ++i) current_score += manhattan_distance(b, all_targets[i]);\n        if (current_score > max_score) { max_score = current_score; to_evict = b; }\n    }\n    return to_evict;\n}\n\nstruct Plan {\n    char type; int cost; set<Pos> final_blocks;\n    vector<Action> path_actions;\n    Pos alter_block, alter_adj;\n};\n\nint main() {\n    ios_base::sync_with_stdio(false); cin.tie(NULL);\n    int N_in, M_in; cin >> N_in >> M_in;\n    vector<Pos> targets(M); for (int i = 0; i < M; ++i) cin >> targets[i].r >> targets[i].c;\n\n    Pos current_pos = targets[0];\n    set<Pos> blocks;\n    vector<Action> total_actions;\n\n    for (int k = 0; k < M - 1; ++k) {\n        Pos start_node = current_pos; Pos end_node = targets[k + 1];\n\n        vector<Plan> best_plans; int min_cost = 1000000;\n\n        // Baseline plan\n        auto [cost, path] = a_star_full(start_node, end_node, blocks);\n        if (cost < min_cost) { min_cost = cost; best_plans.clear(); }\n        if (cost == min_cost) best_plans.push_back({'B', cost, blocks, path, {}, {}});\n\n        auto dist_from_start = dijkstra(start_node, blocks);\n        map<Pos, int> dist_from_end_for_penalty;\n        if (blocks.size() >= K) dist_from_end_for_penalty = dijkstra(end_node, blocks);\n\n        set<Pos> cand_stop_points;\n        cand_stop_points.insert(end_node);\n        cand_stop_points.insert({start_node.r, end_node.c});\n        cand_stop_points.insert({end_node.r, start_node.c});\n        if (k + 2 < M) {\n            Pos next_target = targets[k+2];\n            cand_stop_points.insert(next_target);\n            cand_stop_points.insert({end_node.r, next_target.c});\n            cand_stop_points.insert({next_target.r, end_node.c});\n        }\n        \n        set<Pos> cand_add_blocks;\n        for(const auto& sp : cand_stop_points) {\n            for(int i=0; i<4; ++i) {\n                Pos b = {sp.r + dr[i], sp.c + dc[i]};\n                if (is_valid(b)) cand_add_blocks.insert(b);\n            }\n        }\n\n        // Add-1 plans\n        for (const auto& b : cand_add_blocks) {\n            if (blocks.count(b)) continue;\n            set<Pos> next_blocks = blocks; next_blocks.insert(b);\n            auto dist_to_end = dijkstra(end_node, next_blocks);\n            for (int i = 0; i < 4; ++i) {\n                Pos adj_b = {b.r - dr[i], b.c - dc[i]};\n                if (is_valid(adj_b) && !blocks.count(adj_b) && dist_from_start.count(adj_b) && dist_to_end.count(adj_b)) {\n                    int current_cost = dist_from_start.at(adj_b) + 1 + dist_to_end.at(adj_b);\n                    int penalized_cost = current_cost;\n                    if (blocks.size() >= K) {\n                        Pos to_evict = find_block_to_evict(next_blocks, k + 2, targets);\n                        int eviction_penalty = 1000000;\n                        for (int i_ev = 0; i_ev < 4; ++i_ev) {\n                            Pos adj_ev = {to_evict.r - dr[i_ev], to_evict.c - dc[i_ev]};\n                            if (is_valid(adj_ev) && adj_ev != b && dist_from_end_for_penalty.count(adj_ev)) {\n                                eviction_penalty = min(eviction_penalty, dist_from_end_for_penalty.at(adj_ev) + 1);\n                            }\n                        }\n                        penalized_cost += (eviction_penalty < 1000000) ? eviction_penalty : N*N;\n                    }\n                    if (penalized_cost < min_cost) { min_cost = penalized_cost; best_plans.clear(); }\n                    if (penalized_cost == min_cost) best_plans.push_back({'A', current_cost, next_blocks, {}, b, adj_b});\n                }\n            }\n        }\n\n        // Remove-1 plans\n        for (const auto& b : blocks) {\n            set<Pos> next_blocks = blocks; next_blocks.erase(b);\n            auto dist_to_end = dijkstra(end_node, next_blocks);\n            for (int i = 0; i < 4; ++i) {\n                Pos adj_b = {b.r - dr[i], b.c - dc[i]};\n                if (is_valid(adj_b) && !blocks.count(adj_b) && dist_from_start.count(adj_b) && dist_to_end.count(adj_b)) {\n                    int rem_cost = dist_from_start.at(adj_b) + 1 + dist_to_end.at(adj_b);\n                    if (rem_cost < min_cost) { min_cost = rem_cost; best_plans.clear(); }\n                    if (rem_cost == min_cost) best_plans.push_back({'R', rem_cost, next_blocks, {}, b, adj_b});\n                }\n            }\n        }\n        \n        Plan final_plan = best_plans[0];\n        if (best_plans.size() > 1 && k + 2 < M) {\n            int best_future_cost = 1000000;\n            Pos next_end_node = targets[k + 2];\n            for (const auto& plan : best_plans) {\n                auto [future_cost, _] = a_star_full(end_node, next_end_node, plan.final_blocks);\n                if (future_cost < best_future_cost) { best_future_cost = future_cost; final_plan = plan; }\n            }\n        }\n        \n        if (final_plan.type == 'B') {\n            total_actions.insert(total_actions.end(), final_plan.path_actions.begin(), final_plan.path_actions.end());\n        } else {\n            auto [c1, p1] = a_star_full(start_node, final_plan.alter_adj, blocks);\n            total_actions.insert(total_actions.end(), p1.begin(), p1.end());\n            char alter_dir = ' ';\n            for (int j=0; j<4; ++j) if(final_plan.alter_block.r==final_plan.alter_adj.r+dr[j] && final_plan.alter_block.c==final_plan.alter_adj.c+dc[j]) alter_dir=dir_char[j];\n            total_actions.push_back({'A', alter_dir});\n            auto [c2, p2] = a_star_full(final_plan.alter_adj, end_node, final_plan.final_blocks);\n            total_actions.insert(total_actions.end(), p2.begin(), p2.end());\n        }\n        blocks = final_plan.final_blocks;\n        current_pos = end_node;\n\n        if (blocks.size() > K) {\n            Pos to_evict = find_block_to_evict(blocks, k + 2, targets);\n            Pos adj_to_evict; int min_dist = 1000000;\n            auto dist_from_curr = dijkstra(current_pos, blocks);\n            for (int i = 0; i < 4; ++i) {\n                Pos adj_b = {to_evict.r - dr[i], to_evict.c - dc[i]};\n                if (is_valid(adj_b) && !blocks.count(adj_b) && dist_from_curr.count(adj_b)) {\n                    if (dist_from_curr.at(adj_b) < min_dist) { min_dist = dist_from_curr.at(adj_b); adj_to_evict = adj_b; }\n                }\n            }\n            if (min_dist < 1000000) {\n                auto [c, p] = a_star_full(current_pos, adj_to_evict, blocks);\n                total_actions.insert(total_actions.end(), p.begin(), p.end());\n                current_pos = adj_to_evict;\n                char alter_dir = ' ';\n                for(int j=0; j<4; ++j) if(to_evict.r==current_pos.r+dr[j] && to_evict.c==current_pos.c+dc[j]) alter_dir=dir_char[j];\n                total_actions.push_back({'A', alter_dir});\n                blocks.erase(to_evict);\n            }\n        }\n    }\n\n    for (const auto& action : total_actions) cout << action.act << \" \" << action.dir << \"\\n\";\n    return 0;\n}"}}}